再谈一下DDD中的聚合设计

news2024/11/23 12:50:55

何为聚合

在领域模型中,一些实体或者值对象具有强而有力的业务关联关系,于是这些对象就组成了一个聚合,聚合内部的业务实体之间必须保证状态一致性。从技术角度来看,聚合是数据修改与持久化的基本单元,聚合内数据修改必须由聚合根统一组织,以确保每次数据修改都按照聚合内统一的业务规则来完成

聚合为什么存在

在问题域中,不同的业务实体之间存在一些强制的业务规则。例如:订单(Order)总金额=订单行(OrderItem)明细金额之和;一个投保单必然包含投保标的......

为了保证上面的业务一致性,所以DDD中就有了聚合。聚合就是为了保证业务一致性的。

使用聚合碰到的问题:

在DDD中聚合设计的过于臃肿庞大,成为了一个对象树。“聚合根”就是最上层的对象,里面包含许多子对象的数据组或者集合。聚合保存时经常出现事务失败的情况;聚合内部子对象的修改导致整个聚合都要随之变更。

在《实现领域驱动设计》中,也举了这么一个列子:

在scrum核心领域中使用聚合。作者给出了两种聚合的表示形态

 形态一:

Product被建模成一个非常大的聚合。此时Product作为一个根(root)对象而存在,它包含了所有的BacklogItem,Release和Sprint。

形态二:

将形态一中,一个大的Product聚合拆分成4个相对较小的聚合:Product、BacklogItem、Release、Sprint,它们都关联值对象ProductID。

很明显,形态二设计的更加合理。Product与BacklogItem、Release、Sprint根本不是强聚合关系。因为Product与BacklogItem、Release、Sprint不具有相同的生命周期,一个Product可以拥有多个Sprint,当Product存在时,并不是每一个Sprint都已经存在,第二个Sprint估计还不存在,反之,第二个Sprint结束了,Product很可能还没有完结。Product与BacklogItem、Release、Sprint就是松散的聚合关系,对于松散聚合关系应该设计成第二种形态。

形态三:

额外补充一下,大家都学过面相对象的分析与设计。大家会设计成形态三的样子。Product拥有自己的ID,BacklogItem、Release、Sprint则是关联一个ProductID。形态三与形态二都不承认“强聚合”关系的存在。组合与聚合都是特殊的关联关系 ,组合强调了整体与部分的生命周期是一致的,而聚合(弱聚合)的整体和部分之间在生命周期上没有什么必然的联系。有很多文章讲解他们区别,感兴趣的读者可以再温习一下。

如何设计聚合

原则一:强聚合设计成对象树的形态,也就是形态一;弱聚合则设计成多个聚合根引用主实体ID的形态——形态二。

学过OOA的开发应该知道“组合”与“聚合”的概念。组合就是一种强聚合,只有这种强聚合才能设计成对象树的形态(形态一),因为强聚合要保证一致性。反之,则建议拆解成多个聚合根,也就是形态二

1、如何区分“组合”与“聚合”:

组合是强聚合,内部实体具有不可违背的业务一致性关系,而且内部实体之间具有一致的生命周期。

例如在电商领域中,订单(order)与订单行(orderItem)就是强聚合,订单是聚合根,多个订单行形成子实体集合;订单(Order)总金额=订单行(orderItem)明细金额之和。但是在员工(Employee)与员工异动记录,则是弱聚合关系.  组织内部的一个员工(Employee)可以有多条“员工异动记录”,一个“员工异动记录”必然属于一个员工,但是员工异动记录与员工不具有相同的生命周期。

原则二:一个聚合内必须保证数据强一致性

这个也就是模型中真正的不变条件,是我们的业务规则的体现,我们在程序设计中会使用事务一致性来保证。思考一下,在程序设计中,是否需要“事务一致性“,如果没有,则应该怀疑这个聚合存在的合理性。

同时,在一个事务中,建议只修改一个聚合实例。

原则三:引用其他聚合的ID,而不是直接引用聚合

如何你明白形态三的设计,这一点应该很好理解。弱聚合设计成关联关系,你直接关联主实体的ID,而不是关联主实体。

 在BacklogItem中,直接存在属性值:productID,releaseID,sprintID。而不是直接存在对象product、release、sprint

实践举例

订单与订单行

