从零开始领域驱动-划分代码层次

Updated on with 312 views and 0 comments

开头说两句

Java基础Demo 站: https://www.javastudy.cloud
Java中高级开发博客: https://www.lixiang.red
Java学习公众号: java技术大本营
java_subscribe

项目背景

不知从何时开始,业内慢慢开始有了领域驱动的声音,刚好公司有些新项目要做,就借着DDD的浪潮,新项目,新技术选型

学习调研时遇到的问题

国内关于DDD的书和视频真心不怎么多,听说阿里盒马对DDD有着深入的使用,但也没什么资料流出,网上为数不多的两本书,一本红皮书,像天书一样,啃了几天,啃不下去,还有本稍好一点,也不是太好理解,大致翻了一遍后还是有点蒙,还是动手写代码吧,边写边思考,边改进, 在学习过程中主要有以下思考阶段

  1. 在实际编码中,如果代码如何分层
  2. DDD是以业务为主,那么如果去划分业务上下界
  3. DDD提倡了一种专家和开发人员都能理解的语言,那么如何去把这种新语言沉淀下来
    等等...

对领域驱动的理解

有句笑谈是,没有加个中间表解决不了的业务,如果有,就加两张. 虽说领域驱动是以业务为主,但是落叶归根也是要建库建表的.那么我们新引入的领域驱动的概念就是加在数据库表和Manage层的中间件.
以小刀现在负责的用户模块为例,我们先业务建模,小刀是按经典的三户模型进行设计的:客户-用户-账户.

  1. 客户
    是指自然人,只要点了我们系统的,就是我们的客户,不管是看了一眼还是点了一下.
  2. 用户
    指不仅仅看了我们的系统,还和我们系统产生了业务数据
  3. 账户
    原指金额行业中用来为用户销账的账户,在我们系统中,小刀修改成通行证的概念.即,一个通行证,可以对应多个用户.
    举个例子就是:小刀我是一个客户,我手里面两个通行证,一个是公司APP的通行证,一个是公司后台管理系统的通行证. APP通行证下面有我的微信账号,手机账号. 管理系统通行证下面有A管理系统,B管理系统的权限这样
    那么按照这三户的业务,他们实际上是属于同一个领域,但是有三张数据库表. 对领域驱动的理解总结起来就是: 一个领域对应多张表. 外层(service , manager) 从dao层拿了数据之后,业务都要通过领域层来处理.

领域驱动对应的代码分层

为什么修改代码分层呢,那肯定是以前的不好才会改,那以前的怎么不好了呢,我们来一起看下以前的代码分层

经典的代码分层结构

以前的经典分层是 controller 调用 manager/service , 然后service调用dao , dao层去数据库取数据,然后service里面对数据进行业务加工,然后返回给controller , controller 给包一个BaseResponse之类的,加上状态码,信息之类的然后返回给调用方.
这样写也没什么不好的, 但有时候逻辑写的时候清楚,过段时间回来再看就无从下手了,最主要的原因是代码没有根着业务走,只是拼出了业务想要的数据而已

新的代码分层结构

其实新也新不到哪去,下面这个分层结构是小刀结合看的书自己琢磨出来的,有不全之处,欢迎大家一起来讨论
image.png
如上图所示,其实这里已经欠下了技术债(passport,account概念混乱了),但是代码一期已经上线了,jar包也打出去了,不好再更改了.

DAO层

这层和以前代码一样,采用Mybatis实现的,只不过小刀这里用的是mybatis新的provider方式,没有用xml去写sql,这里其实有点小纠结,就是 redis/缓存 算不算DAO层的范围.因为我们也是从redis中去做数据的存取.考量再三还是没有把redis归到DAO层,而是归到了领域层里面,因为redis里面都是业务数据

domain层

这一层是重点了,在这一层抽象出了四个主要的概念

  1. 领域配置对象: PassportConfig
    这里从apollo上获取一些项目业务配置信息
  2. 领域规则对象: PassportSpec
    这里面主要是对参数,验证码,节点值做检验,业务可以进行的,返回 true/false ,业务不能进行的,就抛出 RuntimeException
  3. 领域缓存对象: PassportRedis
    如名,对redis的操作和存取
  4. 领域充血对象:AccountRich(现在想应该是PassportRich)
    这里面封装了以上三个对象来进行业务操作

manage层

在这一层,如上图所示,每个方法都是大体这几步

  1. 通过mapper从数据库取出业务实体对象
  2. 把业务实体对象做为根传入充血对象
  3. 对充血对象进行各种业务操作
  4. 最后调用 2dto方法,返回一个值对象给调用方

最后说两句

领域驱动这块小刀还在不停的实践中,大家有什么想法和小刀一起讨论的可以加小刀微信: best396975802


标题:从零开始领域驱动-划分代码层次
作者:xiaodaojava
地址:https://www.lixiang.red/articles/2019/07/23/1563896973689.html

charset="utf-8">