04.领域驱动设计:了解聚合和聚合根,怎样设计聚合

目录

1、概述

2、聚合

3、聚合根

4、怎么设计聚合

4.1 聚合的构建过程主要步骤

第 1 步:采用事件风暴。

第 2 步:选出聚合根。

第 3 步:找出与聚合根关联的所有紧密依赖的实体和值对象。

第 4 步:画出对象的引用和依赖模型。

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

4.2 聚合的一些设计原则

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

2.设计小聚合。

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

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

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

5、总结

1.聚合的特点

2.聚合根的特点

3.实体的特点

4.值对象的特点

6、思考题


1、概述

在事件风暴中,我们会根据一些业务操作和行为找出实体(Entity)或值对象(ValueObject),进

而将业务关联紧密的实体和值对象进行组合,构成聚合,再根据业务语义将多个聚合划定到同一个

限界上下文(Bounded Context)中,并在限界上下文内完成领域建模

那你知道为什么要在限界上下文和实体之间增加聚合和聚合根这两个概念吗?它们的作用是什么?

怎么设计聚合?

2、聚合

在DDD中,实体和值对象是很基础的领域对象。实体一般对应业务对象,它具有业务属性和业务

行为;而值对象主要是属性集合对实体的状态和特征进行描述。

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

保这些领域对象在实现共同的业务逻辑时,能保证数据的一致性

可以理解,聚合就是由业务和逻辑紧密关联的实体和值对象组合而成的,聚合是数据修改和持久化

的基本单元,每一个聚合对应一个仓储,实现数据的持久化。

聚合有一个聚合根和上下文边界,这个边界根据业务单一职责和高内聚原则,定义了聚合内部应该

包含哪些实体和值对象,而聚合之间的边界是松耦合的。按照这种方式设计出来的微服务很自然就

是“高内聚、低耦合”的。

聚合在DDD分层架构里属于领域层,领域层包含了多个聚合,共同实现核心业务逻辑。聚合内实

体以充血模型实现个体业务能力,以及业务逻辑的高内聚。跨多个实体的业务逻辑通过领域服务来

实现,跨多个聚合的业务逻辑通过应用服务来实现。

3、聚合根

聚合根的主要目的是为了避免由于复杂数据模型缺少统一的业务规则控制,而导致聚合、实体之间

数据不一致性的问题。

如果把聚合比作组织,那聚合根就是这个组织的负责人。聚合根也称为根实体,它不仅是实体,还

聚合的管理者。

首先它作为实体本身,拥有实体的属性和业务行为,实现自身的业务逻辑

其次它作为聚合的管理者,在聚合内部负责协调实体和值对象,按照固定的业务规则协同完成共同

的业务逻辑。

最后在聚合之间,它还是聚合对外的接口人,以聚合根ID关联的方式接受外部任务和请求,在上下

文内实现聚合之间的业务协同。也就是说,聚合之间通过聚合根ID关联引用,如果需要访问其它聚

合的实体,就要先访问聚合根,再导航到聚合内部实体,外部对象不能直接访问聚合内实体。

4、怎么设计聚合

DDD领域建模通常采用事件风暴,它通常采用用例分析、场景分析和用户旅程分析等方法,通过

头脑风暴列出所有可能的业务行为和事件,然后找出产生这些行为的领域对象,并梳理领域对象之

间的关系,找出聚合根,找出与聚合根业务紧密关联的实体和值对象,再将聚合根、实体和值对象

组合,构建聚合

4.1 聚合的构建过程主要步骤

以保险的投保业务场景为例。

第 1 步:采用事件风暴。

根据业务行为,梳理出在投保过程中发生这些行为的所有的实体和值对象,比如投保单、标的、客

户、被保人等等。

第 2 步:选出聚合根。

从众多实体中选出适合作为对象管理者的根实体,也就是聚合根。

判断一个实体是否是聚合根,你可以结合以下场景分析:

  • 是否有独立的生命周期

  • 是否有全局唯一ID

  • 是否可以创建或修改其它对象

  • 是否有专门的模块来管这个实体

