《软件方法(下)》8.3.4.6 DDD话语“聚合”中的伪创新(1)

DDD领域驱动设计批评文集

做强化自测题获得“软件方法建模师”称号

《软件方法》各章合集


8.3 建模步骤C-2 识别类的关系

8.3.4 识别关联关系

8.3.4.6 DDD话语“聚合”中的伪创新

DDD话语中也有“聚合”。Eric Evans的“Domain-Driven Design: Tackling Complexity in the Heart of Software”书中是这样说的:

An AGGREGATE is a cluster of associated objects that we treat as a unit for the purpose of data changes. Each AGGREGATE has a root and a boundary. ……The root is the only member of the AGGREGATE that outside objects are allowed to hold references to, ……

一个AGGREGATE是一簇相关联的对象,我们把它作为数据变化的单元来对待。每个AGGREGATE有一个根和一个边界。……根是AGGREGATE的成员中唯一允许外部对象持有引用的,……

以上文字提到了两个概念:

(1)aggregate(聚合体),指整个聚合/组合结构。

(2)aggregate root(聚合根),聚合/组合结构中扮演整体的对象。

先阐明本书对于这两个概念的观点:

两者都不提倡使用。其中,aggregate属于冗余概念,aggregate root属于错误概念。

接下来说一下原因。

我们以图8-138中Grady Booch关于系统结构的一段隐喻作为素材,比较aggregate、aggregate root以及前文所说的UML的aggregation(composition)。

图片

图8-138 摘自《面向对象分析与设计(原书第2版)》,Grady Booch 著;冯博琴 等 译,英文原版出版于1994年

把图8-138的内容用类图和组合结构图表达如图8-139,并在标出三个用语的位置。

图片

图8-139 三个用语的位置

(1)aggregation是本质概念

aggregation指类之间的“整体-部分”关联,可以称为“聚合关联”。

例如,图8-139中,“植物”和“根”、“茎”、“叶”存在aggregation关联,说明可能会存在“植物”对象,它的组成部件是“根”、“茎”、“叶”对象。

根据前文提到的本书观点,“整体-部分”关联就是“组合(composition)”,因此,图8-139以及后面的图形都会使用实心菱形。

(2)aggregate是冗余概念

在面向对象建模领域,aggregate并非Eric Evans在“Domain-Driven Design”书中首先使用。

1991年,James Rumbaugh等人的书“Object-Oriented Modeling and Design”中就阐述了aggregation和aggregate,如图8-140所示。

图片

图8-140 摘自Object-Oriented Modeling and Design,James Rumbaugh et al. ,1991

可以看到,图8-140中的标题是Aggregation,不是Aggregate。

1999年出版的“The Unified Modeling Language Reference Manual(UML参考手册)”第1版中,也有“aggregate”词条,但内容只有一句话,接下来的“aggregation”词条的内容却达4页之多,如图8-141。

图片

图8-141 摘自The Unified Modeling Language Reference Manual,James Rumbaugh et al. ,1999

可以看出来,UML规范认为aggregation才是本质的概念。

为什么两者待遇不一样?

因为aggregate只是类(类图上的结点)在aggregation关联(类图上的边)中扮演的一个角色。同一个类可能在某个aggregation关联中扮演aggregate(聚合体,整体),在另外一个aggregation关联中扮演part(部件)。

我们进一步扩展图8-139中的类图,得到图8-142。可以看到,包括“植物”在内的很多类,既扮演整体,也扮演部分。

图片

图8-142 既扮演整体又扮演部分

一个对象可能由很多部件(最小部件是其简单属性值)组成,同时它又可以成为更大对象的部件。

离开特定的关联,指着一个对象说“它是整体”、“它是aggregate”或“它是aggregate root”,都是不合适的,除非只存在一级整体-部分结构。

这也是现在DDD实践中aggregate的现状——再多一级的话,不妨祭出“性能”遮羞布遮掩过去——“这得加载多少数据啊,会影响性能的!”。

即使只存在一级整体-部分结构,也没有必要在类上标注“aggregate root”,或者圈一个边界说这是一个aggregate,关系上的菱形标记已经提供了足够的信息。

图片

图8-143 这两个标记都是冗余的

同理,如果要体现某些领域驱动设计实践投资少、见效快、产量高、门槛低、仪式感十足的特点,就可以考虑图8-143的标记。

(3)aggregate root是伪创新

在“Domain-Driven Design”之前的软件开发书籍中,没有出现aggregate root的说法,aggregate root应该是Eric Evans的造词。

可惜,这是一个伪创新。

我们再看一遍“Domain-Driven Design”中的描述:

An AGGREGATE is a cluster of associated objects that we treat as a unit for the purpose of data changes. Each AGGREGATE has a root and a boundary. ……The root is the only member of the AGGREGATE that outside objects are allowed to hold references to, ……

一个AGGREGATE是一簇相关联的对象,我们把它作为数据变化的单元来对待。每个AGGREGATE有一个根和一个边界。……根是AGGREGATE的成员中唯一允许外部对象持有引用的,……

