DDD实战,领域驱动设计
2020-02-28 10:46:39 46 举报
AI智能生成
领域驱动设计的原著实在是晦涩难懂, 本文先把DDD的10个核心概念梳理清楚, 以及DDD的分层架构, 如何结合微服务构建 高内聚,低耦合的系统
作者其他创作
大纲/内容
DDD是什么
概念
DDD是一种设计思想, 通过事件风暴使用通用语言对业务进行领域建模,通过限界上下文进行合理的领域拆分, 可以使得领域模型转向微服务的设计和落地, 从而解决复杂软件难以理解, 难以演进, 也可以解决微服务业务界限难以界定的问题.
战略设计
建立领域模型,划分微服务边界,建立通用语言的限界上下文
战术设计
侧重于领域模型的技术实现,从领域模型转向微服务的设计和落地
图示
微服务与DDD结合
DDD
架构设计方法, 从业务领域视角划分领域边界, 使用通用语言进行高效沟通, 抽象出业务领域模型,维持业务和代码的一致性
微服务
架构风格, 关注 运行时的服务间的通讯, 容错和隔离降级, 实现整体的服务治理, 各个服务的地理开发, 测试, 构建, 部署
解决问题
DDD通过战略设计建立领域模型, 划定领域边界, 解决微服务设计过程中, 边界难以划定的难题
DDD带来的好处
完整的架构设计思路, 能给你带来战略设计到战术设计的过程, 是的设计思路清晰明了, 设计过程更加规范
擅长处理高复杂的业务, 建立一个核心且稳定的领域模型, 有利于领域知识的传递和传承
领域专家和开发的合作, 建立良好的沟通氛围, 达到业务和代码的逻辑一致性
设计思想, 原则 和模式 有助于提高架构设计能力
DDD的核心概念
领域
即范围, 边界, 特定的区域
子域
概念
领域按照一定的业务规则细分, 进而划分出多个子域, 每个子域对应一个更小的业务范围
过程
把问题域逐步分解, 降低业务理解和系统实现的复杂度
分类
核心域
唯一的定义明确的领域模型, 业务的核心部分, 公司核心竞争力
通用域
系统中用到的通用系统, 例如: 认证, 权限等. 甚至可以采购现成的.
支撑域
具有企业特性, 具备"定制开发"的特性
通用语言
定义上下文的含义
在事件风暴中, 通过团队交流达成共识的, 能简单清晰准确地描述业务含义和规则的言语
注意
在说某通用语言时, 必须要限定在某个上下文内, 以确保每个上下文含义在它特定的边界内都有唯一的含义
限界上下文
定义领域边界
领域可以被拆分成多个子领域, 一个领域相当于一个问题域, 拆分的过程就是大问题拆分为小问题的过程. 每个领域模型都有他对应的限界上下文, 理论上限界上下文就是微服务的边界
实体
概念
领域模型中的实体是多个属性, 操作和行为的载体, 拥有唯一标志. 实体和值对象是组成领域模型的基础单元, DDD中采用充血模型构建实体. 使用ID即可判定两实体是否相等
值对象
概念
通过对象属性值来识别的领域对象, 将多个相关的属性组合为一个概念整体, 具有整体概念和不可修改的属性. 值对象之间使用属性值进行判断相等性.
实体和值对象的关系
实体和值对象是领域模型的最基本单元, 一起实现实体最基本的核心领域, 值对象依附于实体
聚合/聚合根
理解
聚合包含一个聚合根和上下文边界, 这个边界根据业务单一职责和高内聚原则, 定义了聚合内部应该包含哪些实体和值对象, 而聚合之间的边界是松耦合的.
领域模型中的实体和值对象好比个体, 而能让实体和值对象协同工作的组织就是聚合, 用于保这些领域对象在实现共同的业务逻辑时, 能保证数据的一致性.
业务和逻辑紧密关联的实体和值对象组合而成, 聚合是数据修改和持久化的基本单元, 每个聚合对应一个仓储, 实现数据的持久化
如何设计聚合
1. 采用事件风暴, 根据业务行为, 梳理出业务发生过程中的实体和值对象
2. 从众多实体中选出合作为对象管理者的根实体, 也叫聚合根
3. 根据业务单一职责和高内聚原则, 找出与聚合根关联的所有的紧密依赖的实体和值对象.
4. 在聚合内根据 聚合根, 实体, 值对象 的依赖关系, 画出对象的引用和依赖模型.
5. 多个聚合根据业务语义和上下文一起划分到同一个限界上下文中
聚合的设计原则
1. 在一致性边界内建模真正的不变条件: 聚合内的实体和值对象按照统一的业务规则运行, 实现数据对象的一致性
2. 设计小聚合: 降低由于业务过大导致的聚合重构的可能性.
3. 通过唯一标志引用其他聚合: 聚合之间通过关联外部聚合根id的方式引用
4. 在边界之外使用最终一致性: 在一次事务中, 最多只能更改一个聚合的状态. 若一次业务操作导致多个聚合状态的修改, 可以采用领域事件异步修改相关的聚合.
5. 通过应用层实现跨聚合的服务调用
聚合/聚合根/实体/值对象 特征
聚合特征
高内聚, 低耦合, 领域模型的最底层的边界, 甚至可以作为拆分微服务的最小单元. 但需结合实际情况;一个微服务可包含多个聚合, 聚合之间的边界是微服务内天然的逻辑边界, 在微服务架构演进的时候就可以聚合为单位进行拆分和组合了.
聚合根特征
聚合根是特殊的实体, 一个聚合仅有个聚合根, 聚合根在聚合内对实体和值对象采用直接对象引用的方式进行组织和协调 聚合根之间则通过ID关联的方式实现聚合之间的协同
实体特征
有个唯一的ID标志, 通过ID判定相等性, 状态可变, 依附于聚合根, 其生命周期由聚合根管理. 实体一般会持久化. 实体可以引用聚合内的 聚合根, 实体, 值对象.
值对象特征
无ID, 不可变, 无生命周期, 值对象之间通过属性值全等判断相对性. 核心本质是值, 是一组概念完整的属性组合的集合, 值对象尽量只引用值对象
领域事件
概念
一个领域事将导致进一步的业务操作 在实现业务解耦的同时, 还有助于形成完整的业务闭环
识别领域事件
在时间风暴中,做用户旅程 或者场景分析时, 出现类似 "如果...那么.." "发生...时, 则..." 等, 发生某种事情之后, 触发进一步的操作, 那么这个事件很有可能就是领域事件
领域事件可以切断领域模型之间的强依赖关系, 事件发布完成之后, 发布方不必关系订阅方事件处理是否成功. 实现领域模型之间的解耦, 最终保证了基于事件的一致性
使用场景
微服务内的领域事件
完成业务实体构建和命令, 事件数据的的持久化后, 按照DDD原则"一次事务只更新一个聚合", 则需要把事件发布到事件总线, 但是这样会增加复杂度. 因此需要结合应用复杂度和收益进行总和考虑
数据实时要求高的场景下, 可以在应用服务层, 可以通过跨聚合的服务编排和组合, 以服务调用的方式完成跨聚合的访问. 这个过程会用到分布式事务. 以保证发布方和订阅方的数据同时更新.
微服务间的领域事件
可以采用微服务直接调用的方式, 实现数据和服务的实时访问. 需要引入分布式事务以保证数据的一致性.
考虑: 事件构建, 发布和订阅, 事件数据的持久化.
事件风暴
概念
梳理用户旅程, 分析业务场景, 领域专家和开发人员头脑风暴的过程, 进而确定 限界上下文, 通用语言,找出实体, 值对象等 依次 进行领域分解, 建立领域模型
事件风暴的准备工作
参与者
项目团队, 领域专家(业务,架构师,产品,开发, 测试); 领域专家需要单独的说下: 对业务或者问题有深刻见解的主体专家, 例如需求分析人员, 产品经理, 或者是在这里领域多年开发经验的开发人员.
材料
事件风暴的参与者会把自己的想法和意见写在即时贴上
可用不同的颜色的贴纸区分领域行为
蓝色: 命令
绿色: 实体
橙色: 领域事件
黄色: 补充信息
关注点
重点关注某类业务的语言和行为, 比如某些业务动作或者行为是否会触发下一个业务动作, 进而可以分析出聚合, 事件, 实体,命令
DDD分层架构
DDD四层架构
用户接口层
负责向用户显示信息和接受用户的指令, 包括:用户, 程序, 自动化测试, 批处理等.
应用层
理论上不应该有业务规则或者逻辑, 主要面向用例和流程相关的操作. 由于位于领域层之上, 所以包含了多个聚合, 可以协调多个聚合服务和领域对象完成服务编排和组合. 负责处理业务用例的执行顺序和结果的拼装, 例如: 安全认证, 权限校验, 事务控制, 发送或者订阅领域事件
应用层也是微服务之间交互的通道, 调用其他服务, 完成微服务之间的组合和编排
领域层
领域层主要体现领域模型的业务能力, 用来表达业务概念 业务状态和业务规则.
领域层包括: 聚合根, 实体, 值对象, 领域服务等
基础层
贯穿所有层, 采用依赖倒置设计为其他层提供通用的技术和基础服务. 包括: 工具, 驱动, 消息中间件, 网关, 文件, 换成, 数据库持久化
原则
每层只能与其下方的层发生耦合
微服务架构的演进
以聚合为基础单元, 完成领域模型和微服务的架构演进, 聚合可以作为一个整体, 在不同的领域模型之间重组或拆分, 或者直接把一个聚合独立为一个微服务.
架构模型分类
整洁架构
最外用户层 -> 应用服务层 -> 领域服务层 -> 领域模型
图示
六边形架构
通过接口与外部进行交互的
最外层用户 -> 适配器 -> 应用层 -> 领域服务层
图示
与DDD分层架构比较
原则都是:"高内聚 低耦合"
核心的点
1. 大致都分了两层
1). 领域层实现面向领域模型, 实现领域模型的核心业务逻辑, 属于原子模型, 需要保持领域模型也业务逻辑的稳定. 对外提供稳定的相对细颗粒度的领域服务.
2). 应用层实现面向用户的相关用例和流程. 对外提供粗粒度的API服务. 对前台应用和领域层进行适配, 接受前台需求. 可随时做出响应和调整
2. 合理分层的优势
不要把领域无关的逻辑放在领域层实现, 保证领域层的纯洁稳定.
也不要把领域层的逻辑放在应用层, 会导致应用层过于庞大, 最终导致领域模型失焦.
若不能保证上诉两点, 则可引入防腐层,进行新老系统的适配和转换, 过渡完成后, 废弃掉防腐层代码
通过分层的方式来控制需求的变化从外到里对系统的影响, 收到的需求的影响会越来越小.面对用户端可以快速在应用层调整, 对服务和聚合进行组合和编排达到快速适配的效果.
数字转型
大平台
把公共能力和核心能力分开建设, 解决公共模块重复投入和重复建设的问题
中台
概念
关键字: 共享, 联通, 融合, 创新
联通是前台和中台之间的联通
融合是前台流程和数据的融合
然后以共享的方式支持前端一线业务的发展和创新
解决问题
核心业务链路的联通和不同渠道服务的共享问题
解决系统微服务拆分之后的数据孤岛, 数据融合和业务创新的问题
针对前端用户的感受就是只有一个前台, 而非要使用一个企业下的多个APP,网站,应用等.
数据中台主要职能
1. 完成企业全域数据的采集和存储, 实现不同业务的数据的会中个集中管理
2. 按照标准的数据贵方或数据模型,把数据按照不同的主题或场景进行加工和处理
3. 建立业务需求驱动的数据体系, 基于各个维度的数据深度萃取数据价值, 支持业务和运营
达到的效果
前台需要什么样的业务, 需要什么样的资源, 可以直接找中台, 不需要每次都修改自己的底层逻辑代码
分类
1. 通用中台: 把共享的公共能力进行领域建模
2. 核心中台: 把核心能力进行领域建模
领域,中台和微服务关系
从DDD视角看, 子域可分为核心域, 通用域和支撑域; 从中台的视角看, 业务域细分后的业务中台,可分为核心中台和通用中台
图示
中台建模步骤
1. 按照业务流程把业务域细分为多个中台, 根据功能属性和重要性进行归类为 通用中天和核心中台
2. 选取中台, 根据用例,业务场景和用户旅程完成事件风暴, 找出实体 聚合 限界上下文. 进行领域分解 建立领域模型
3. 以主领域模型为基础, 扫描其他的中台领域模型, 检查是否存在重复或需要重组的领域对象, 功能. 提炼并重构主领域模型, 完成领域模型的设计
4. 遍历所有的主领域重复第三步, 直到所有的领域模型完成建模
5. 基于领域模型完成微服务设计, 完成系统落地
中台业务模型建设
1.自顶而下的策略
适用于全新的应用系统建设, 或者是旧系统重建的请款g
步骤
1. 自上而下领域分解为子域, 分为核心域, 通用域, 支撑域
2. 对子域建模, 划分领域边界, 建立领域模型和限界上线文
3. 根据限界上下文进行微服务设计
2.自底而上的策略
适用于遗留系统业务模型的演进式重构
步骤
1. 锁定系统所在的业务域, 采用时间风暴, 找领域对象, 构建聚合, 划分限界上线文, 建立领域模型
2.从传统系统的核心领域模型中, 归纳出业务子域, 对比分析域内领域模型和 聚合的差异和共同点, 打破原有的模型,完成新新业务的模型重组和归并的过程
3. 根据领域模型设计微服务
互联网电商案例
主要领域模型图示
针对互联网中的 用户模型
抽象出的集合包含聚合根,实体, 值对象,领域服务等
图示
DDD设计微服务模型
标准代码模型好处
1. 项目团队成员更好地理解代码, 根据代码规范实现团队协作
2. 可以让微服务各层互不干扰, 分工协作, 避免不必要的代码混淆
3. 可以轻松应对微服务架构的演进和代码重构
微服务根目录
Interfaces 用户接口层
与前端交互, 用来接收用户数据和展现数据相关代码
下级
assembler
实现DTO和领域对象之间的相互转换和数据交换
dto
数据传输的载体
facade
提供叫粗烈度的调用接口, 把请求委派给一个或多个服务进行处理
Application 应用层
被Interfaces层调用, 组合编排不同的微服务和内部的聚合
下级
event
包括两个子目录, publish 和 subscribe, 事件的发布和订阅
service
应用层会对多个领域服务或其他外部服务进行封装 编排和组合
Domain 领域层
主要存放领域层核心业务逻辑代码, 包括领域对象, 领域服务, 和事件
下级
aggregate 聚合
根据实际项目的聚合名称命名, 定义聚合根, 实体, 值对象 领域服务的关系和边界
entity
聚合根, 实体, 值对象, 实体工厂模式, 实体类采用充血模型
event
事件相关
service
一个领域服务由多个实体组合出来的业务逻辑
repository
存放聚合的查询或持久化领域对象的代码
Infrastructure 基础层
基础资源相关的代码
下级
config
配置相关代码
util
开发框架, 消息, 数据库, 缓存, 文件, 工具包, 通用算法...
图示
0 条评论
下一页