反DDD模式之关系型数据库
本文书接上回《图穷匕见-所有反DDD模式都是垃圾》,关注公众号(老肖想当外语大佬)获取信息:
最新文章更新;
DDD框架源码(.NET、Java双平台);
加群畅聊,建模分析、技术实现交流;
视频和直播在B站。
背景
我在与开发者交流关于DDD的建模思路时,往往会遇到一个难题,就是不少经验丰富的开发者,总是带着技术的思维来理解业务,ta的大脑里无法纯粹地勾勒出一个边界明确的代表业务实体的形象。其中最明显的一个现象,就是习惯性地用关系数据库中的“关系”,来映射业务模型之间的关系,一旦带着“关系”来思考,那么“边界”就很难再有一席之地。而对于没有太多“关系数据库”经验的开发者,反倒很容易理解什么叫“边界明确”。
关系型数据库的三范式
这里我们先列出来关系型数据库的三范式定义:
- 第一范式(1NF):确保每列的值都是原子性的,即每列的值不可再分。
- 第二范式(2NF):在满足第一范式的基础上,确保表中的每一列都完全依赖于主键,而不是部分依赖。
- 第三范式(3NF):在满足第二范式的基础上,确保表中的每一列都不依赖于非主键列,即消除传递依赖。
更通俗地说:
- 第一范式(1NF):每个字段只能存储一个值,不能有重复的列。
- 第二范式(2NF):在满足第一范式的基础上,所有非主键字段必须完全依赖于主键,而不能只依赖于主键的一部分。
- 第三范式(3NF):在满足第二范式的基础上,非主键字段之间不能有依赖关系,必须直接依赖于主键。
而满足三范式的几个关键目的:
- 消除数据冗余:通过确保每个数据项在数据库中只存储一次,减少数据重复,节省存储空间。
- 提高数据一致性:减少数据冗余后,数据更新时只需修改一个地方,避免数据不一致的问题。
- 简化数据维护:通过规范化设计,减少数据异常和复杂的维护操作,使数据库结构更清晰,易于管理和扩展。
DDD思维 vs 三范式思维
假设我们在设计一个包含用户、角色、部门要素的系统,如果我们基于关系数据库的思维,那么设计出来的效果大概率类似下图:
假如我们设计一个系统,完全满足关系型数据库的三范式,那么可以推论出来,基本上整个系统的所有实体之间都会直接或者间接地产生“关系”,画出来的图也会像一张蜘蛛网一样错综复杂,这与DDD的理念正好相反。
因此,从这个角度来说“关系型数据库三范式的模式是一种反DDD模式”。
而如果我们使用DDD的思维,那么“连线意味着它们就是一个整体”,要把边界给明确出来,就需要消除连线,那么设计出来的图,大概率是下面的样子:
当然你一定会有疑问,用户和角色之间客观上是存在关系的呀,你把连线移除,那么这个关系就无法表达了,上面的图并不能反映完整的设计,实际上,如果我们把“用户聚合”的细节图展开,你就会发现,我们把“关系”放置到了“用户聚合内部”,需要注意的是这里多出来了一个叫“用户角色”的实体,它与“角色聚合”不是同一个概念。
到这里,我想你也能发现DDD的思维有一些特征:
聚合之间不连线(join),保持边界明确
聚合内部满足关系型数据库三范式
为了实现聚合之间不连线(join),会产生一些“冗余”实体
代价与收益
假如我们使用DDD的模式来设计系统,代价是数据会一定程度上的“冗余”,这些冗余的实体数据,需要通过“事件驱动”的方式保持一致性,而收益是系统被明确地划分成了多个边界明确的“领域”,复杂度就像“杂物”一样被收纳在了一个个“收纳箱”。
此外,关于“冗余数据”,我们是从“关系型数据库”的视角来看待的,如果用DDD的视角来看,前面模型图中的“用户角色”是“用户聚合”客观上存在的属性,因此它不是冗余。你看,我们一旦切换到DDD的视角,会发现事情变得很自然了。
现实世界到处是冗余
如果上面的例子,你仍然觉得没有说服力,那么可以观察一下现实世界的状况,你会发现信息冗余的现象是普遍存在的,比如我的手机通讯录,冗余了你的名字和手机号,因为“我的通讯录”就是客观上“我”的属性,现实世界到处是类似的例子。
结论
如果你期望尽快地走进DDD的世界,那么在分析需求和设计模型时,一定要尽可能先忘记关系数据库和三范式的存在,哪怕你要应用三范式,也应该仅仅将它应用在你的模型的内部,千万不要用它来表达“聚合”之间的关系,因为,“聚合”是独立的有明确边界的。
反DDD模式之关系型数据库的更多相关文章
- 关系型数据库与NoSQL的对比
SQL(结构化的查询语言)数据库是过去四十年间存储数据的主要方式.20世纪90年代末随着Web应用和MySQL.PostgreSQL和SQLite等开源数据库的兴起,用户爆炸式的增长. NoSQL数据 ...
- 关系型数据库与Key-value型数据库Mongodb模式设计对比
MongoDb 相比于传统的 SQL 关系型数据库,最大的不同在于它们的模式设计( Schema Design )上的差别,正是由于这一层次的差别衍生出其它各方面的不同. 我们可以简单的认为关系型数据 ...
- 大数据时代的数据存储,非关系型数据库MongoDB
在过去的很长一段时间中,关系型数据库(Relational Database Management System)一直是最主流的数据库解决方案,他运用真实世界中事物与关系来解释数据库中抽象的数据架构. ...
- 大数据时代的数据存储,非关系型数据库MongoDB(一)
原文地址:http://www.cnblogs.com/mokafamily/p/4076954.html 爆炸式发展的NoSQL技术 在过去的很长一段时间中,关系型数据库(Relational Da ...
- 关系型数据库工作原理-事务管理(一)(翻译自Coding-Geek文章)
本文翻译自Coding-Geek文章:< How does a relational database work>. 原文链接:http://coding-geek.com/how-dat ...
- python-MongoDB 非关系型数据库
一 简介 MongoDB是一款强大.灵活.且易于扩展的通用型数据库1.易用性 MongoDB是一个面向文档(document-oriented)的数据库,而不是关系型数据库.不采用关系型主要是为了获得 ...
- 非关系型数据库MongoDB
爆炸式发展的NoSQL技术 在过去的很长一段时间中,关系型数据库(Relational Database Management System)一直是最主流的数据库解决方案,他运用真实世界中事物与关系来 ...
- 非关系型数据库(NoSql)
最近了解了一点非关系型数据库,刚刚接触,觉得这是一个很好的方向,对于大数据 方面的处理,非关系型数据库能起到至关重要的地位.这里我主要是整理了一些前辈的经验,仅供参考. 关系型数据库的特点 1.关系型 ...
- SQLite vs MySQL vs PostgreSQL:关系型数据库比较
自1970年埃德加·科德提出关系模型之后,关系型数据库便开始出现,经过了40多年的演化,如今的关系型数据库种类繁多,功能强大,使用广泛.面对如此之多的关系型数据库,我们应该如何权衡找出适合自己应用场景 ...
- 关系型数据库与NOSQL
本文转载自: http://www.cnblogs.com/chay1227/archive/2013/03/17/2964020.html(只作转载, 不代表本站和博主同意文中观点或证实文中信息) ...
随机推荐
- <el-table-column prop="item_no" label="料号"/>设置最小宽度
可以通过min-width属性来设置el-table-column的最小宽度.以下是一个示例: <template> <el-table :data="tableData& ...
- oeasy教您玩转vim - 22 - 配置文件
配置文件 回忆上节课内容 我们上次了解到了状态横条 通过转义表示 item 控制 item 宽度的方法 将 item 成组的方法 还有一个总开关 laststatus 但是每次都要写很长的一段话来配置 ...
- [rCore学习笔记 05]第0章作业题
作业1 略. 作业2 C语言程序 gcc编译 gcc -o main main.c 编译报错 成功产生异常 main.c: In function 'main': main.c:5:26: warni ...
- 【AppStore】IOS应用上架Appstore的一些小坑
前言 上一篇文章写到如何上架IOS应用到Appstore,其中漏掉了些许期间遇到的小坑,现在补上 审核不通过原因 5.1.1 Guideline 5.1.1 - Legal - Privacy - D ...
- 手把手教你集成GraphRag.Net:打造智能图谱搜索系统
在人工智能和大数据发展的背景下,我们常常需要在项目中实现知识图谱的应用,以便快速.准确地检索和使用信息. 今天,我将向大家详细介绍如何在一个新的.NET项目中集成GraphRag.Net,这是一个参考 ...
- 5/15课下作业:评价一下steam软件
用户界面: 登录后会弹出特惠广告,广告内容可能不常用.主界面简洁方便,启动游戏,购买游戏,浏览社区,浏览自己内容一目了然 记住用户选择: 登录一次后会记住用户的账户密码,可以直接进行用户间的切换,会记 ...
- Jmeter函数助手6-time
time函数用于获取不同格式的当前时间(年月日时分秒). Format string for SimpleDateFormat (optional):时间格式,填入如yyyyMMdd-HHmmss.d ...
- proxmox ve 部署双节点HA集群及glusterfs分布式文件系统
分布式存储的作用 加入分布式存储的目的:主要是为了对数据进行保护避免因一台服务器磁盘的损坏,导致数据丢失不能正常使用. 参考文档:https://gowinder.work/post/proxmo ...
- LinuxUDP通讯
目录 前言 一.UDP通讯 1.UDP通讯概述 2.UDP的特点 3.UDP的应用 二.UDP基本通讯 1.socket函数 2.bind函数 2.1 主机字节序和网络字节序 2.2 点分制十进制转换 ...
- 路径规划综述博客:A* Optimizations and Improvements
地址: https://lucho1.github.io/JumpPointSearch/ 原作者还开发了A* 算法的Windows系统上的小程序:(重点:小程序意义不大,这个综述还是不赖的) 项目地 ...