以图8-139为例,按照这个说法,我们可以说:

①(“植物”+“根”+“茎”+“叶”)等一簇相关联的对象形成了一个aggregate。

②其中“植物”是该aggregate的aggregate root。

先来看①的问题。

图片

图8-144 对象不需要也不能和其部件并列

如图8-144,“植物”已经包括“根”、“茎”、“叶”等部件在内,不能也不需要再和这些部件并列。

在类级别,说“植物和根、茎、叶是整体-部分关联”,可以。

在对象级别,说“某个植物对象由若干根、茎、叶对象组成”,可以。

但是,说“某个植物对象和它的根、茎、叶一起组成aggregate”,不可以。

说“植物对象是一个aggregate”,可以,但这样的说法无意义。所有对象都是aggregate,否则要它干什么呢?

要把这个圆过去,可以把“植物”排除在组成aggregate的“一簇相关联的对象”之外,说“一簇根、茎、叶对象组成了植物aggregate”,不过,Eric Evans又说了“根是AGGREGATE的成员”,看来是圆不过去了。

再来看②的问题。

即使我们排除了①的错误,采取“一簇根、茎、叶对象组成了植物aggregate”的说法,但说法②仍然不合适。我们可以看下面的表述:

植物由根、茎、叶组成,所以,植物是[根……]的根?

汽车由发动机、车身、底盘组成,所以,汽车是[发动机……]的根?

墙由砖垒成,所以,墙是砖的根?

分子由原子组成,所以,分子是原子的根?

之所以会有aggregate root这样的错觉,有可能是受了关系数据库思考方式的影响。

图8-139的类图,如果用关系数据库来保存对象,可能会得到图8-145的几个表,这样就产生了“植物”就是“植物”表的错觉,于是觉得有必要提醒它是aggregate root,别忘了带上其他几个小弟。

图片

图8-145 受关系数据库思考方式影响的aggregate root错觉

aggregate root错觉另一个可能的原因来自人类社会的直觉。

(待续……)

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

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

相关文章

在今日头条上写文章:ChatGPT完整使用教程

了解如何充分运用ChatGPT进行创作 简介 在今日头条上发布文章变得越来越方便。本文旨在详细解析如何运用ChatGPT来创作文章,并提供全方位的使用指南及常见问题的答疑。 第一步:基础准备 确保你已注册今日头条账号。 登录ChatGPT并与你的今日头条账号进…

华为、华三、思科、锐捷交换机路由器设备命令行常见错误信息

目的 使用CLI命令行界面,如果输入错误,系统将会向用户报告错误信息。 知己知彼,方能百战不殆。下面是小木为大家收集整理的几大厂商常见的命令行错误提示。 华为设备命令行常见错误信息 Error: Unrecognized command found at ^ position. …

Java中的CAS(Compare-And-Swap)操作详解

一、技术难点 CAS操作,全称为Compare-And-Swap,是Java并发编程中的一个重要概念,其技术难点主要体现在以下几个方面: 原子性保证:CAS操作必须保证整个操作的原子性,即在多线程环境中,当一个线…

mysql 删除重复数据 关联自己 关联子查询 delete

有手工录入的数据时&#xff0c;删除系统定时任务计算的数据。 delete from t1 using data_tab as t1, (select * from (select input_type,system_code,DATE_FORMAT(start_time,%Y-%m-%d) as date_ from data_tab where start_time >2024-05-20 and start_time <2024-…

软件测试经理工作日常随记【6】-利用python连接禅道数据库并自动统计bug数据到钉钉群

测试管理_利用python连接禅道数据库并统计bug数据到钉钉 这篇不多赘述&#xff0c;直接上代码文件。 另文章基础参考博文&#xff1a;参考博文 加以我自己的需求优化而成。 统计的前提 以下代码统计的前提是禅道的提bug流程应规范化 bug未解决不删除bug未关闭不删除 db_…

Paddle 0-d Tensor 使用指南

Paddle 0-d Tensor 使用指南 1. 0-d Tensor 的定义 在深度学习框架中&#xff0c;Tensor 是存储和操作数据的基本数据结构。一个 Tensor 可以有 0 到任意多的维度,每个维度对应一个 shape 值。而 0-d Tensor&#xff0c;顾名思义&#xff0c;就是一个无任何维度的 Tensor&…

Oracle 数据泵(Data Pump)的impdp解析

impdp 是 Oracle 数据泵&#xff08;Data Pump&#xff09;用于数据导入的命令行工具。 directory: 指定转储文件和日志文件所在的操作系统目录对象名。此目录对象必须事先使用 CREATE DIRECTORY 命令创建并在数据库中定义。 impdp system/password directorydir_name ...dumpf…

LuatOS学习

开发顺序 Lua是脚本语言中运行速度最快的语言 资源占用极低 脚本语言运行方式 脚本语言是从上往下一行一行运行的 变量 coun 123456 a,b,c 1,2,3交换 a,b b,a在测试环境中&#xff0c;用print(a,b)打印 nil类型 未声明的变量就是nil&#xff0c;nil用来表示此变量为空…

