反DDD模式之关系型数据库

news/2024/11/14 15:17:38/文章来源:https://www.cnblogs.com/xiaoweiyu/p/18417142

本文书接上回《图穷匕见-所有反DDD模式都是垃圾》,关注公众号(老肖想当外语大佬)获取信息:

最新文章更新;
DDD框架源码(.NET、Java双平台);
加群畅聊,建模分析、技术实现交流;
视频和直播在B站。

背景

我在与开发者交流关于DDD的建模思路时,往往会遇到一个难题,就是不少经验丰富的开发者,总是带着技术的思维来理解业务,ta的大脑里无法纯粹地勾勒出一个边界明确的代表业务实体的形象。其中最明显的一个现象,就是习惯性地用关系数据库中的“关系”,来映射业务模型之间的关系,一旦带着“关系”来思考,那么“边界”就很难再有一席之地。而对于没有太多“关系数据库”经验的开发者,反倒很容易理解什么叫“边界明确”。

关系型数据库的三范式

这里我们先列出来关系型数据库的三范式定义:

  1. 第一范式(1NF):确保每列的值都是原子性的,即每列的值不可再分。
  2. 第二范式(2NF):在满足第一范式的基础上,确保表中的每一列都完全依赖于主键,而不是部分依赖。
  3. 第三范式(3NF):在满足第二范式的基础上,确保表中的每一列都不依赖于非主键列,即消除传递依赖。

更通俗地说:

  1. 第一范式(1NF):每个字段只能存储一个值,不能有重复的列。
  2. 第二范式(2NF):在满足第一范式的基础上,所有非主键字段必须完全依赖于主键,而不能只依赖于主键的一部分。
  3. 第三范式(3NF):在满足第二范式的基础上,非主键字段之间不能有依赖关系,必须直接依赖于主键。

而满足三范式的几个关键目的:

  1. 消除数据冗余:通过确保每个数据项在数据库中只存储一次,减少数据重复,节省存储空间。
  2. 提高数据一致性:减少数据冗余后,数据更新时只需修改一个地方,避免数据不一致的问题。
  3. 简化数据维护:通过规范化设计,减少数据异常和复杂的维护操作,使数据库结构更清晰,易于管理和扩展。

DDD思维 vs 三范式思维

假设我们在设计一个包含用户、角色、部门要素的系统,如果我们基于关系数据库的思维,那么设计出来的效果大概率类似下图:

假如我们设计一个系统,完全满足关系型数据库的三范式,那么可以推论出来,基本上整个系统的所有实体之间都会直接或者间接地产生“关系”,画出来的图也会像一张蜘蛛网一样错综复杂,这与DDD的理念正好相反。

因此,从这个角度来说“关系型数据库三范式的模式是一种反DDD模式”。

而如果我们使用DDD的思维,那么“连线意味着它们就是一个整体”,要把边界给明确出来,就需要消除连线,那么设计出来的图,大概率是下面的样子:

当然你一定会有疑问,用户和角色之间客观上是存在关系的呀,你把连线移除,那么这个关系就无法表达了,上面的图并不能反映完整的设计,实际上,如果我们把“用户聚合”的细节图展开,你就会发现,我们把“关系”放置到了“用户聚合内部”,需要注意的是这里多出来了一个叫“用户角色”的实体,它与“角色聚合”不是同一个概念。

到这里,我想你也能发现DDD的思维有一些特征:

  1. 聚合之间不连线(join),保持边界明确

  2. 聚合内部满足关系型数据库三范式

  3. 为了实现聚合之间不连线(join),会产生一些“冗余”实体

代价与收益

假如我们使用DDD的模式来设计系统,代价是数据会一定程度上的“冗余”,这些冗余的实体数据,需要通过“事件驱动”的方式保持一致性,而收益是系统被明确地划分成了多个边界明确的“领域”,复杂度就像“杂物”一样被收纳在了一个个“收纳箱”。

此外,关于“冗余数据”,我们是从“关系型数据库”的视角来看待的,如果用DDD的视角来看,前面模型图中的“用户角色”是“用户聚合”客观上存在的属性,因此它不是冗余。你看,我们一旦切换到DDD的视角,会发现事情变得很自然了。

现实世界到处是冗余

如果上面的例子,你仍然觉得没有说服力,那么可以观察一下现实世界的状况,你会发现信息冗余的现象是普遍存在的,比如我的手机通讯录,冗余了你的名字和手机号,因为“我的通讯录”就是客观上“我”的属性,现实世界到处是类似的例子。

结论

如果你期望尽快地走进DDD的世界,那么在分析需求和设计模型时,一定要尽可能先忘记关系数据库和三范式的存在,哪怕你要应用三范式,也应该仅仅将它应用在你的模型的内部,千万不要用它来表达“聚合”之间的关系,因为,“聚合”是独立的有明确边界的。

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

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

