首页 > 数据库 >反DDD模式之关系型数据库

反DDD模式之关系型数据库

时间:2024-09-17 14:12:37浏览次数:8  
标签:关系 范式 数据库 模式 主键 冗余 DDD

本文书接上回《图穷匕见-所有反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的世界,那么在分析需求和设计模型时,一定要尽可能先忘记关系数据库和三范式的存在,哪怕你要应用三范式,也应该仅仅将它应用在你的模型的内部,千万不要用它来表达“聚合”之间的关系,因为,“聚合”是独立的有明确边界的。

标签:关系,范式,数据库,模式,主键,冗余,DDD
From: https://www.cnblogs.com/xiaoweiyu/p/18417142

相关文章

  • Qt:实现单例模式
    前言记录一下。正文单例模式根据实现方式和应用场景在Qt中可以分为以下几种类型:1.懒汉式单例懒汉式单例在第一次使用时才创建实例,延迟了对象的初始化。懒汉式单例分为线程安全和线程不安全两种实现方式。线程不安全的懒汉式单例:在第一次调用getInstance()时创建......
  • JDBC的介绍和连接MySQL数据库
    目录1.为什么学习JDBC1.1数据存储​编辑​编辑1.2 数据操作​编辑2.JDBC概述2.1JDBC概念2.2JDBC核心组成3.实现JDBC3.1JDBC搭建步骤3.2详细演示 3.3核心API3.3.1Driver​3.3.2 Connection​3.3.3Statament​3.3.4PreparedStatement3.3.5Res......
  • 【理论篇】数据挖掘 第六章 挖掘频繁模式、关联和相关性:基本概念和方法(下)
    说明:文章为《数据挖掘:概念与技术原书第03版》的学习笔记,该书是数据挖掘领域的经典之作,想了解更多内容请参阅原著。首先祝大家中秋快乐,本文章接上篇【理论篇】数据挖掘第六章挖掘频繁模式、关联和相关性:基本概念和方法(上)思考:满足最小支持度和最小置信度的模式一定是有趣......
  • 【MySQL】—— 数据库操作、数据表操作
    文章目录:前言一、SQL简介SQLMySQL二、数据库(数据集合)操作1.连接服务器2.创建数据库3.查看数据库4.选中数据库5.删除数据库三、数据表操作1.MySQL中常用数据类型整形和浮点型字符串类型时间日期2.创建表3.查看表4.查看表结构5.删除表前言九月......
  • 十五,Spring Boot 整合连接数据库(详细配置)
    十五,SpringBoot整合连接数据库(详细配置)@目录十五,SpringBoot整合连接数据库(详细配置)最后:JDBC+HikariDataSource(SpringBoot内置的数据库)HikariDataSource:目前市面上非常优秀的数据源,是SpringBoot2默认数据源。演示SpringBoot如何通过jdbc+HikariDataSou......
  • LVS三种负载均衡模式的比较
    文章目录三种模式对比三种模式对比LVS-NATLVS-DRLVS-TUN服务器操作系统可以使用任何支持TCP/IP的操作系统大多数常见的操作系统都可以使用需要支持IP隧道技术的操作系统服务器网络需要私有网络,所有真实服务器(RS)必须位于同一局域网内同样需要局域网,但RS可以使用公网......
  • redis哨兵模式和集群模式
    ###哨兵模式 想象一下你有一家便利店,这个便利店就是你的Redis服务器。为了确保便利店能一直营业,你需要有人来监督这家店是否正常运作。这就是哨兵模式的基本思想。 -**哨兵(Sentinel)**:哨兵就像是便利店的保安,它们的任务是监视便利店是否正常开门营业(也就是监视Redis服务......
  • 大数据技术原理与应用——从入门到文档数据库
    大数据技术原理与应用3次信息化的浪潮研究问题的四个阶段大数据技术的层次大数据的计算模式PaaS物联网的概念云计算、大数据、物联网之间的关系Hadoop应用现状选择Hdoop需要考虑的因素Hadoop的定量评分(满分为5分)总体评价Ubuntu的一些基本知识(之所以不......
  • Python 操作 MySQL 数据库
    Python操作MySQL数据库Python标准数据库接口为PythonDB-API,PythonDB-API为开发人员提供了数据库应用编程接口。Python数据库接口支持非常多的数据库,你可以选择适合你项目的数据库:GadFlymSQLMySQLPostgreSQLMicrosoftSQLServer2000InformixInterbaseOracleSybase......
  • 数据库的基本使用
     数据存储逻辑   数据存储的逻辑是行和列。我们根据数据库中的表的结构来认识数据的存储结构,用什么的结构去呈现我们所要存储的数据。               6.2数据库架构   MySQL是一种可移植的数据库,几乎能在当前所有的操作系统中运行,如......