图中的聚合根分别是投保单和客户实体。

第 3 步:找出与聚合根关联的所有紧密依赖的实体和值对象。

根据业务单一职责和高内聚原则,找出与聚合根关联的所有紧密依赖的实体和值对象。

构建出 1 个包含聚合根(唯一)、多个实体和值对象的对象集合,这个集合就是聚合

在图中我们构建了客户和投保这两个聚合。

第 4 步:画出对象的引用和依赖模型

在聚合内根据聚合根、实体和值对象的依赖关系,画出对象的引用和依赖模型。

说明一下:投保人和被保人的数据,是通过关联客户 ID 从客户聚合中获取的,在投保聚合里它们

是投保单的值对象,这些值对象的数据是客户的冗余数据,即使未来客户聚合的数据发生了变更,

也不会影响投保单的值对象数据。

从图中我们还可以看出实体之间的引用关系,比如在投保聚合里投保单聚合根引用了报价单实体,

报价单实体则引用了报价规则子实体。

第 5 步:多个聚合,根据业务语义和上下文一起划分到同一个限界上下文内
4.2 聚合的一些设计原则
1.在一致性边界内,建模真正的不变条件。

聚合用来封装真正的不变性,而不是简单地将对象组合在一起。

2.设计小聚合。

如果聚合设计得过大,聚合会因为包含过多的实体,导致实体之间的管理过于复杂,高频操作时会

出现并发冲突或者数据库锁,最终导致系统可用性变差。而小聚合设计则可以降低由于业务过大导

致聚合重构的可能性,让领域模型更能适应业务的变化。

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

聚合之间是通过关联外部聚合根ID的方式引用,而不是直接对象引用的方式。

外部聚合的对象放在聚合边界内管理,容易导致聚合的边界不清晰,也会增加聚合之间的耦合度。

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

聚合内数据强一致性,而聚合之间数据最终一致性

在一次事务中,最多只能更改一个聚合的状态。如果一次业务操作涉及多个聚合状态的更改,应采

用领域事件的方式异步修改相关的聚合,实现聚合之间的解耦。

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

为实现微服务内聚合之间的解耦,以及未来以聚合为单位的微服务组合和拆分,应避免跨聚合的领

域服务调用和跨聚合的数据库表关联。

上面的这些原则是DDD的一些通用的设计原则,还是那句话:“适合自己的才是最好的。”

在系统设计过程时,你一定要考虑项目的具体情况,如果面临使用的便利性、高性能要求、技术能

力缺失和全局事务管理等影响因素,这些原则也并不是不能突破的,总之一切以解决实际问题为出

发点

5、总结

聚合、聚合根、实体和值对象,它们之间的联系和区别:

1.聚合的特点

高内聚、低耦合,它是领域模型中最底层的边界,可以作为拆分微服务的最小单位,但不建议你对

微服务过度拆分。

一个微服务可以包含多个聚合,聚合之间的边界是微服务内天然的逻辑边界。有了这个逻辑边界,

在微服务架构演进时就可以以聚合为单位进行拆分和组合了,微服务的架构演进也就不再是一件难

事了。

2.聚合根的特点

聚合根是实体有实体的特点,具有全局唯一标识有独立的生命周期。

一个聚合只有一个聚合根,聚合根在聚合内对实体和值对象采用直接对象引用的方式进行组织和协

调,聚合根与聚合根之间通过ID关联的方式实现聚合之间的协同。

3.实体的特点

有ID标识,通过ID判断相等性ID在聚合内唯一即可。状态可变,它依附于聚合根,其生命周期由

聚合根管理。

实体一般会持久化,但与数据库持久化对象不一定是一对一的关系

实体可以引用聚合内的聚合根、实体和值对象

4.值对象的特点

无ID,不可变,无生命周期,用完即扔。

值对象之间通过属性值判断相等性。它的核心本质是,是一组概念完整的属性组成的集合,用于

描述实体的状态和特征。

