DDD的优势(2)

简介: DDD的优势(2)

7.5.2 聚合根


聚合根(Aggregate Root)是DDD中的一个概念,是一种更大范围的封装,会把一组有相同生命周期、在业务上不可分割的实体和值对象放在一起,只有根实体可以对外暴露引用,这也是一种内聚性的表现。


确定聚合边界要满足固定规则(Invariant),是指在数据变化时必须保持的一致性规则,具体规则如下。


  • 根实体具有全局标识,最终负责检查规定规则。
  • 聚合内的实体具有本地标识,这些标识在Aggregate内部才是唯一的。
  • 外部对象不能引用除根Entity之外的任何内部对象。
  • 只有Aggregate的根Entity才能直接通过数据库查询获取,其他对象必须通过遍历关联来发现。
  • Aggegate内部的对象可以保持对其他Aggregate根的引用。
  • Aggregate边界内的任何对象在修改时,整个Aggregate的所有固定规则都必须满足。


仍以银行转账的例子来说明,如图7-10所示,账号(Account)是客户信息(CustomerInfo)Entity和值对象(Address)的聚合根,交易(Tansaction)是流水(Journal)的聚合根,流水是因为交易才产生的,具有相同的生命周期。


image.png


7.5.3 领域服务


有些领域中的动作是一些动词,看上去并不属于任何对象。它们代表了领域中的一个重要的行为,所以不能忽略它们或者简单地把它们合并到某个实体或者值对象中。当这样的行为从领域中被识别出来时,推荐的实践方式是将它声明成一个服务。这样的对象不再拥有内置的状态,其作用仅仅是为领域提供相应的功能。Service往往是以一个活动来命名,而不是Entity来命名。


例如在银行转账的例子中,转账(transfer)这个行为是一个非常重要的领域概念,但是它发生在两个账号之间,归属于账号Entity并不合适,因为一个账号Entity没有必要去关联它需要转账的账号Entity。在这种情况下,使用MoneyTransferDomainService就比较合适了。识别领域服务,主要看它是否满足以下3个特征。


(1)服务执行的操作代表了一个领域概念,这个领域概念无法自然地隶属于一个实体或者值对象。


(2)被执行的操作涉及领域中的其他对象。



(3)操作是无状态的。


7.5.4 领域事件


领域事件(Domain Event)是在一个特定领域由一个用户动作触发的,是发生在过去的行为产生的事件,而这个事件是系统中的其他部分或者关联系统感兴趣的。

为什么领域事件如此重要?因为在分布式环境下,很少有业务系统是单体的(Monolithic),消息作为分布式系统间耦合度最低、最健壮、最容易扩展的一种通信机制,是我们实现分布式系统互通的重要手段。关于领域事件,我们需要注意两点,分别是事件命名和事件内容。


1.事件命名


事件是表示发生在过去的事情,所以在命名上推荐使用Domain Name + 动词的过去式 + Event,这样可以更准确地表达业务语义。例如,在银行转账的例子中,对于转账成功和失败我们都需要发出事件通知,可以定义两个领域事件如下。

(1)MoneyTransferedEvent:表示转账成功发出的事件。


(2)MoneyTransferFailedEvent:表示转账失败发出的事件。


2.事件内容


事件内容在计算机术语中叫作payload,有以下两种形式。


(1)自恰(Enrichment):就是在事件的payload中尽量多放数据,这样consumer不需要回查就能处理消息,也就是自恰地处理消息。


(2)回查(Query-Back):这种方式是只在payload放置id属性,然后consumer通过回调的形式获取更多数据。这种形式会加重系统的负载,可能会引起性能问题。


7.5.5 边界上下文


领域实体的意义是有上下文的,比如同样是Apple,在水果店和苹果手机专卖店中表达出的含义就完全不一样。边界上下文(Bounded Context)的作用是限定模型的应用范围,在同一个上下文中,要保证模型在逻辑上统一,而不用考虑它是不是适用于边界之外的情况。


那么不同上下文之间的业务实体要如何实现交互呢?就像关系数据库和对象之间需要ORM一样,不同上下文之间的实体也需要映射。在DDD中,这种机制叫作上下文映射(Context Mapping),我们可以使用防腐层(Anti-Corruption)来完成映射的工作。


如图7-11所示,在我们开发的CRM系统中,商家的客户大部分是来自于ICBU网站的会员,虽然二者有很多属性都是一样的,但我们还是有必要引入防腐层来做上下文映射,主要有以下两个原因。


(1)虽然属性大部分一样,但二者的作用和行为在各自上下文中是不一样的。

(2)解耦影响,加入了防腐层之后,网站的会员变化就不会影响到CRM系统了。


image.png

相关文章
|
7月前
|
存储 设计模式 前端开发
MVC架构和DDD架构的区别?
最近在学习一个开源社区项目,第一次听说了DDD项目架构,于是通过搜索之后来分享给大家
|
7月前
|
数据库
DDD架构浅谈
DDD架构浅谈
152 4
|
消息中间件 JavaScript 小程序
领域驱动设计(DDD)的几种典型架构介绍
领域驱动设计(DDD)的几种典型架构介绍
|
敏捷开发 架构师 领域建模
别吵,可落地的DDD!
别吵,可落地的DDD!
492 0
|
消息中间件 架构师 Dubbo
DDD的基础设施到底在哪里
DDD的基础设施到底在哪里
DDD的基础设施到底在哪里
|
设计模式 缓存 Java
DDD之代码架构
这是一篇迟到的文章。这其实是我写DDD的第四篇文章。去年11月份左右我在个人网站上写了三篇关于DDD的文章,都是比较偏战略部分的。那个时候我还在一个正在使用DDD的项目上,也是我第一次真正开始深入使用DDD。
621 1
|
设计模式 JSON 缓存
|
设计模式 领域建模
DDD的模式与实践案例(1)
DDD的模式与实践案例(1)
1026 0
DDD的模式与实践案例(1)
|
Java uml
DDD的优势(4)
DDD的优势(4)
259 0
DDD的优势(4)
|
Dubbo Java 应用服务中间件
DDD的模式与实践案例(4)
DDD的模式与实践案例(4)
1119 0
DDD的模式与实践案例(4)