美文网首页
领域驱动设计-聚合和聚合根

领域驱动设计-聚合和聚合根

作者: 乙腾 | 来源:发表于2020-12-29 00:30 被阅读0次

聚合

领域模型内的实体和值对象就好比个体,而能让实体和值对象协同工作的组织就是聚合,它用来确保这些领域对象在实现共同的业务逻辑时,能保证数据的一致性。

你可以这么理解,聚合就是由业务和逻辑紧密关联的实体和值对象组合而成的,聚合是数据修改和持久化的基本单元,每一个聚合对应一个仓储,实现数据的持久化。

byMe:

聚合:

按照一个功能/模块/业务对项目进行划分,将符合同一个功能/模块/业务的实体,值对象找出来,聚合到同一个领域内。

聚合就是由业务和逻辑紧密关联的实体和值对象组合而成的。

聚合属于战略设计上的一个概念,不直接对应代码实现,聚合在代码中的体现是聚合根。

聚合根

负责按照聚合的逻辑,将符合同一个业务逻辑的Entity,VO,聚合到一个class中。

如何设计聚合

image.png

第 1 步:

采用事件风暴,根据业务行为,梳理出在投保过程中发生这些行为的所有的实体和值对象,比如投保单、标的、客户、被保人等等。

第 2 步:

从众多实体中选出适合作为对象管理者的根实体,也就是聚合根。判断一个实体是否是聚合根,你可以结合以下场景分析:是否有独立的生命周期?是否有全局唯一 ID?是否可以创建或修改其它对象?是否有专门的模块来管这个实体。图中的聚合根分别是投保单和客户实体。

第 3 步:

根据业务单一职责和高内聚原则,找出与聚合根关联的所有紧密依赖的实体和值对象。构建出 1 个包含聚合根(唯一)、多个实体和值对象的对象集合,这个集合就是聚合。在图中我们构建了客户和投保这两个聚合。

第 4 步:

在聚合内根据聚合根、实体和值对象的依赖关系,画出对象的引用和依赖模型。这里我需要说明一下:投保人和被保人的数据,是通过关联客户 ID 从客户聚合中获取的,在投保聚合里它们是投保单的值对象,这些值对象的数据是客户的冗余数据,即使未来客户聚合的数据发生了变更,也不会影响投保单的值对象数据。从图中我们还可以看出实体之间的引用关系,比如在投保聚合里投保单聚合根引用了报价单实体,报价单实体则引用了报价规则子实体。

第 5 步:

多个聚合根据业务语义和上下文一起划分到同一个限界上下文内。这就是一个聚合诞生的完整过程了。

聚合的一些设计原则

《实现领域驱动设计》一书中对聚合设计原则的描述,原文是有点不太好理解的,我来给你解释一下。

1. 在一致性边界内建模真正的不变条件。

聚合用来封装真正的不变性,而不是简单地将对象组合在一起。聚合内有一套不变的业务规则,各实体和值对象按照统一的业务规则运行,实现对象数据的一致性,边界之外的任何东西都与该聚合无关,这就是聚合能实现业务高内聚的原因。

byMe: 聚合内的业务规则一般不变

聚合内的业务规则一般不变,实体和值对象都遵从于该业务逻辑。任何外界变化不会影响到聚合,以实现聚合的高聚合特性。

2. 设计小聚合

如果聚合设计得过大,聚合会因为包含过多的实体,导致实体之间的管理过于复杂,高频操作时会出现并发冲突或者数据库锁,最终导致系统可用性变差。而小聚合设计则可以降低由于业务过大导致聚合重构的可能性,让领域模型更能适应业务的变化。

byMe: 小聚合

尽量简单化聚合,防止聚合过于庞大,聚合越小,业务重构的成本越低。

3. 通过唯一标识引用其它聚合

聚合之间是通过关联外部聚合根 ID 的方式引用,而不是直接对象引用的方式。外部聚合的对象放在聚合边界内管理,容易导致聚合的边界不清晰,也会增加聚合之间的耦合度。

byMe: 防止聚合之间直接引用,而是通过唯一标识引用其他聚合

如果直接引用其他聚合对象,会增加耦合度,通过唯一标识聚合其他聚合根。

4. 在边界之外使用最终一致性

聚合内数据强一致性,而聚合之间数据最终一致性。在一次事务中,最多只能更改一个聚合的状态。如果一次业务操作涉及多个聚合状态的更改,应采用领域事件的方式异步修改相关的聚合,实现聚合之间的解耦(相关内容我会在领域事件部分详解)。

byMe: 同一个聚合内数据强一致性,聚合之间数据最终一致性。

5. 通过应用层实现跨聚合的服务调用

为实现微服务内聚合之间的解耦,以及未来以聚合为单位的微服务组合和拆分,应避免跨聚合的领域服务调用和跨聚合的数据库表关联。

byMe: 通过应用层实现跨聚合的服务调用

对于跨聚合之间的调用,放在应用层中,在聚合之间再加一层。

上面的这些原则是 DDD 的一些通用的设计原则,还是那句话:“适合自己的才是最好的。”在系统设计过程时,你一定要考虑项目的具体情况,如果面临使用的便利性、高性能要求、技术能力缺失和全局事务管理等影响因素,这些原则也并不是不能突破的,总之一切以解决实际问题为出发点。

相关文章

  • 领域驱动设计-聚合和聚合根

    聚合 领域模型内的实体和值对象就好比个体,而能让实体和值对象协同工作的组织就是聚合,它用来确保这些领域对象在实现共...

  • 设计能力 - 你如何划分领域边界

    学习完整课程请移步 互联网 Java 全栈工程师 【领域驱动设计】浅谈聚合的划分与设计 聚合以及聚合根是领域驱动设...

  • DDD 领域驱动设计学习(六)- 聚合和资源库

    聚合的定义 聚合(以及聚合根):聚合表示一组领域对象(包括实体和值对象),用来表述一个完整的领域概念。而每个聚合都...

  • 领域模型:聚合、聚合根

    聚合 聚合Aggregate就是一组相关对象的集合,我们把它作为数据修改和访问的单元。一个聚合包含聚合根、实体和值...

  • 实现领域驱动设计-聚合

    最难理解的模式 将实体和值对像在一致性边界之内组成聚合。所以理解聚合的关键的一致性边界,可以直接理解为RDB的事务...

  • 微服务架构设计模式(五)业务逻辑设计

    微服务架构中的业务逻辑设计 1、使用聚合设计领域模型 1.1 为什么要使用聚合 聚合拥有明确的边界 聚合将领域分为...

  • 领域驱动设计 DDD 实践

    背景 DDD 领域驱动设计,想必大家都已经耳熟能详了,经常能听到『事件风暴』、『聚合根』、『限界上下文』等等名词,...

  • DDD落地过程中关于聚合的思考

    前言 聚合是由实体和值对象组成的一个整体概念,聚合根就是组成这个聚合的一个实体。 聚合设计原则 参照沃恩弗农: 1...

  • Golang领域模型-聚合根

    前言:聚合是要把实体、值对象等聚合起来完成完整的业务逻辑的一个存在。聚合根据上下文边界与业务单一职责、高内聚等原则...

  • 什么是聚合根

    对领域概念做静态建模的时候,有一类概念被视为聚合根(root)。它有自己的生灭过程,数据和行为聚合于其上,有...

网友评论

      本文标题:领域驱动设计-聚合和聚合根

      本文链接:https://www.haomeiwen.com/subject/wvztoktx.html