背景:在大集团采购中,组织会批量采购原材料。例如某建筑公司,会批量采购水泥、钢筋、砖块、砂浆,该建筑公司会下单给可信任的供应商,形成一个大的订单, 而且订单总金额=Sum(订单子项金额)

在建模设计中,订单总金额=Sum(订单子项金额)是一个强制性约束,而且订单行必然属于一个订单,订单行都填写完毕后,该订单才是完整的;

系统在保存时,必须保证订单与订单行的一致性,所以这是一个强聚合。强聚合设计成对象树的形态,也就是形态一.

员工与年度考核记录

员工与自己的年度考核记录是弱聚合关系。一个员工可以有多个年度考核记录;员工每考核一次就多一条考核记录,但是考核记录与员工不具有相同的生命周期。弱聚合则设计成多个聚合根引用主实体ID的形态——形态二,我更加倾向于形态三。

总结

聚合的设计体现了一个开发者领域建模的能力,只要大家分清强聚合与弱聚合,基本就可以舍弃掉不需要的臃肿聚合设计。而强聚合则是实体间具有不可违背的业务一致性关系,而且内部实体之间具有一致的生命周期。

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

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

相关文章

docker实践作业

1.安装docker服务,配置镜像加速器 2.下载系统镜像(Ubuntu、 centos) 3.基于下载的镜像创建两个容器 (容器名一个为自己名字全拼,一个为首名字字母) 4.容器的启动、 停止及重启操作 5.怎么查看正在运行的容器…

SpeedBI数据可视化工具:浏览器上做分析

SpeedBI数据分析云是一种在浏览器上进行数据可视化分析的工具,它能够将数据以可视化的形式呈现出来,并支持多种数据源和图表类型。 所有操作,均在浏览器上进行 在浏览器中打开SpeedBI数据分析云官网,点击【免费使用】进入&#…

Faster RCNN网络数据流总结

前言 在学习Faster RCNN时,看了许多别人写的博客。看了以后,对Faster RCNN整理有了一个大概的了解,但是对训练时网络内部的数据流还不是很清楚,所以在结合这个版本的faster rcnn代码情况下,对网络数据流进行总结。以便…

生成式AI将催生出大量新的就业机会,倒逼14亿员工学习掌握新技能

尽管IBM的研报指出生成式AI的普及将为未来三年内的14亿劳动力带来必须学习和掌握新技能的挑战,但它也强调这股浪潮不会引发失业潮,相反,它将催生出大量新的就业机会。生成式AI被认为将在各种商业模式中发挥重要作用,为企业提供了利…

STM32CubeMx配置HAL库PWM

PWM简介 PWM(Pulse Width Modulation)是脉冲宽度调制的缩写,是一种利用微处理器的数字输出来对模拟电路进行控制的技术。PWM的原理是 通过调节占空比来调节脉冲宽度,从而改变输出电压的大小。波形图如下 PWM的两个重要参数为频率和占空比。频率是周期…

【最新附安装包】UG NX2023安装教程(CAD/CAM)

软件下载 软件:UG NX版本:2023语言:简体中文大小:10.78G安装环境:Win11/Win10/Win8/Win7硬件要求:CPU3.0GHz 内存8G(或更高)下载通道①百度网盘丨64位下载链接:https://pan.baidu.c…

(动态规划) 剑指 Offer 10- II. 青蛙跳台阶问题 ——【Leetcode每日一题】

❓剑指 Offer 10- II. 青蛙跳台阶问题 难度:简单 一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶。求该青蛙跳上一个 n 级的台阶总共有多少种跳法。 答案需要取模 1e97(1000000007),如计算初始结果为:1…

2023企业数智化转型的正确打开方式是什么?他这样说(三)

哈喽~又见面了大家!上两期我们说到了数据在数智化转型中的重要性以及监控在数智化转型中的角色,戳这里↓↓↓,一键回放精彩内容 2023企业数智化转型的正确打开方式是什么?他这样说(一)https://mp.csdn.net…

MacBook 上的 Asahi Linux 将基于 Fedora Linux

MacBook 上的 Asahi Linux 将基于 Fedora Linux Asahi Linux 旨在将 Linux 移植到使用 M1、M2 等苹果硅芯片的 Mac 电脑上。它最初是基于 Arch Linux 的软件包构建的,采用 Arch Linux ARM,添加了自己的覆盖包资源库,并将所有的集成工作打包到…

