DDD领域驱动设计
通用语言<br>Ubiquitous Language
概念
通过团队交流、达成共识的、能够准确传递业务规则的、简单:语言
价值
解决了交流障碍问题,使领域专家和开发人员协同合作
同名的业务词汇与实际业务关系不清
同名的业务词汇与不同的业务词汇关联
同名的业务词汇之间的关系不清楚
领域模型<br>Domain Model
特点
综合了系统分析和设计
语言、模型、代码三者紧密绑定
可以通过UML类图来展示
领域<br>Domain
本质
领域与具体开发技术无关,就是你的软件系统要解决的实际问题相关的所有东西的集合
解决方案空间:如何实现软件以解决这些业务挑战
问题空间:业务所面临的问题和挑战
子域<br>Sub Domain
包含
核心域<br>Core Domain
业务系统核心价值所在
支撑子域
通用子域
例子
电商网站
核心域:销售子域
通用子域:日志子域
支撑子域:除了销售子域之外的子域,如物流子域
限界上下文<br>Bounded Context<br>
本质
保证模型概念的清晰和无歧义,避免具有多重含义和职责的模型
例子
商品
在采购上下文中 - 补货商品
在售后上下文中 - 售后商品
如何划分
语言二义性
变化一致性
业务相关性
概念相关性
与技术组件保持一致(保持一致的模型认识)
一个团队
一个IDEA工程
一个部署单元
梳理关系
上下文映射图<br>Context Map
描述不同Context下模型的联系点
上下文依赖
应用服务<br>Application Service
隐藏领域层的复杂性及其内部实现
领域服务<br>Domain Service
表述领域行为
eg.金额计算、支付、生成订单=>领域行为
聚合<br>Aggregate
来源
UML类图概念,整体与部分的关系
eg.车和轮胎=>可以独立存在
DDD中的概念
领域对象的<b>显示分组</b>
封装业务
保证聚合内领域对象的数据一致性
关键
领域对象间的关联关系
基于<b><font color="#f15a23">业务用例</font></b>而非现实生活建立必要关联
减少不必要的关联
将双向关联转换为单项关联
难点
一致性的维护
聚合内实现事务一致性
聚合外实现最终一致性
设计
一个持续性的活动
无法一口吃个胖子
持续改进聚合的设计
实体<br>Entity
概念
实体=唯一身份标识 + 可变性【状态(属性) + 行为(方法或领域事件或领域服务)】
特征
唯一标识
委派标识
为了迎合ORM而创建,和领域实体标识无关系
领域标识
基于领域实体概念分析确定的唯一身份标识
eg.支付宝交易流水号
可变性
实体的状态
eg.订单状态:未支付、正常、已发货、关闭
值对象<br>Value-Object
概念
<b><font color="#f15a23">值对象=值+对象</font></b> => 将一个值用对象的方式进行表述,表达一个具体的固定不变的概念
值的特征
表示一个具体的概念
通过值的属性对其识别
属性判等
固定不变
作用
符合通用语言,更简单明了的表达简单业务概念
简化设计,减少不必要的数据库表设计
值对象不会孤立存在,可作为所属实体的数据列
多个值对象序可以列化到单个列
建模
结合通用语言的表述检查其是否具有值得的含义和特征
仓库<br>Repository
要点
通过<b>聚合根</b>来持久化和检索领域对象
隐藏聚合持久化和检索的底层技术实现
定义数据模型与领域模型的<b>边界</b>
领域事件<br>Domain Event
基本概念
捕获领域中发生的具有业务价值的一些事情
eg."订单支付成功"=>一个领域事件
最终一致性
案例
订单系统发布"订单成功支付"事件
库存系统订阅并处理库存扣减逻辑
通知系统订阅并处理拣货通知
实现
事件存储
事件发布可用于重新发布
通过消息中间件去分发事件
事件溯源
工厂<br>Factory
目标
隐藏对象的复杂创建逻辑
表达对象实例化的意图
好处
将领域对象的使用和创建分离
隐藏创建复杂领域对象的业务逻辑
根据调用者的需要创建相应的领域对象
封装聚合的内部状态
模块<br>Module
抽象
对领域模型进行分解的产物,相对独立的功能单元
由一系列高内聚的领域对象组成
架构风格<br>Achitecture
分层架构<br>Layered Architecture
UI层
为外部用户访问底层系统提供交互界面和数据表示 e.g 接受和校验用户输入、输出JSON/XML的数据
Facade层
分离UI和应用层,将应用层数据mapping成UI层适用的数据
应用层
定义系统业务功能,编排领域层中的领域对象实现功能
基础设施层
为领域层提供技术支撑 e.g 持久化、序列化、消息通知
六边形架构(端口和适配器)<br>Hexagonal Architecture<br>
端口
Application和Domain层通过端口(一般是API)与外部通信
保证内部逻辑的独立,和外部依赖解耦
面向服务<br>SOA<br>
松耦合:由于服务自治,有一定封装边界,服务调用交互是通过发布接口。这意味着应用程序不感兴趣的服务如何被实现<br>
位置透明:服务的消费者不必关系服务位于什么地方。<br><br>
可在异构平台间复用。可以将遗留系统包装成服务。<br>
便于测试,能并行开发,较高可靠性和良好可伸缩性
命令查询职责分离<br>CQRS
Command - 改变对象状态
Query - 返回对象数据
解决领域模型显示的复杂性
事件驱动<br>Event Driven
管道和过滤器
架构设计的终极大招还是By Experience ——靠经验吃饭