DDD 中关于应用架构的那些事


DDD 中关于应用架构的那些事

文章插图
对领域驱动设计中关键的一些概念,大家有了更为深入的认识是不够的,在具体实践中我们还会面临诸如代码如何分层、不同上下文之间如何集成,以及某些时候还会用到CQRS 。本文就来补齐领域驱动设计中剩余的一些内容,希望能够助你更游刃有余地应对开发中遇到的各种问题 。
作者 | 于振
责编 | 韩楠
你好,今天我想与你聊聊DDD中的应用架构 。在过往我分享的几篇文章中,我们介绍了领域驱动设计中的一些基本概念,这里,再做一个简单的回顾 。
·《基础问题不简单|怎么合理使用值对象,让你的代码更清晰、更安全?》
·《不想只做Cruder?实体、聚合根,还不快去了解下》
·《如何通过仓储,对实体进行持久化处理?》
·《实体表达力不够?那你应该试试领域服务》
·《如何使用工厂,进一步解耦领域对象的职责》
·《领域模型细节太多不便使用?那就加个应用服务吧》
·《DDD在Go中如何落地|如何在业务中使用领域事件?》
使用值对象和实体帮助我们构建了具有丰富行为的领域模型,实体创建出来后需要通过仓储进行持久化,如果领域模型跟数据模型存在差异,就还需要通过 Converter 进行转换,以及通过 Snapshot 对实体进行追踪 。
DDD 中关于应用架构的那些事

文章插图
如果某些行为不适合放到某个实体上,就需要使用领域服务,同时,为了一定程度地防止领域服务的滥用,我们规定领域服务在命名上必须有一个动词 。
为了解耦领域对象的创建过程和其自身行为,我们又介绍了工厂方法 。
对于外部用户来说,领域之内的各个对象描述的,都是细粒度的领域概念,为了方便外部调用,同时屏蔽领域对象的具体细节,就又有了应用服务 。
最后,通过领域事件,进一步解耦了不同上下文之间的依赖,即使在同一边界之内的不同的聚合根,也可以实现数据的最终一致性 。
至此,大家应该对领域驱动设计中关键的一些概念,有了更为深入的认识 。但仅仅是这些应该是还不够的,在具体实践中,我们还面临着诸如代码如何分层、不同上下文之间如何集成,以及某些时候还会用到CQRS 。
在这篇文章中,我们就来补齐领域驱动设计中剩余的一些内容 。
首先,我们从代码的分层开始说起 。
01? DDD的分层架构
分层架构作为一种历史悠久的架构模式,在很多的场景中都得到了应用 。
大家比较熟悉的应该就是 MVC 对应用三层架构的拆分 。MVC 这种分层是自上而下的 。
随着业务越来越复杂,人们逐渐发现,MVC 架构在应对复杂的业务问题时会显得力不从心 。
于是,后面逐渐演化出了六边形架构、洋葱架构、整洁架构等架构模式 。这几种架构也是一种分层架构,但这种分层不是由上而下的,而是由内而外的 。
我们以洋葱架构为例:
DDD 中关于应用架构的那些事

文章插图
可以看到,最关键的是中心的领域模型,它包括了所有的应用逻辑与规则 。在这一层中不会直接引用技术实现,这样就能够确保在技术层面的改动不会影响到领域核心 。
在领域层之外又包裹了领域服务层、应用服务层,而具体的技术实现则是被置于最外层的 。
这种架构的好处就在于,它屏蔽掉了应用程序在UI层、DB层,以及各种中间件层的本质区别,所有的这些外部资源都被抽象成了对系统的输入输出,然后我们就能够以一致的方式来处理不同的请求类型,并且,在与实际运行的设备和数据库相隔离的情况下,也可以先行开发和测试 。
在 DDD 的技术实现中,就用到了这种分层方式 。
下图是 Eric Evans 在其经典著作《领域驱动设计》中给出的一个典型的 DDD 系统所采用的分层架构:
DDD 中关于应用架构的那些事

文章插图
在上图中可以看到,整个架构划分成了四个层,各层所表示的含义及其职责描述如下:
1、用户接口层
这一层主要负责直接面向外部用户或者系统,接收外部输入,并返回结果 。
用户接口层是比较轻的一层,不含业务逻辑 。可以做一些简单的入参校验,也可以记录一下访问日志,对异常进行统一的处理 。同时,对返回值的封装也应当在这层完成 。
2、应用层


推荐阅读