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

news2025/1/18 8:49:37

目录

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.coloradmin.cn/o/1416508.html

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

相关文章

web前端项目-五子棋【附源码】

五子棋(人机对弈) 本项目【五子棋】是一款人机对弈的策略型棋类游戏。可以选择落子方;游戏难度和是否显示落子次序。游戏双方分别使用黑白两色的棋子,在棋盘直线与横线的交叉点上进行对弈。五子棋可以促进大脑发育、提高思维能力…

go语言基础之泛型

1.泛型 泛型是一种独立于所使用的特定类型的编写代码的方法。使用泛型可以编写出适用于一组类型中的任何一种的函数和类型。 1.1 为什么需要泛型 func reverse(s []int) []int {l : len(s)r : make([]int, l)for i, e : range s {r[l-i-1] e}return r }fmt.Println(reverse…

Docker—入门及Centos7安装

1、Docker入门 1.1、Docker是什么? Docker是基于Go语言实现的云开源项目。 Docker的主要目标是“Build,Ship,and Run Any App,Anywhere”,也就是通过对应组件的封装、分发、部署、运行等生命周期的管理,使用户的APP&…

指数计算(填空)

解题思路: 7的2020次方很大,需要用BigInteger来进行运算。 pow用来算指数运算。 remainder用来算BigInteger之间的取余。 解题代码: public static void main(String[] args) {BigInteger xnew BigInteger ("7");BigInteger ynew…

Tools工具安装及模板制作

Tools工具: 如何安装tools 1、右键单击——tools——挂载tools 2、把光盘里面的内容挂载到系统的临时挂载目录里面 mount /dev/cdrom /mnt 先卸载光盘 安装zip包 ********************************************** 使用yum源 1、挂载光盘 2、配置yum 写文件 安装…

java servlet勤工助学家教管系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 java servlet 勤工助学家教管系统是一套完善的java web信息管理系统 serlvetdaobean mvc 模式开发 ,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myecli…

Vite+Vue3使用Vue-i8n笔记

一、下载依赖 vue-i18n yarn add vue-i18n创建存放语言文件的目录 以及配置文件的配置 我是在src/lang 新建index.ts、cn.ts、en.ts以及test文件夹其中再分别新建cn.ts以及en.ts /lang/index.ts 用于导出vue-i18n需要的配置对象 import en from "./en.ts"; import…

(八)循环控制中的break和continue关键字

文章目录 break提前结束整个循环示例代码现象 continue提前结束本次循环示例代码现象 break提前结束整个循环 示例 代码 #include <stdio.h>int main() {int numOfPerson ;int totalmoney 0;int money ;printf("这是一个使用break关键字的程序\n");for(numO…

2024年阿里云幻兽帕鲁Palworld游戏服务器优惠价格表

自建幻兽帕鲁服务器租用价格表&#xff0c;2024阿里云推出专属幻兽帕鲁Palworld游戏优惠服务器&#xff0c;配置分为4核16G和4核32G服务器&#xff0c;4核16G配置32.25元/1个月、10M带宽66.30元/1个月、4核32G配置113.24元/1个月&#xff0c;4核32G配置3个月339.72元。ECS云服务…

【Git配置代理】Failed to connect to github.com port 443 问题解决方法

前言&#xff1a; 在学习代码审计时&#xff0c;有时会需要使用git去拉取代码&#xff0c;然后就出现了如下错误 看过网上很多解决方法&#xff0c;觉得问题的关键还是因为命令行在拉取/推送代码时并没有使用VPN进行代理。 解决办法 &#xff1a; 配置http代理&#xff1a;…

前端canvas项目实战——简历制作网站(三)——右侧属性栏(线条宽度样式)

目录 前言一、效果展示二、实现步骤1. 实现线条宽度&#xff08;strokeWidth&#xff09;的属性模块2. 实线线条样式&#xff08;strokeDashArray&#xff09;的属性模块3. 意料之外的“联动” 三、Show u the code后记 前言 上一篇博文中&#xff0c;我们初步实现了右侧属性栏…

理顺 QR 分解算法

咱们网站的这个公式编辑器&#xff0c;估计是后台生成图片后贴回来的&#xff0c;固定分辨率而且分辨率不高。 还不如先离线 latex 生成 pdf 后再截图上来 1. Why QR When A and b are known, to solver the minimization of , where . The reduction of A to various canoni…

【计算机网络】概述|分层体系结构|OSI参考模型|TCP/IP参考模型|网络协议、层次、接口

目录 一、思维导图 二、计算机网络概述 1.计算机网络定义、组成、功能 2.计算机网络分类 3.计算机网络发展历史 &#xff08;1&#xff09;计算机网络发展历史1&#xff1a;ARPANET->互联网 &#xff08;2&#xff09;计算机网络发展历史2&#xff1a;三级结构因特网 …

时序预测 | MATLAB实现ICEEMDAN-SSA-GRU、ICEEMDAN-GRU、SSA-GRU、GRU时间序列预测对比

时序预测 | MATLAB实现ICEEMDAN-SSA-GRU、ICEEMDAN-GRU、SSA-GRU、GRU时间序列预测对比 目录 时序预测 | MATLAB实现ICEEMDAN-SSA-GRU、ICEEMDAN-GRU、SSA-GRU、GRU时间序列预测对比预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 时序预测 | MATLAB实现ICEEMDAN…

详解SpringCloud微服务技术栈:ElasticSearch实践2——RestClient查询并处理文档

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位大四、研0学生&#xff0c;正在努力准备大四暑假的实习 &#x1f30c;上期文章&#xff1a;详解SpringCloud微服务技术栈&#xff1a;ElasticSearch搜索结果处理&#xff08;排序、分页、高亮&#xff09; &#x1f4da;订…

kali系统入侵电脑windows(win11系统)渗透测试,骇入电脑教学

本次渗透测试将使用kali虚拟机&#xff08;攻击机&#xff09;对本机&#xff08;靶机&#xff09;进行入侵并监控屏幕 声明&#xff1a;本篇仅仅是将本机作为靶机的一次简易渗透测试&#xff0c;实际情况中基本不可能出现如此简单的木马骇入&#xff08;往往在上传木马时就被防…

Unity中URP下逐顶点光照

文章目录 前言一、之前额外灯逐像素光照的数据准备好后&#xff0c;还有最后的处理二、额外灯的逐顶点光照1、逐顶点额外灯的光照颜色2、inputData.vertexLighting3、surfaceData.albedo 前言 在上篇文章中&#xff0c;我们分析了Unity中URP下额外灯&#xff0c;逐像素光照中聚…

vue3之echarts3D环柱图

vue3之echarts3D环柱图 效果&#xff1a; 核心代码&#xff1a; <template><div class"container"><div ref"chartRef" class"charts"></div></div> </template><script lang"ts" setup&g…

通讯录小项目(上)

Start And Stick 通讯录的实现有很多种方式&#xff0c;今天我们将用结构体实现简单的通讯录项目功能。包括通讯录的增、删、查、改等功能。 思路&#xff1a; 此次代码文件分别为&#xff1a; 文件名用途sqlist.h用于函数和结构体的声明sqlist.c用于函数的实现test.c用于通讯…

【数据结构四】栈与Stack详解

目录 栈与Stack 1.实现一个自己的栈 2.Stack的基本使用 3.栈的一些oj题训练 4.栈&#xff0c;虚拟机栈&#xff0c;栈帧的区别 栈与Stack 栈 &#xff1a;一种特殊的线性表&#xff0c;其 只允许在固定的一端进行插入和删除元素操作 。进行数据插入和删除操作的一端称为栈顶…