《小型支付商城系统》学习记录
1. MVC框架
2. DDD思想
3. MVC —> DDD重构
3.1 为什么要重构呢?
MVC旧工程随着业务的扩展,项目在不断地迭代更新,整个项目越来越庞大,业务越来越复杂,导致了MVC工程的腐化严重,迭代成本太高。
所以,希望借助DDD的设计思想,将MVC的工程重构,以便改善MVC工程的现状。
3.2 详解MVC工程的腐化
在普通的MVC中,一般主要包括三个部分:DAO、Domain、Service。这里的domain一般称为贫血对象,即只有对象没有逻辑,真正的逻辑是在Service中实现的,可能包括:po、vo等对象。这样的结构可能存在以下问题:“裤子乱穿”:当第一个对象定义好po、vo对象之后,另一个对象想使用时,发现已有的po、vo能够满足使用需求,就直接拿来使用。又一个对象想使用时,发现现存的po、vo基本可以满足需求,但是需要在此基础上进行适当扩展。别的对象想要调用时,也是同样的方式,这样随着对象的逐渐增多,就会导致交叉调用越来越混乱,po、vo对象也越来越复杂。就像是一条裤子,当第一个人做好之后,后边的人会将裤子拿来穿,但是发现不合适,就会进行加肥、加大,下一个人来穿,再进行加一些别的东西,这样就导致了这条裤子最后变得非常复杂。除此之外,在Service中,也会出现平行调用的情况,比如说某一个Service对象在实现业务逻辑时,发现别的Service已经实现该方法了,那么就直接将这个Service拿过来使用。并且,在Service中也不会区分业务功能和基础功能,比如说就是业务功能的Service会出现平行调用,同样比如说一些通用的功能如MQ消息、配置中心、缓存服务等,也会平行调用。这样就会使得整个结构非常混乱,在后期迭代更新、业务扩展时较为复杂。这样的工程架构对于小型的简单项目来说是适用的,开发速度较快,实现简单。但是对于长周期发展的项目来说,就会让项目后期的维护成本越来越高。
而DDD架构下,将domain这一层定义为充血模型,这里不仅仅是创建对象,还存在一些业务实现以及仓储逻辑。在这样的充血模型下,每个包和每个包之间是不存在任何关系的,是互相解耦的,没有任何依赖关系。并且,即使在初始阶段,某一个包下的功能另一个包下的功能很相似,也会去重新实现一遍,因为即使现阶段是相似的,但是随着业务功能的扩展以及后期的迭代更新,可能会不断地改变。所以,在domain充血模型下,是不存在平行调用的。
3.3 DDD思想下的分层结构
-
应用封装 - app: 这是应用启动和配置的第一层,如一些 aop 切面或者 config 配置,以及打包镜像都是在这一层处理。你可以把它理解为专门为了启动服务而存在的。
-
接口定义 - api:因为微服务中调用的 RPC 需要外提供接口的描述信息,也就是调用方在使用的时候,需要引入 Jar 包,让调用方好能依赖接口的定义。
-
领域封装 - trigger: 触发器层,一般也叫做 adapter 适配器层。用于提供接口服务,消息接收,任务执行等。所以对于这样的操作,这里把它做触发器层。
-
领域编排【可选】 - case: 领域编排层,一般对于较大且复杂的的项目,为了更好的防腐和提供通用的服务,一般会添加 case/application 层,用于对 domain 领域的逻辑进行封装组合处理。但对于一些小项目来说,完全可以去掉这一层。少量一层对象转换,代码的维护成本会降低很多。
-
领域封装 - domain: 领域模块层,是一个非常重要的模块。无论怎样做DDD的分层架构,domain 都是必须存在的。在这一层中会有一个细分的领域服务,在每个服务包含各自【模型、仓库、服务】这样3部分。
-
包含服务 - infrastructure: 基础层依赖于 domain 领域,因为存在对 domain 层定义的一些业务操作需要在这里实现。这是依赖倒转的一种设计方式。所有的仓库、接口、事件消息,都可以通过此处定义的方式进行调用。
-
外部接入 - gateway: 对于外部接口的调用,也可以根据基础层定义一条 gateway 网关来进行 RPC/HTTP 等类请求的接入。
3.4 DDD分层调用链路
图中的下方是整个链路的调用关系。
3.5 设计模式的重要性
仅有DDD的设计思想是远远不够的,是不能提升代码质量的,想要提升代码质量必须合理使用设计模式再结合DDD的设计思想。
4. 需求PRD
需求,一般由产品给出,交由研发进行实现。