1.0 DDD是什么

全称:Domain-driven design, 领域驱动设计
一句话概括:DDD是一种指导软件架构的理论与方法。DDD提出了一些概念,并提供了一些架构方法来让这些概念落地为软件。

2.0 演变历史

| |

二层软件架构(90代以前)

|

三层软件架构(90年代)

|

DDD出现(2004年)

|

DDD兴起(2010年后)

| | —- | —- | —- | —- | —- | | 架构 | image.png | image.png | image.png | 微服务兴起与流行 | | 代表人物 | ~ | Martin Fowler
image.png
现任思特沃克公司首席科学家
马丁·福勒先生是当今世界软件开发领域最具影响力的5位大师之一 | Eric Evans
image.png | Martin Flower (没错又是他)
提出并倡导微服务的概念 | | 特性 | 特定:本地应用,单机软件, Client/Server | Browser/Server | 富含业务知识,流程,规则,模型 | |

3.0 DDD概念

一图胜千言

image.png

概念解释

名称 解释 备注
领域 百科对领域的解释:“领域具体指一种特定的范围或区域。
在DDD中,领域就是一个业务范围,具有一个业务边界,范围越大,则领域越大
在该业务范围里,解决对应业务问题,所以:领域就是一个业务问题域或问题空间
子域 一个业务问题域或问题空间的划分有粒度与范围之说,如果粒度较小,则一个大的问题域可以拆分为多个小问题域,所以一个小的问题域表示一个子域
统一语言 一个领域的软件生命周期里,需要统一语言,各个角色都要达成一致,才好交流
限界上下文 限界就是领域或子域的边界,而上下文则是语义环境。所以由于限定的是领域或子域,所以这个边界可大可小(同领域的边界)
划好一个边界后,在该边界内则成为一个上下文,在该上下文用统一语义交流
核心域 公司或团队资源应该重点投入的子域,也就是该子域里的业务价值最大
通用域 被多个子域使用的通用功能子域是通用域
支撑域 既不包含决定产品和公司核心竞争力的功能,也不包含通用功能的子域,但是必要的功能,它就是支撑域
实体 具有唯一标识的对象,同时具有业务属性和业务行为(业务知识) 关注唯一标识
一般与DB里的DO实体有一定的映射,部分字段对应或一一对应
值对象 通过对象属性值来识别的对象,它将多个相关属性组合为一个概念整体 不关注唯一标识
关注多个属性
聚合 业务和逻辑紧密关联的实体和值对象组合而成的,是一个逻辑上的概念,通过聚合根来体现聚合的概念 关注一个整体
聚合根 聚合根是主要的业务逻辑载体,聚合根也称为根实体,它不仅是实体,还是聚合的管理者
领域事件 表示领域中发生的事件,即一个业务动作完成后,产生一个事件 多用于业务流程解耦场景(一个业务用例需要操作多不同域的聚合根)
领域服务 有些业务逻辑并不适合于放在聚合根上,比如涉及到外部数据交换,中间临时数据获取(依赖远程服务), 用领域服务来协调聚合里多个实体来完成一段业务逻辑。
在DDD中,ApplicationService和DomainService是两个很不一样的概念,前者是必须有的DDD组件,而后者只是一种妥协的结果,因此程序中的DomainService应该越少越好。
理论上相关业务逻辑都应该在聚合根里直接完成,但是涉及到外部数据交换,无法在聚合根里,所以需要单独通过DomainService来协助
资源库(Repository) 领域对象的统一数据层接口,持久化聚合根,查询实体,值对象等
工厂 创建聚合根的地方,强化对象的创建概念
命令 写操作,外部向领域模型发起的一次命令操作(更改状态)
查询 读操作, 外部向领域模型发起一次读操作

如何画领域模型图

1) 领域范围:可以用圆形、椭圆形、矩形、不规则的椭圆形都可
2) 用实线隔开不同的限界上下文
3) 用虚线分隔不同的子域
4) 子域里画聚合根、实体,值对象

场景A:大的限界上下文包含多个子域(业务域范围划分粒度较大)

image.png

