1.0 DDD是什么
全称:Domain-driven design, 领域驱动设计
一句话概括:DDD是一种指导软件架构的理论与方法。DDD提出了一些概念,并提供了一些架构方法来让这些概念落地为软件。
2.0 演变历史
二层软件架构(90代以前)
三层软件架构(90年代)
DDD出现(2004年)
DDD兴起(2010年后)
|
| —- | —- | —- | —- | —- |
| 架构 | | | | 微服务兴起与流行 |
| 代表人物 | ~ | Martin Fowler
现任思特沃克公司首席科学家
马丁·福勒先生是当今世界软件开发领域最具影响力的5位大师之一 | Eric Evans
| Martin Flower (没错又是他)
提出并倡导微服务的概念 |
| 特性 | 特定:本地应用,单机软件, Client/Server | Browser/Server | 富含业务知识,流程,规则,模型 | |
3.0 DDD概念
一图胜千言
概念解释
名称 | 解释 | 备注 |
---|---|---|
领域 | 百科对领域的解释:“领域具体指一种特定的范围或区域。 在DDD中,领域就是一个业务范围,具有一个业务边界,范围越大,则领域越大 在该业务范围里,解决对应业务问题,所以:领域就是一个业务问题域或问题空间 |
|
子域 | 一个业务问题域或问题空间的划分有粒度与范围之说,如果粒度较小,则一个大的问题域可以拆分为多个小问题域,所以一个小的问题域表示一个子域 | |
统一语言 | 一个领域的软件生命周期里,需要统一语言,各个角色都要达成一致,才好交流 | |
限界上下文 | 限界就是领域或子域的边界,而上下文则是语义环境。所以由于限定的是领域或子域,所以这个边界可大可小(同领域的边界) 划好一个边界后,在该边界内则成为一个上下文,在该上下文用统一语义交流 |
|
核心域 | 公司或团队资源应该重点投入的子域,也就是该子域里的业务价值最大 | |
通用域 | 被多个子域使用的通用功能子域是通用域 | |
支撑域 | 既不包含决定产品和公司核心竞争力的功能,也不包含通用功能的子域,但是必要的功能,它就是支撑域 | |
实体 | 具有唯一标识的对象,同时具有业务属性和业务行为(业务知识) | 关注唯一标识 一般与DB里的DO实体有一定的映射,部分字段对应或一一对应 |
值对象 | 通过对象属性值来识别的对象,它将多个相关属性组合为一个概念整体 | 不关注唯一标识 关注多个属性 |
聚合 | 业务和逻辑紧密关联的实体和值对象组合而成的,是一个逻辑上的概念,通过聚合根来体现聚合的概念 | 关注一个整体 |
聚合根 | 聚合根是主要的业务逻辑载体,聚合根也称为根实体,它不仅是实体,还是聚合的管理者 | |
领域事件 | 表示领域中发生的事件,即一个业务动作完成后,产生一个事件 | 多用于业务流程解耦场景(一个业务用例需要操作多不同域的聚合根) |
领域服务 | 有些业务逻辑并不适合于放在聚合根上,比如涉及到外部数据交换,中间临时数据获取(依赖远程服务), 用领域服务来协调聚合里多个实体来完成一段业务逻辑。 在DDD中,ApplicationService和DomainService是两个很不一样的概念,前者是必须有的DDD组件,而后者只是一种妥协的结果,因此程序中的DomainService应该越少越好。 |
理论上相关业务逻辑都应该在聚合根里直接完成,但是涉及到外部数据交换,无法在聚合根里,所以需要单独通过DomainService来协助 |
资源库(Repository) | 领域对象的统一数据层接口,持久化聚合根,查询实体,值对象等 | |
工厂 | 创建聚合根的地方,强化对象的创建概念 | |
命令 | 写操作,外部向领域模型发起的一次命令操作(更改状态) | |
查询 | 读操作, 外部向领域模型发起一次读操作 |
如何画领域模型图
1) 领域范围:可以用圆形、椭圆形、矩形、不规则的椭圆形都可
2) 用实线隔开不同的限界上下文
3) 用虚线分隔不同的子域
4) 子域里画聚合根、实体,值对象
场景A:大的限界上下文包含多个子域(业务域范围划分粒度较大)
场景B:一个子域里按小粒度拆分多个限界上下文(复杂业务)
场景C:一个子域代表一个限界上下文(最佳实践)
4.概念落地
核心是:把DDD里的概念转换为业务知识,围绕业务知识设计系统
业界一般做法分为:战略设计与战术设计
战略设计
产出:领域名词,领域事件,命令(基于事件风暴)
产出:领域模型图,子域与限界上下文 (1、根据相关性做归类。 2、根据团队粒度做裁剪、根据技术特点做裁剪)
战术设计
提炼和定义出领域模型和之间的关系、将战略设计阶段的产出通过DDD领域概念进行承接并细化数据和行为
通过分层模式作为顶层架构规范
DDD分层架构 | 整洁架构(洋葱架构) | 六边形架构(端口与适配器架构) | |
---|---|---|---|
架构模式 | |||
提出人 | Eric Evans 2004年 |
Robert C. Martin(鲍勃大叔) 2012年 《整洁架构之道》作者 书中提出的整洁架构 |
2005年库克伯恩 (Alistair Cockburn)首次提出 2014年 出版《实现领域驱动设计》作者 Vaughn Vernon(沃恩.弗农)应用到了DDD中 |
3种模式其核心都是关注应用层与领域层,它的作用就是将核心业务逻辑与外部应用、基础资源进行隔离。
红色框内部主要实现核心业务逻辑,但核心业务逻辑也是有差异的,有的业务逻辑属于领域模型的能力,有的则属于面向用户的用例和流程编排能力。按照这种功能的差异,在这三种架构中划分了应用层和领域层,来承担不同的业务逻辑。
各层职责说明
名称 | 职责 | 备注 |
---|---|---|
用户接口层 | 用户接口层负责向用户显示信息和解释用户指令。这里的用户可能是:用户、程序、自动化测试和批处理脚本等等。 | 很薄,允许有简单的参数校验 |
应用层 | 主要面向用例和流程相关的操作,可以协调多个聚合的服务和领域对象完成服务编排和组合,协作完成业务操作。 应用服务还可以进行安全认证、权限校验、事务控制、发送或订阅领域事件等。 |
|
领域层 | 领域层的作用是实现核心业务逻辑,通过各种校验手段保证业务的正确性。领域层主要体现领域模型的业务能力,它用来表达业务概念、业务状态和业务规则。领域层包含聚合根、实体、值对象、领域服务等领域模型中的领域对象。领域模型的业务逻辑主要是由实体和领域服务来实现的,其中实体会采用富含业务知识(行为)的模型来实现所有与之相关的业务功能。其次,实体和领域服务在实现业务逻辑上不是同级的,当领域中的某些功能,单一实体(或者值对象)不能实现时,则需要领域服务,它可以组合聚合内的多个实体(或者值对象),实现复杂的业务逻辑 | |
基础设施层 | 提供通用的技术和基础服务,包括第三方工具、驱动、消息中间件、网关、文件、缓存以及数据库等。比较常见的功能还是提供数据库持久化。 |
分层架构原则
架构根据耦合的紧密程度又可以分为两种:严格分层架构和松散分层架构
在《实现领域驱动设计》一书中,DDD分层架构有一个重要的原则:每层只能与位于其下方的层发生耦合(严格分层)。
所以:我们建议采用严格分层架构,不允许跨层调用
通过分层后的代码架构作为开发规范
DDD编程范式
几种特殊的对象与数据转换
|
Command | Query | Event | DTO | |
---|---|---|---|---|
语意 | ”希望“能触发的操作 | 各种条件的查询 | 已经发生过的事情 | DTO对象只是数据容器,只是为了和外部交互,所以本身不包含任何逻辑,只是贫血对象,可细化为CommandDTO,QueryDTO |
读/写 | 写 | 只读 | 通常是写 | 根据场景,可以是写DTO请求,读DTO请求 |
返回值 | DTO 或 Boolean | DTO 或 Collection | Void |
注:上图来自文章,DTO转换采用了Assembler命名,我们这边采用的仍然是Converter命名
写场景
读场景
5.参考资料
https://insights.thoughtworks.cn/backend-development-ddd/
这篇文章多读几次都不过分