相关文章

常回家看看之house_of_catWO

house_of_cat 前言: house of cat 这个利用手法和前面提到的 house of kiwi ,和 house of emma 利用的手法是一个链子,当程序无法通过main函数返回时候,或者程序不能显性调用exit函数的时候,我们可以通过 __malloc_assert 来刷新IO流,当然这个函数在2.35之后移除了刷新IO…

C++11 线程同步接口std::condition_variable和std::future的简单使用sk

合集 - C++(1)1.C++11 线程同步接口std::condition_variable和std::future的简单使用09-17收起 std::condition_variable 条件变量std::condition_variable有wait和notify接口用于线程间的同步。如下图所示,Thread 2阻塞在wait接口,Thread 1通过notify接口通知Thread 2继续执…

安全:nftables:基础知识

一,policy: 1,原文档链接: https://docs.redhat.com/zh_hans/documentation/red_hat_enterprise_linux/9/html/configuring_firewalls_and_packet_filters/assembly_creating-and-managing-nftables-tables-chains-and-rules_getting-started-with-nftables#con_basics-of-nft…

Leetcode 952. 按公因数计算最大组件大小

1.题目基本信息 1.1.题目描述 给定一个由不同正整数的组成的非空数组 nums ,考虑下面的图: 有 nums.length 个节点,按从 nums[0] 到 nums[nums.length - 1] 标记;只有当 nums[i] 和 nums[j] 共用一个大于 1 的公因数时,nums[i] 和 nums[j]之间才有一条边。 返回 图中最大连…

Leetcode 19.删除链表的倒数第第N个结点

1.题目基本信息 题目:给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。 地址:https://leetcode.cn/problems/remove-nth-node-from-end-of-list/description/ 2.解题方法 2.1.解题思路 使用快慢指针 2.2.解题步骤 第一步,初始化快指针为head,慢指针指向一…

Leetcode 297. 二叉树的序列化与反序列化

1.题目基本信息 1.1.题目描述 序列化是将一个数据结构或者对象转换为连续的比特位的操作,进而可以将转换后的数据存储在一个文件或者内存中,同时也可以通过网络传输到另一个计算机环境,采取相反方式重构得到原数据。 请设计一个算法来实现二叉树的序列化与反序列化。这里不限…

曾亨瑾第一次作业

这个作业属于哪个课程 https://edu.cnblogs.com/campus/zjlg/rjjc/这个作业的目标 发布一篇随便简单介绍自己姓名 曾亨瑾学号 2022329301104一、自我介绍 1.基本信息 大家好,我是电气工程及其自动化(2)班的曾亨瑾,来自广东东莞。 2.兴趣爱好 我喜欢打羽毛球和慢跑(虽然都是…

2024软件工程第二次作业

这个作业属于哪个课程 https://edu.cnblogs.com/campus/fzu/SE2024这个作业要求在哪里 https://edu.cnblogs.com/campus/fzu/SE2024/homework/13253这个作业的目标 开发类“羊了个羊”消除类小游戏,并借助AIGC技术提高效率学号 052203132项目展示Github地址:https://github.c…

宏定义与特别运用

目录宏定义数值宏常量字符串宏常量用define宏定义注释符号?程序的编译过程预处理中宏替换和去注释谁先谁后?如何写一个可靠的宏函数do-while-zero结构do-while-zero的评价宏定义中的空格宏只能在main函数上面定义吗?宏的作用范围#undef宏替换是在函数调用之前进行.块中进行#…

白云龙期货投资-第六讲

## 价量行情中的配合 1,价涨量增,顺势推动。 2,价量背离,趋势转变 (价与量在相对高位称为顶背离,在下跌末期为底背离。背离后如果想再次上涨或者下跌,一般价格都会出现一个盘整期,而成交量则出现缩量地量期)价量行情中的配合 1,价涨量增,顺势推动。 2,价量背离,趋势…

软件工程结对项目 3:python实现自动生成小学四则运算题目的程序

这个作业属于哪个课程 广工计院计科34班软工这个作业要求在哪里 作业要求团队成员1 庄崇立3122004633团队成员2 罗振烘3122004748这个作业的目标 结对合作完成小学四则运算题目的程序,熟悉项目开发流程,提高团队合作能力一、GitHub地址 二、需求 1.题目:实现一个自动生成小学…

结构、权限修饰符、类

结构、权限修饰符、类 结构(struct:自定义的数据结构) struct student {// 成员变量int number;char name[100];void func(){ // 成员函数(方法)number++;} };// 1. 形参为引用 void func1(student &stu){stu.number = 2000;strcpy_s(stu.name, sizeof(stu.name…