- 聚合根是实体,拥有实体的业务属性和行为,同时也是聚合的管理者,负责协调聚合内的实体和值对象,按照固定的业务规则,完成业务逻辑。
- 聚合根是聚合对外唯一的接口人,聚合之间以聚合根ID关联的方式接受聚合的外部任务和请求,聚合外不能通过对象引用的方式访问聚合内的对象。需要将关联的聚合根ID作为入参,先访问聚合根,再通过聚合根导航到聚合内部实体。
- 如果聚合根被删除了,他引用的实体和值对象就不会存在了
- 聚合根和聚合根所在层的领域服务都可以组合多个实体完成领域逻辑,但为了DDD分层架构的职责单一,聚合根最好只承担聚合管理职能,只实现聚合内实体和聚合根本身相关的业务逻辑,而跨多个实体的复杂领域逻辑统一放到领域服务中实现。
- 领域建模中,可能存在一些独立的找不到聚合根的实体,但可以根据高度依赖的业务逻辑,把这些实体集合也作为聚合处理。
- 如图,第一步首先采用事件风暴,梳理网购领域中的业务行为和行为产生的实体,值对象
- 从众多实体中找到适合作为聚合对象管理者的根实体,即聚合根(图中加深色的实体),我们可以根据这个实体是否贯穿整个软件的生命周期,是否有全局唯一ID,是否可以作为一个聚合管理者去管理其他实体和值对象来确定是不是聚合根
- 将聚合根和关联的实体,值对象汇聚到多个聚合里,如图,用户和订单作为用户聚合和订单聚合的聚合根,汇聚了其他实体和值对象,形成用户和订单两个聚合,划分好了聚合间的上下文。
- 找到聚合之间的引用,比如用户数据冗余到了订单聚合里的发件人和收件人,不至于用户聚合发生异常时,订单聚合也出现问题,订单聚合记录了发件人和收件人的快照数据
- 遍历查看所有的聚合,看是否有与其他聚合相关的实体和值对象,遵循单一职责剥离出来归并到其他聚合中
1、聚合内要有一套不变的,基本长期固化的业务规则,而不是简单的将实体和值对象组合到一起,聚合的上下文边界要清晰,保证聚合边界外的任何东西与聚合无关
2、聚合可以作为拆分微服务的最小业务单元,与Serverless完美的结合,但不适合过度拆分,除非业务需求
3、聚合要高内聚,不宜设计得过大,会导致聚合内的实体和值对象膨胀从而不好管理
4、聚合间的交互要通过聚合根ID应用其他聚合
- 当领域模型随着业务需求的变化,微服务内需要进行更小粒度的拆分,即聚合层面的拆分,这样原本互相在微服务内互相依赖的聚合,就变成了服务间调用了,如果最开始在聚合内用对象应用的方式,那么服务拆分后就会失效,需要很大的代码调整
- 采用聚合根ID应用的方式,则可以将聚合根ID和目标方法作为微服务的入参,实现跨微服务的调用,这种的改动方式会小很多,代码理解起来也会更加的清晰
6、在聚合内使用数据强一致性,在聚合外使用数据最终一致性。DDD强调在一次事务中,最多只能修改一个聚合的数据。如果涉及到多个聚合的数据修改,在微服务内可以使用事件总线,微服务外使用领域事件驱动,通过消息的最终一致性来保证