代码结构
DDD并没有给出标准的代码模型,不同的人可能会有不同理解。
按DDD分层架构的分层职责定义,在代码模型里分别为用户接口层、应用层、领域层和基础层,建立了 interfaces、application、domain 和 infrastructure 四个一级目录。
1 DDD分层架构
1.1 分层架构的基本原则
每层只与位于其下方的层发生耦合。
1.2 分层架构的分类
严格分层架构(Strict Layers Architecture)
某层只能与其直接下层耦合,即我的奴隶的奴隶,不是我的奴隶。
松散分层架构(Relaxed Layers Architecture)
允许任意上层与任意下层耦合。由于用户接口层和应用服务通常需要与基础设施打交道,许多系统都是该架构。
较低层有时也可与较高层耦合,但只限于采用观察者 (Observer)模式或者调停者(Mediator)模式场景。
较低层绝不能直接访问较高层。例如,在使用调停者模式时,较高层可能实现了较低层的接口,然后将实现对象作为参数传递到较低层。当较低层调用该实现时, 它并不知道实现出自何处。
1.3 分层架构演进
1.3.1 传统四层架构
将领域模型和业务逻辑分离出来,并减少对基础设施、用户界面甚至应用层逻辑的依赖,因为它们不属业务逻辑。将一个夏杂的系统分为不同的层,每层都应该具有良好的内聚性,并且只依赖于比其自身更低的层。
传统分层架构的基础设施层位于底层,持久化和消息机制便位于该层。
这里的消息包含
MQ消息
SMTP
文本消息(SMS)
可将基础设施层中所有组件看作应用程序的低层服务,较高层与该层发生耦合以复用技术基础设施。即便如此,依然应避免核心的领域模型对象与基础设施层直接耦合。
1.3.2 改良版四层架构
传统架构的缺陷
DDD初创开发团队发现,将基础设施层放在最底层存在缺点,比如此时领域层中的一些技术实现就很困难:
- 违背分层架构的基本原则
- 难以编写测试用例
何解?
使用依赖反转设计原则:低层服务(如基础设施层)应依赖高层组件(比如用户界面层、应用层和领域层)所提供的接口。
应用依赖反转原则
- 依赖反转原则后的分层方式:基础设施层在最上方,可实现所有其他层中定义的接口
- 依赖反转原则真的可以支持所有层吗?
有人认为依赖反转原则中只存在两层:最上方和最下方,上层实现下层定义的抽象接口。因此上图的基础设施层将位于最上方,而用户接口层、应用层和领域层应作同层且都位于下方。对此大家可保留自己意见。
2 各层职责
2.1 Interfaces(用户接口层)
一般包括用户接口、Web 服务等。
只处理用户显示和用户请求,不应包含领域或业务逻辑。
有人认为,既然用户接口需验证用户输入,就无可避免应该包含业务逻辑。事实上,用户接口所进行的验证和对领域模型的验证不同:对那些粗制滥造且只面向领域模型的验证行为,应该予以限制。
如果用户接口使用了领域模型中的对象,那么此时领域对象仅限于数据渲染展现。在采用这种方式时,可使用展现模型对用户接口与领域对象进行解耦。
由于用户可能是人,也可能是其他系统,有时用户接口层将采用开放主机服务的方式向外提供API。
用户接口层是应用层的直接用户。
用户接口层在于前后端调用的适配。若你的微服务要提供服务给很多外部应用,而对每个外部应用的入参出参都不同,你不可能开发一堆一对一的应用服务,这时Facade接口就起到了很好的作用,包括DO和DTO对象的组装和转换。
由于主要负责接入各种终端,所以该层有人也叫接入层。
实际开发中,我们都会感受到该层依附于应用层存在。随前后端分离,Restful API 流行,对简单的系统来说该层越来越弱化。对于有终端接入的系统来说,该层并不简单,需要处理各种协议适配:XMPP、websocket、MQTT 等。
复杂度不高时,我们往往把该层和应用层合并部署,主要凭开发经验和理解程度来决定。
存放用户接口层与前端交互、展现数据相关的代码。
前端应用通过这层接口,向应用服务获取展现所需的数据。
该层主要用来处理用户发送的Restful请求,解析用户输入的配置文件,并将数据传递给应用层。
数据的组装、数据传输格式以及Facade接口等代码都会放在这一层目录里。
封装应用服务和对外暴露接口。
特点
- 关心视图和对外的服务,Restful、页面渲染、websocket、XMPP 连接等
- 如果没有多种用户端接入方式,可以和应用层合并
- 对应到分布式系统中的网关、BFF、前台等概念
- 只产生接入异常,例如数据校验,对应 HTTP 状态码 400、415 等
- 一个应用可以有多个接入层
- 接入层做和业务规则无关的 bean validation 验证
- 准单体系统下,按照连接方式分包
该层指的是服务端用于适配端侧的部分,而非端侧本身。因为该层本就依赖应用层,无人使用接口在这里做依赖倒置,所有又被称作主动适配。