支持4KHz回报的电竞鼠标,游戏操作更精准,雷柏VT950Pro上手

雷柏这两年推出的V系列外设很受还原,配合新近推出的4K电竞游戏技术,非常适合在高分辨率的显示器上玩游戏。目前很多雷柏经典的鼠标型号,也都出了新版本,设计更加炫酷,还可以支持4K了,配上一只4K接收器就可以…

elastic-job源码- job自动装配

版本&#xff1a;3.1.0-SNAPSHOT git地址&#xff1a;GitHub - apache/shardingsphere-elasticjob: Distributed scheduled job framework Maven 坐标 1 2 3 4 5 <dependency> <groupId>org.apache.shardingsphere.elasticjob</groupId> <artif…

vite+vue3使用@路径,报错处理

报错原因&#xff1a;未配置 符号为指定路径别名&#xff0c;直接使用导致 处理方法&#xff1a; 安装path模块&#xff1a; npm install --save-dev types/node修改vite.config.ts import { defineConfig } from vite import vue from vitejs/plugin-vue import path from…

Hope.money:新兴DeFi项目如何重新定义稳定币生态的未来?

联储加息导致金融市场紧缩&#xff0c;Terra、3AC、FTX等知名中心化机构未能妥善应对而暴雷&#xff0c;并重创了整个加密货币市场&#xff0c;导致参与者损失惨重。这些事件揭示了中心化机构的局限&#xff0c;投资者对其资产掌控权的担忧愈发强烈。 自2018年首个DeFi协议Com…

Java算法:对角线遍历

Java算法&#xff1a;对角线遍历 学习目标&#xff1a;对角线遍历算法算法要求算法思路算法实现 学习目标&#xff1a;对角线遍历算法 每日初级算法&#xff1a;对角线遍历 算法要求 给你一个大小为 m x n 的矩阵 mat &#xff0c;请以对角线遍历的顺序&#xff0c;用一个数组…

使用 Feature Flags 与可观测工具实现数据库灰度迁移

场景描述 很多企业会遇到数据库升级、或数据库迁移的情况&#xff0c;尤其是在自建数据库服务向云数据库服务、自建机房向云机房、旧数据库向新数据库迁移等场景。 然而&#xff0c;我们需要在整个移植过程中保证其稳定性、避免数据遗失、服务宕机等情况&#xff0c;最常见的移…

PHP求职招聘系统Dreamweaver开发mysql数据库web结构php编程计算机网页

一、源码特点 PHP 求职招聘系统是一套完善的web设计系统&#xff0c;对理解php编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。 源码 https://download.csdn.net/download/qq_41221322/88240283 论文 https://down…

Python土力学与基础工程计算.PDF-隧道涌水量

Python 求解代码如下&#xff1a; 1. # 定义参数 2. A 2000 # 地表面积&#xff0c;单位&#xff1a;平方米 3. S 10 # 截面积&#xff0c;单位&#xff1a;平方米 4. h 500 # 年地下径流深度&#xff0c;单位&#xff1a;毫米 5. 6. # 转换单位 7. h h / 1000 # 单…

Linux 中查看文件第n行内容的命令(实战案例)

Linux 中查看文件第n行内容的命令实战案例 方法1&#xff1a; head -m filename | tail -1 //查看filename文件的第m行&#xff08;tail -1 是数字1&#xff09; head -n &#xff08;数字&#xff09;&#xff08;文件名&#xff09;&#xff1a;数字为正数 显示前多少行的文…

React学习记录

一、简介 1、React是什么&#xff1f; 一个将数据渲染为HTML视图的开源JavaScript库&#xff0c;操作DOM呈现页面。 2、特点 采用组件化模式&#xff0c;声明式编码&#xff0c;提高开发效率及组件复用率在react native中可使用react语法进行移动端开发使用虚拟DOM优秀的di…

数据结构之——(手撕)顺序表

本章会介绍的知识点如下图&#xff1a; 1&#xff1a; 顺序表的概念&#xff1a;顺序表是用一段物理地址连续的存储单元依次存储数据的线性结构&#xff0c;通常我们使用数组来表示&#xff0c;对数组进行增删查改。 顺序表的结构&#xff1a;逻辑结构与物理结构都是内存中一块…