值对象,尽量只引用值对象

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

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

相关文章

P2246 SAC#1 - Hello World(升级版)

网址如下: P2246 SAC#1 - Hello World(升级版) - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 刚开始是用递归做的,虽然用了哈希表优化,但是超时,只得了50 后面想到了一个新的算法,时间复杂度…

喝酒筛子小游戏集合源码微信小程序喝酒骰子程序带流量主版本源码酒桌玩筛子源码

2023新版酒桌小游戏喝酒小程序源码-(流量主版本) 修改增加了广告位 根据文档直接替换,原版本没有广告位 直接上传源码到开发者端即可 通过后改广告代码,然后关闭广告展示提交,通过后打开即可 无广告引流 流量主版…

3338 蓝桥杯 wyz的数组IV 简单

3338 蓝桥杯 wyz的数组IV 简单 //C风格解法1&#xff0c;通过率50% #include<bits/stdc.h>int main(){std::ios::sync_with_stdio(false);std::cin.tie(nullptr);std::cout.tie(nullptr);int n; std::cin >> n;int ans 0;std::vector<int>a(n);for(auto &am…

必应聊天在当前安全搜索设置下不可用

使用Bing必应搜索引擎&#xff0c;想用必应AI聊天功能会提示&#xff1a;必应聊天在当前安全搜索设置下不可用。 当安全搜索设置设置为“严格”时&#xff0c;不支持必应聊天。 那么怎么修改安全搜索设置呢&#xff1f; 点击右上角的菜单图标&#xff0c;在下拉菜单里点击安全…

权威的健康养生与医学基础知识科普学习信息汇总

目录 1 关于健康与食物营养的权威网址1.1 世界卫生组织&#xff08;World Health Organization: WHO&#xff09;1.2 美国国家卫生研究院 (National Institutes of Health: NIH)1.3 澳大利亚政府健康门户 (Healthdirect)1.4 国际食品信息委员会 (International Food Informatio…

【Midjourney】内容展示风格关键词

1.几何排列(Geometric) "Geometric" 是一个与几何有关的词汇&#xff0c;通常用于描述与形状、结构或空间几何特征相关的事物。这个词可以涉及数学、艺术、工程、计算机图形学等多个领域。 使用该关键词后&#xff0c;图片中的内容会以平面图形拼接的方式展示&#…

Apache Shiro <= 1.2.4反序列化漏洞攻击 CVE-2016-4437 已亲自复现

Apache Shiro < 1.2.4反序列化漏洞攻击 CVE-2016-4437 已亲自复现 漏洞名称漏洞描述影响版本 漏洞复现环境搭建漏洞利用 修复建议总结 漏洞名称 漏洞描述 在 1.2.5 之前的 Apache Shiro 中&#xff0c;当未为“记住我”功能配置密钥时&#xff0c;远程攻击者可以通过未指定…

obsidian阅读pdf和文献——与zotero连用

参考&#xff1a; 【基于Obsidian的pdf阅读、标注&#xff0c;构建笔记思维导图&#xff0c;实现笔记标签化、碎片化&#xff0c;便于检索和跳转】 工作流&#xff1a;如何在Obsidian中阅读PDF - Eleven的文章 - 知乎 https://zhuanlan.zhihu.com/p/409627700 操作步骤 基于O…

武忠祥2025高等数学,基础阶段的百度网盘+视频及PDF

考研数学武忠祥基础主要学习以下几个方面的内容&#xff1a; 1.微积分:主要包括极限、连续、导数、积分等概念&#xff0c;以及它们的基本性质和运算方法。 2.线性代数:主要包括向量、向量空间、线性方程组、矩阵、行列式、特征值和特征向量等概念&#xff0c;以及它们的基本…

RK3568平台 of 操作函数获取设备树节点

一.of函数概述 Linux内核给我们提供了一系列的函数来获取设备树中的节点或者属性信息&#xff0c;这一系列的函数都有一个统一的前缀 ”of“ &#xff0c; 所以在很多资料里面也被叫做OF函数。 Linux 内核使用device_node 结构体来描述一个节点&#xff0c;此结构体定义在文件…

