文章目录
- DDD领域驱动设计笔记
- 贫血模型的优点和缺点
- 领域模型的特点
- 领域驱动设计概念
- 领域模型
- 通用语言:避免鸡同鸭讲
- DDD分层架构
- 在领域层有什么东西?
- 实体(Entity)
- 值对象(Value Object)
- 领域服务
- 聚合
- 重建已经存储的领域对象:资源库
- 总结
- DDD是一套原则和模式,主要聚焦设计
- DDD构造块
- DDD获取成功的条件
贫血模型的优点和缺点
- 简单
- 对于只有少量业务逻辑的应用来说,使用起来非常自然
- 开发迅速,易于理解
- 注意:不能完全排斥这种方式
- 无法良好的应对复杂逻辑
- 例如:收入确认规则发生变化
领域模型的特点
- 对业务领域做了建模
- 细粒度的类,易于扩展,容易复用
- 可以应对复杂的业务逻辑
- 需要经验才能掌握
- 简单的领域模型
- 几乎和数据库中的表一一对应
- 复杂领域模型
- 使用了继承、组合、设计模式等各种手段
领域驱动设计概念
- Domain Driven Design
- DDD是一种以领域为核心的设计和开发理念。
- DDD通过维护一个深度反应领域概念的模型,以及提供了可行的经过实践检验的大量模式来应对领域的复杂性
领域模型
- 不是一个具体的图,而是那个图要传递的思想
- 不是领域专家头脑中的知识,而是一个经过严格组织并选择性抽象的知识
- 一幅图能够描绘和传达一个模型,同样,经过精心编写的代码和一段英语句子都能达到这个目的
- 不是要建立一个尽可能符合“现实”的模型
通用语言:避免鸡同鸭讲
- 领域专家(业务专家)必须要参与到模型的建立中来
- 但是用谁的语言来沟通?
- 专家有自己的行话
- 技术人员有自己的黑话
- 需要有一种通用语言,让团队在交流时能达到一致。
DDD分层架构
层级 | 作用 |
用户界面/展现层 | 负责向用户展现信息以及解释用户命令 |
应用层 | 很薄的一层,用来协调应用的活动。它不包含业务逻辑。它不保留业务对象的状态,但它保有应用任务的进度状态。(相当于贫血模型中的Service层,但是在领域模型中,该层级不实现业务逻辑,只调用领域层中的方法) |
领域层 | 本层包含关于领域的信息。这是业务软件的核心所在。在这里保留业务对象的状态,对业务对象和它们状态的持久化被委托给了基础设施层。 |
基础设施层 | 本层作为其它层的支撑库存在。它提供了层间的通信,实现对业务对象的持久化,包含对用户界面层的支撑库等作用。 |
在领域层有什么东西?
实体(Entity)
- 对象不是由属性定义的,而是标志定义的
- 对象内容的变化不会影响标识符
- 无论保存到硬盘、装入内存、通过网络发送,标识符都不变
- 除了标识外,哪些东西应该成为实体的属性?
- 抓住实体对象定义的最基本特征,用于识别、查找或匹配对象的特征
- 只添加那些对概念至关重要的行为和这些行为所需的属性
值对象(Value Object)
- 对象是根据值来确定的
- 可以在不同实体中使用
- 值对象通常是不可变的
- Color/Point/Money/Address
领域服务
- 有些领域逻辑是动词,表示了一种重要的行为很难映射为对象,无法归结到实体和值对象当中
- 例如:转账
- 特征
- 服务执行的操作涉及一个领域概念,这个领域概念通常不属于一个实体或值对象
- 被执行的操作涉及到领域中的其他对象
- 操作是无状态的
- 将Service划分到各个层中
层级 | 功能 |
应用层 | 资金转账应用服务 获取输入(例如json请求) 发送消息给领域层服务,要求其执行 监听转账的确认消息 使用基础设施服务来发送通知 |
领域层 | ** 资金转账领域服务** 与必要的账户对象进行交互,执行相应的介入和贷出操作 提供结果的确认(成功、失败等) |
基础设施层 | 发送通知服务 发送电子邮件 |
聚合
- 聚合概念
- 聚合表示逻辑上联系很紧密的对象
- 每个聚合都有一个根,有一个边界
- 聚合根控制了对这个聚合内所有对象的访问,外部要想访问内部对象,必须通过聚合根才行
- 聚合举例
- 用户直接调用
car.ride()
- 用户直接操作细节
if(car.getTires).getUsageLevel() < Car.ACCEPTABLE_TIRE_USAGE){
for(Wheel w: car.getWheels(){
w.spin();
})
}
- 聚合的特点
- 根实体有全局标识(例如 OrderId)
- 聚合内的实体有本地标识(只在聚合内部是唯一的,例如LinItem的序号)
- 聚合外部的对象不能直接引用除了根之外的对象
- 可以把一个值对象的copy传递给外界,该副本和聚合没有关联
- 只有聚合的根才能通过数据库被装载
- 删除操作会把聚合内的所有对象删除
- 当对聚合边界内任何对象做修改时,聚合内的规则必须被满足(例如Order的总价格和各个LineItem的价格和要相等)
重建已经存储的领域对象:资源库
- 工厂负责创建对象
- 资源库(Repository)从存储中重建对象
- 不分配唯一的标识,标识是输入参数的一部分
- 资源库“说”的是领域语言
总结
DDD是一套原则和模式,主要聚焦设计
- 理解领域(软件需要在领域内工作)
- 建立这个领域富有表达力的模型
- 提取通用语言
DDD构造块
- 分层架构
- 实体、值对象、领域服务
- 聚合
- 工厂、资源库
DDD获取成功的条件
- 你面对的不是一个简单的领域
- 否则直接用贫血模型就OK了
- 你可以和领域专家合作
- 你有一个迭代式的开发过程
- 你有一个技能熟练的、能够自我激励的团队
- 一定要把这个系统做好!