什么是聚合根和聚合

news/2025/1/7 14:29:25/文章来源:https://www.cnblogs.com/chenshibao/p/18644830

实体和值对象组成聚合,再根据业务,将多个聚合划定到同一限界上下文,并在限界上下文内完成领域建模。
聚合只是单纯将一些共享父类、密切关联的对象聚集成一个对象树吗?如果是这样,对于存在于这个树中的对象,有没有一个实用的数目限制? 既然一个聚合可以引用另一个聚合,是否可以深度遍历下去,并且在此过程中修改对象? 聚合的不变条件和一致性边界是什么意思?

1 聚合

  • 实体一般对应业务对象,具有业务属性和业务行为
  • 值对象主要是属性集合,描述实体的状态和特征

但都只是个体化对象,其行为表现出的是个体能力

1.1 意义

领域模型内的实体和值对象好比个体,而能让实体和值对象协同工作的组织就是聚合,用来确保这些领域对象在实现共同的业务逻辑时,能保证数据的一致性。
聚合由业务和逻辑紧密关联的实体和值对象组合而成,是数据修改和持久化的基本单元,每个聚合对应一个仓储,实现数据的持久化。

聚合有一个聚合根和上下文边界:

  • 该边界根据业务单一职责和高内聚原则,定义了聚合内部应该包含哪些实体和值对象
  • 聚合之间的边界是松耦合的

按这种方式设计出来的微服务自然就是高内聚、低耦合。
聚合属于领域层,领域层包含多个聚合,共同实现核心业务逻辑。聚合内的实体以充血模型实现个体业务能力,以及业务逻辑的高内聚。

跨多个实体的业务逻辑通过领域服务来实现,跨多个聚合的业务逻辑通过应用服务来实现:

  • 有的业务需同一聚合的A和B两个实体共同完成,就可将这段业务逻辑用领域服务实现
  • 有的业务需聚合C和聚合D中的两个服务共同完成,使用应用服务来组合这俩服务

2 聚合根

为避免由于复杂数据模型缺少统一的业务规则控制,而导致聚合、实体之间数据不一致。
传统数据模型中的每一个实体都是同级对等,若任由实体无管控地调用数据修改,可能导致实体之间数据逻辑的不一致。而若使用锁则会增加代码复杂度,降低系统性能。

若把聚合比作组织,则聚合根就是该组织负责人。聚合根也称为根实体,它不仅是实体,还是聚合的管理者。

  • 作为实体,拥有实体的属性和业务行为,实现自身的业务逻辑
  • 作为聚合的管理者,在聚合内部负责协调实体和值对象按照固定业务规则协同完成共同的业务逻辑

在聚合间,它还是聚合对外的接口人,以聚合根ID关联的方式接受外部任务和请求,在上下文内实现聚合之间的业务协同。即聚合间通过聚合根ID关联引用,若需要访问其它聚合的实体,就要先访问聚合根,再导航到聚合内部实体,外部对象不能直接访问聚合内实体

2.1 电商案例

典型的聚合根:库存、商品、订单等。

以订单为例,订单在聚合里是聚合根,与订单关联的有订单明细和收货地址:

  • 订单明细包括商品ID、商品名称、价格及数量等。由于订单明细是多个,它是一个集合,它被设计为实体,被订单引用
  • 订单只有一个收货地址,收货地址的值源于你的个人中心维护的收货地址,收货地址只能被整体替换,所以设计为值对象

3 聚合设计案例

DDD领域建模通常采用事件风暴,采用用例分析、场景分析和用户旅程分析等方法,通过头脑风暴列出所有可能的业务行为和事件,然后找出产生这些行为的领域对象,并梳理领域对象之间的关系,找出聚合根,找出与聚合根业务紧密关联的实体和值对象,再将聚合根、实体和值对象组合,构建聚合

image

  1. 采用事件风暴,根据业务行为,梳理出在投保过程中发生这些行为的所有的实体和值对象
  2. 从众多实体中选出适合作为对象管理者的根实体(聚合根)。判断一个实体是否是聚合根,可分析:是否有独立生命周期?是否有全局唯一ID?是否可创建或修改其它对象?是否有专门模块管这个实体
  3. 根据业务单一职责和高内聚原则,找出与聚合根关联的所有紧密依赖的实体和值对象。构建出 1 个包含聚合根(唯一)、多个实体和值对象的对象集合,这个集合就是聚合
  4. 在聚合内根据聚合根、实体和值对象的依赖关系,画出对象的引用和依赖模型。

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

  • 多个聚合根据业务语义和上下文一起划分到同一个限界上下文内。

4 设计原则

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