Python初学者学习记录——python基础综合案例:数据可视化——折线图可视化

一、案例介绍 效果一&#xff1a;2020年印美日新冠累计确诊人数 效果二&#xff1a;全国疫情地图可视化 效果三&#xff1a;动态GDP增长图 数据来源&#xff1a; 本案例数据全部来自《百度疫情实时大数据报告》&#xff0c;及公开的全球各国GDP数据 使用的技术&#xff1a; E…

C++爱好者的科目四易错点总结

科目四易错点总结 在科目四考试中&#xff0c;一部分内容是可以通过刷题快速掌握的&#xff0c;一部分内容缺因易混淆而降低我们的准确率&#xff0c;本文主要对后者进行总结&#xff0c;期待大家补充与指正。 注&#xff1a; 本文不是全部的知识点总结处 本文不是权威机构 本文…

张维迎《博弈与社会》笔记(3)导论:一些经济学的基础知识

这篇的主要内容介绍了经济学的基础知识吧。 经济学、社会学、心理学的区别 经济学与社会学的区别与共同点 经济学一般是从个人的行为出发解释社会现象&#xff08;from micro to macro&#xff09;。社会学的传统方法则是从社会的角度来解释个人的行为&#xff08;from macro…

硕士毕业论文如何体现自己的工作量

一、工作量是什么 工作量就是你在科研过程中做的所有工作量的体现&#xff0c;包括你对背景的调查&#xff0c;对问题的发现&#xff0c;你做的实验&#xff0c;提出的创新点。 notice&#xff1a;任何别人做的实验&#xff0c;提出的模型&#xff0c;都不能算是你的工作量。…

uniapp+vue3+ts --微信小程序tab导航可以上下滚动选中选项组件代码

uniappvue3ts --微信小程序tab导航可以上下滚动选中选项组件代码 废话不多说&#xff0c;直接上代码。 组件代码&#xff1a; <template><view class"scroll-tabs-container"><view class"radiusz bg-white pt-[10rpx] z-[999]" :class&…

文件包含漏洞长度截断

长度截断 文件漏洞的利用方式什么是长度截断通过实操理解00截断对版本要求更高一点&#xff0c;而长度截断则是利用了windows的系统漏洞&#xff0c;就是windows文件名&#xff08;就是文件名后缀之后&#xff09;之后如果有空格&#xff0c;或者是点都会被忽略掉&#xff0c;也…

Python tkinter (6) —— Listbox控件

Python的标准Tk GUI工具包的接口 tkinter系列文章 python tkinter窗口简单实现 Python tkinter (1) —— Label标签 Python tkinter (2) —— Button标签 Python tkinter (3) —— Entry标签 Python tkinter (4) —— Text控件 Python tkinter (5) 选项按钮与复选框 目录…

【并发编程】volatile原理

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;并发编程 ⛺️稳重求进&#xff0c;晒太阳 volatile原理实现是内存屏障&#xff0c;Memory Barrier 对volatile变量的写指令后会加入写屏障。对volatile变量的读指令前会加入读屏障 如何…

响应式Web开发项目教程(HTML5+CSS3+Bootstrap)第2版 例5-2 JavaScript 获取HTML元素对象

代码 <!doctype html> <html> <head> <meta charset"utf-8"> <title>JavaScript 获取 HTML 元素对象</title> </head><body> <input type"text" value"admin" /> <br> <input …

【深度学习:t-SNE 】T 分布随机邻域嵌入

【深度学习&#xff1a;t-SNE 】T 分布随机邻域嵌入 降低数据维度的目标什么是PCA和t-SNE&#xff0c;两者有什么区别或相似之处&#xff1f;主成分分析&#xff08;PCA&#xff09;t-分布式随机邻域嵌入&#xff08;t-SNE&#xff09; 在 MNIST 数据集上实现 PCA 和 t-SNE结论…