STM32高级控制定时器(STM32F103):检测输入PWM周期和占空比

目录 概述 1 PWM 输入模式 1.1 原理介绍 1.2 应用实例 1.3 示例时序图 2 使用STM32Cube配置工程 2.1 软件环境 2.2 配置参数 2.3 生成项目文件 3 功能实现 3.1 PWM占空比函数 3.2 输入捕捉回调函数 4 功能测试 4.1 测试软件框架结构 4.2 实验实现 4.2.1 测试实…

视觉语音识别挑战赛 CNVSRC 2024

CNVSRC 2024由NCMMSC 2024组委会发起&#xff0c;清华大学、北京邮电大学、海天瑞声、语音之家共同主办。竞赛的目标是通过口唇动作来推断发音内容&#xff0c;进一步推动视觉语音识别技术的发展。视觉语音识别&#xff08;也称为读唇技术&#xff09;是一种通过观察唇部动作推…

二叉树顺序结构实现【堆的实现】【详细图解】

P. S.&#xff1a;以下代码均在VS2019环境下测试&#xff0c;不代表所有编译器均可通过。 P. S.&#xff1a;测试代码均未展示头文件stdio.h的声明&#xff0c;使用时请自行添加。 目录 1、二叉树的顺序结构2、堆的概念3、堆的实现3.1 堆实现的前提3.1.1 向上调整3.1.2 向下调…

采用java语言+B/S架构+后端SpringBoot前端Vue开发的ADR药品不良反应智能监测系统源码

采用java语言&#xff0b;B/S架构&#xff0b;后端SpringBoot前端Vue开发的ADR药品不良反应智能监测系统源码 ADR监测引擎每日主动获取检验数据、病历内容&#xff08;可拓展&#xff09;、以及其他临床数据&#xff0c;根据知识库内容自动判定患者是否有不良反应迹象&#xf…

算法基础之Nim游戏

Nim游戏 核心思想&#xff1a;博弈论 结论&#xff1a;将所有堆的石子数全部异或起来 得到的结果若为1 则先手必胜 若为0 则先手必败 #include <iostream>#include <cstring>#include <algorithm>using namespace std;const int N 100010;int a[N];int n…

k8s笔记——client-go与 Kubernetes APIServer 交互的客户端

文章目录 四种Kubernetes APIServer 交互的客户端RESTClientclientSetdynamicClientDiscoveryClient 创建、更新、查询、删除Deployment参考资料 四种Kubernetes APIServer 交互的客户端 Client-Go 共提供了 4 种与 Kubernetes APIServer 交互的客户端。分别是 RESTClient、Di…

LeetCode精华75题(持续更新)

LeetCode刷题笔记 数组/字符串 交替合并字符串 题目&#xff1a; 给你两个字符串 word1 和 word2 。请你从 word1 开始&#xff0c;通过交替添加字母来合并字符串。如果一个字符串比另一个字符串长&#xff0c;就将多出来的字母追加到合并后字符串的末尾。 返回 合并后的字符…

【iOS】UI学习(一)

UI学习&#xff08;一&#xff09; UILabelUIButtonUIButton事件 UIViewUIView对象的隐藏UIView的层级关系 UIWindowUIViewController定时器与视图对象 UISwitch UILabel UILabel是一种可以显示在屏幕上&#xff0c;显示文字的一种UI。 下面使用代码来演示UILabel的功能&#…

AI学习指南数学工具篇-Python中的凸优化库

AI学习指南数学工具篇-Python中的凸优化库 在人工智能和机器学习领域&#xff0c;凸优化是一个非常重要的数学工具。它可以帮助我们解决各种问题&#xff0c;包括线性规划、二次规划、半定规划等。而在Python中&#xff0c;有一个非常优秀的凸优化库&#xff0c;即CVXPY。本文…

做好开源快速开发平台研发创新 助力行业高效发展!

随着信息化时代的到来&#xff0c;科技的力量无处不在。为了提高办公效率&#xff0c;很多大中型企业倾向于使用更为先进的软件平台来助力企业降本增效。在众多助力神器之中&#xff0c;开源快速开发平台低代码技术平台深得广大新老客户朋友的喜爱&#xff0c;它与生俱来的优势…

结合PyTest和Selenium进行网页自动化测试的例子

一个结合PyTest和Selenium进行网页自动化测试的示例。 这个测试用例模拟了一个简单的用户登录过程&#xff0c;并包含了对登录后页面状态的断言。我们将使用Selenium的WebDriver来控制浏览器&#xff0c;并使用PyTest来进行断言。 import pytest from selenium import webdri…

vue2+echarts地图下钻+地图遮盖物散点

一、下载工具 npm i echarts echarts-gl axios -S -S是生产依赖默认是-S不写也可以 -D是开发依赖 二、引入工具 import * as echarts from "echarts"; import "echarts-gl"; import axios from "axios"; 三、HTML部分代码 <div class&…