要从限界上下文中发现聚合,需要了解模型中真正的不变条件,才能决定什么样的对象可以放在一个聚合。不变条件表示一个业务规则,该规则应该总是保持一致。

有多种类型的一致性:

  • 事务一致性 要求立即性和原子性
  • 最终一致性

在讨论不变条件时,我们讨论的是事务一致性。我们可能有以下不变条件:

聚合边界之内的所有内容组成一套不变的业务规则,任何操作都不能违背这些规则。边界之外的任何东西与该聚合都无关。因此,聚合表达了与事务一致性边界相同的意思。该例中,AggregateTypel拥有3个int属性,任何聚合都可拥有不同类型的属性。

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

4.2 优先小聚合

聚合设计过大,会因为包含过多实体,导致实体间管理复杂,高频操作时出现并发冲突或数据库锁,即便能保证事务成功执行,依然有可能限制系统的性能和可伸缩性。

小聚合则可降低由于业务过大导致聚合重构的可能性,让领域模型更能适应业务变化。

得多“小”呢?

最极端的,一个聚合只有全局标识和单个属性,当然,这并非推荐的做法(除非正是需求所在)。推荐使用根实体(Root Entity)表示聚合,其中只包含最小数量的属性或值类型属性。

哪些属性是必需的?

最简单的:必须与其他属性保持一致的。比如,一个Product拥有name、description属性,它们需要保持一致,将它们放在两个不同的聚合中根本无意义。修改name时,很可能也会同时修改description。若只修改其一,多半是在修改语法上的错误或使description能更匹配name。

在聚合中,若认为有些被包含的部分应该建模成实体,怎么办?

该部分是否:

  • 会随时间而改变

  • 或能被全部替换

    若可被全部替换,请将其建模成值对象,而非实体
    很多时候,建模成实体的概念都可重构成值对象。优先选用值对象并非意味着聚合就是不变的,因为当值对象属性被替换成其他值时,根实体也就随之改变。

将聚合的内部建模成值对象有很多好处:

  • 据所选用持久化机制,值对象可随根实体而序列化,而实体则需单独的存储区域并予以跟踪
  • 实体还会带来一些不必要操作,如在使用Hibernate时,需对多表联合查询,而对单表读取快得多,而使用值对象也更方便安全
  • 由于值对象不变,测试也相对简单

小聚合不仅有性能和可伸缩性上的好处,它还有助于事务成功执行,即可减少事务提交冲突。系统可用性也得到增强。

在你的领域中,迫使你设计大聚合的不变条件约束并不多。遇到这种情况,可考虑添加实体或集合,但始终都应将聚合设计得尽量小。

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

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

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

聚合内数据强一致性,聚合间数据最终一致性。
一次事务中,最多只能更改一个聚合的状态。若一次业务操作涉及多个聚合状态的更改,应采用领域事件异步修改相关的聚合,实现聚合间的解耦

在不持有对象引用的情况下,不能修改其他聚合,因此可避免在同一事务中修改多个聚合。但这样限制性太强,因为在领域模型中,我们总需要对象之间的关联关系来完成任务。对此,又该怎么办呢?

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

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

5 总结

  • 聚合的特点 高内聚、低耦合,它是领域模型中最底层的边界,可作为拆分微服务的最小单位,但不推荐过度拆分。在对性能有极致要求的场景中,聚合可独立作为一个微服务,以满足版本的高频发布和弹性伸缩要求。 一个微服务可包含多个聚合,聚合之间的边界是微服务内天然的逻辑边界。有了该逻辑边界,在微服务架构演进时就可以聚合为单位进行拆分和组合。
  • 聚合根的特点 聚合根是实体,有实体的特点,具有全局唯一标识,有独立的生命周期。一个聚合只有一个聚合根,聚合根在聚合内对实体和值对象采用直接对象引用的方式进行组织和协调,聚合根与聚合根之间通过ID关联的方式实现聚合之间的协同。
  • 实体的特点 有ID标识,通过ID判断相等性,ID在聚合内唯一即可。状态可变,它依附于聚合根,其生命周期由聚合根管理。实体一般会持久化,但与数据库持久化对象不一定是一对一的关系。实体可引用聚合内的聚合根、实体和值对象。
  • 值对象的特点 无ID,不可变,无生命周期,用完即扔。值对象之间通过属性值判断相等性。它的核心本质是值,是一组概念完整的属性组成的集合,用于描述实体的状态和特征。值对象尽量只引用值对象。

出自:https://cloud.tencent.com/developer/article/1791310

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/862106.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Java 温故而知新系列】基础知识-03 基本类型对应之包装类