场景B:一个子域里按小粒度拆分多个限界上下文(复杂业务)

image.png

场景C:一个子域代表一个限界上下文(最佳实践)

子域的划分粒度基本合适

4.概念落地

核心是:把DDD里的概念转换为业务知识,围绕业务知识设计系统
业界一般做法分为:战略设计与战术设计

战略设计

产出:领域名词,领域事件,命令(基于事件风暴)
产出:领域模型图,子域与限界上下文 (1、根据相关性做归类。 2、根据团队粒度做裁剪、根据技术特点做裁剪)

战术设计

提炼和定义出领域模型和之间的关系、将战略设计阶段的产出通过DDD领域概念进行承接并细化数据和行为

通过分层模式作为顶层架构规范

DDD分层架构 整洁架构(洋葱架构) 六边形架构(端口与适配器架构)
架构模式 image.png image.png image.png
提出人 Eric Evans
2004年
Robert C. Martin(鲍勃大叔)
2012年 《整洁架构之道》作者 书中提出的整洁架构
2005年库克伯恩 (Alistair Cockburn)首次提出
2014年 出版《实现领域驱动设计》作者
Vaughn Vernon(沃恩.弗农)应用到了DDD中

3种模式其核心都是关注应用层与领域层,它的作用就是将核心业务逻辑与外部应用、基础资源进行隔离。
红色框内部主要实现核心业务逻辑,但核心业务逻辑也是有差异的,有的业务逻辑属于领域模型的能力,有的则属于面向用户的用例和流程编排能力。按照这种功能的差异,在这三种架构中划分了应用层和领域层,来承担不同的业务逻辑。

各层职责说明

名称 职责 备注
用户接口层 用户接口层负责向用户显示信息和解释用户指令。这里的用户可能是:用户、程序、自动化测试和批处理脚本等等。 很薄,允许有简单的参数校验
应用层 主要面向用例和流程相关的操作,可以协调多个聚合的服务和领域对象完成服务编排和组合,协作完成业务操作。
应用服务还可以进行安全认证、权限校验、事务控制、发送或订阅领域事件等。
领域层 领域层的作用是实现核心业务逻辑,通过各种校验手段保证业务的正确性。领域层主要体现领域模型的业务能力,它用来表达业务概念、业务状态和业务规则。领域层包含聚合根、实体、值对象、领域服务等领域模型中的领域对象。领域模型的业务逻辑主要是由实体和领域服务来实现的,其中实体会采用富含业务知识(行为)的模型来实现所有与之相关的业务功能。其次,实体和领域服务在实现业务逻辑上不是同级的,当领域中的某些功能,单一实体(或者值对象)不能实现时,则需要领域服务,它可以组合聚合内的多个实体(或者值对象),实现复杂的业务逻辑
基础设施层 提供通用的技术和基础服务,包括第三方工具、驱动、消息中间件、网关、文件、缓存以及数据库等。比较常见的功能还是提供数据库持久化。

分层架构原则

架构根据耦合的紧密程度又可以分为两种:严格分层架构和松散分层架构
在《实现领域驱动设计》一书中,DDD分层架构有一个重要的原则:每层只能与位于其下方的层发生耦合(严格分层)。
所以:我们建议采用严格分层架构,不允许跨层调用

通过分层后的代码架构作为开发规范

image.png

DDD编程范式

几种特殊的对象与数据转换

|

Command Query Event DTO
语意 ”希望“能触发的操作 各种条件的查询 已经发生过的事情 DTO对象只是数据容器,只是为了和外部交互,所以本身不包含任何逻辑,只是贫血对象,可细化为CommandDTO,QueryDTO
读/写 只读 通常是写 根据场景,可以是写DTO请求,读DTO请求
返回值 DTO 或 Boolean DTO 或 Collection Void

image.png
注:上图来自文章,DTO转换采用了Assembler命名,我们这边采用的仍然是Converter命名

写场景

image.png
示例:
image.png

读场景

image.png

5.参考资料

https://insights.thoughtworks.cn/backend-development-ddd/
这篇文章多读几次都不过分