1、包装类都有哪些? 基本类型都有对应的包装类型,这些包装类提供了一种面向对象的方式来处理基本数据类型,允许它们被用于需要对象的场景,如集合框架、泛型等。 对应关系:基本类型包装类型boolean Booleanbyte Bytechar Characterfloat Floatint Integerlong Longshort Sh…

[深度学习] 大模型学习1-大语言模型基础知识

大语言模型(Large Language Model,LLM)是一类基于Transformer架构的深度学习模型,主要用于处理与自然语言相关的各种任务。简单来说,当用户输入文本时,模型会生成相应的回复或结果。它能够完成许多任务,如文本续写、分类、摘要、改写、翻译等。常见的LLM包括GPT、LLaMA等…

昆明理工大学材料调剂参考书-材料测试

昆明理工大学材料调剂昆明理工大学材料调剂

小程序信息收集

引子:本章对常见的小程序信息收集方式做一介绍。免责声明:本文章仅用于交流学习,因文章内容而产生的任何违法&未授权行为,与文章作者无关!!! 附:完整笔记目录~ ps:本人小白,笔记均在个人理解基础上整理,若有错误欢迎指正! 四、小程序信息收集引子:本章对常见的…

2025 胜券在握

这两天我看了一部电影《胜券在握》,这是一部年末由刘循子墨执导,邓超、邓家佳等主演的电影,讲述了一个关于35岁裁员后,通过人工智能创业的故事。该片讲述了在科技公司工作了十年的元老级员工白胜被暴力开除,手握高期权却无法兑现的他暗设骗局,试图重回公司,只为苟住100天…

2024总结与展望--Empirefree

26岁的今年总是惊喜与遗憾伴随我的一年目录🔥1. 年终总结1.1.学习计划1.2. 生活计划1.3 个人总结🔥2. 未来展望 🔥1. 年终总结 1.1.学习计划 ​ 今年没有学习,在弄公司业务,感觉自己涉及的业务面还是很浅,熟悉了不少的业务。 1.2. 生活计划身体锻炼:拉胯,今年身体锻…

某某书主页参数加密分析

主页:aHR0cHM6Ly93d3cueGlhb2hvbmdzaHUuY29tL2V4cGxvcmU= 打开某某书主页,打开浏览器开发者工具,随便点击一个主页tab栏,如影视,找到相关接口为: aHR0cHM6Ly9lZGl0aC54aWFvaG9uZ3NodS5jb20vYXBpL3Nucy93ZWIvdjEvaG9tZWZlZWQ= 根据测试,需逆向请求头中的 X-S 参数,全局搜…

Gamma阶段——第15周Scrum Meeting记录

Gamma阶段——第15周Scrum Meeting记录 1.目前进度: (1)完成游戏整体开发,修复部分BUG,可以初步实现面向玩家的使用; (2)进行集成测试,查找不足; (3)邀请部分玩家参与测试以更好的优化软件 2.目前团队中存在的问题: (1)未能及时同步工作进度,导致需要额外花时间…

MQTT不同ClientID订阅同一个topic消息独立接收

EMQX 使用宝塔安装的docker版本的emqx(Docker应用) 1.0.1 方案一(弃用):mountpoint 旧版本中的配置项,用于为客户端的 MQTT 消息主题动态添加前缀(如客户端 ID)。这一功能在 EMQX 4.x 版本中有效,但在 EMQX 5.x 中被废弃,原因是 EMQX 5.x 的架构和配置方式全面升级,不…

AppGallery编辑推荐:带来应用探索新风尚

近日,原生鸿蒙应用市场发布的“AppGallery Awards 年度影响力应用与游戏”近日隆重揭晓,标志着原生鸿蒙应用市场在用户体验、视觉设计、创新实践等方面迈出了重要一步。 此次年度奖项的评选与发布,依托于AppGallery全新推出的“编辑推荐”机制,即由编辑团队从专业视角精选优…

Web 前端面试指南与高频考题解析

Web 前端面试指南与高频考题解析 准备:简历编写和面试前准备 一般来说,跳槽找工作要经历投递简历、准备面试、面试和谈 offer 四个阶段。其中面试题目会因你的等级和职位而异,从入门级到专家级,广度和深度都会有所增加。不过,不管什么级别和职位,面试题目一般都可以分类为…

内华达大地测量实验室gnss数据半自动化下载

内华达大地测量实验室GNSS数据半自动化下载 前言目的:继上篇GNSS时序形变位移数据下载,介绍了内华达网站GNSS位移数据如何手动交互进行下载。后面发现若自己需要下载很多站点的数据,我要通过手动一个个去点击下载不太方便。为此自己设计了一个根据站点名字文本文件进行批量下…