【DDD】学习笔记-数据分析模型

在 Eric Evans 提出领域驱动设计之前,对企业系统的分析设计多数采用数据模型驱动设计。如前所述,这种数据模型驱动设计就是站在数据的建模视角,逐步开展分析、设计与实现的建模过程。通过对数据的正确建模,设计人员就可以根据模型建立数据字典。数据模型会定义数据结构与关系,有效地消除数据冗余,保证数据的高效访问。由于软件系统的业务功能归根结底是对信息的处理,由此建立的数据模型也可以通过某种编程手段来实现,满足业务需求。

数据分析模型

数据建模过程中的分析活动会通过理解客户需求寻找业务概念建立实体(Entity)。在数据模型中,一个实体就是客户希望建立和存储的信息。这是一个抽象的逻辑概念,位于数据模型的最高抽象层。一个实体不一定恰好对应一个数据表,它甚至可能代表一个主题域。在识别实体的同时,我们还需要初步确定实体之间的关系。由于这个过程与数据库细节完全无关,因而称之为对数据的“概念建模”,建立的模型称之为实体关系模型

经过数十年对数据建模的丰富与完善,这个领域已经出现了许多值得借鉴和重用的数据模型。其中,Len Silverston 的著作《数据模型资源手册》是最重要的模型参考手册。他通过对行业业务的梳理,建立了包括人与组织、产品、产品订购、装运、工作计划、发票等各个主题的数据模型。在确定系统的实体时,这些已有的数据模型可以作为我们的重要参考。

当然,每个软件系统的业务需求必然有其特殊性,除了对已有数据模型的参考,也有一些数据建模方法帮助我们获得实体关系模型。例如通过引入不同的用户视图创建不同的实体关系模型。用户视图的差异取决于业务能力的差异,例如,财务人员的观察视图显然不同于市场人员的观察视角,看到的数据信息显然也有所不同。这就像盲人摸象一般,虽然每个视角得到的实体关系模型只是大象的一部分,然而将这些代表不同人员不同观点的实体关系模型组合起来,就能形成整体的实体关系模型。

实体关系模型是数据建模的开始,目的是让我们可以从一开始抛开对数据库实现细节的考虑,寻找那些表达业务知识的重要概念,并明确它们之间的关系。但对数据模型的分析并不会就此止步,我们必须在分析阶段对实体做进一步细化,形成具体的数据表,并定义表属性,确定数据表之间的真实关系。这时获得的分析模型称之为“数据项模型”。实体关系模型与数据项模型之间的关系如下图所示:

img

在数据建模过程中,越早确定数据库的细节越有利于数据模型的稳定。当今的软件开发,已经不是关系型数据库一统天下的时代。NoSQL 甚至 NewSQL 的诞生,让我们在选择持久化机制时有了更多选择。比较关系数据库和 NoSQL 数据库,前者是严格扁平的结构化数据,后者却是无样式的数据结构(Schemaless Data Structures),结构不同,建立的数据模型自然就有了天壤之别。一旦根据数据模型创建了物理的数据表,再调整数据模型,变化的成本就太高了。因此,究竟选择关系数据库还是 NoSQL 数据库,对确立数据项模型至关重要,我们需要分开讨论。

关系数据库的数据项模型

关系数据库体现了关系模型,形成了一种扁平的结构化数据,这就要求进一步规范数据表的粒度,将实体或主题域拆分为多个遵循数据库范式的数据表,明确一个数据表的主要属性。

数据库范式是面向数据的分析建模活动的一个关键约束。这些范式包括一范式(1NF)、二范式(2NF)、三范式(3NF)、BC 范式(BCNF)和四范式(4NF)。遵循这些范式可以保证数据表属性的原子性、避免数据冗余和传递依赖等。

例如在确定数据项时,该如何考虑避免数据冗余?这就需要合理地设计表以及表之间的关系。

假设一个公司的员工可能同时具有多个角色:运输科的张飞是科室的负责人,他又是供应科的客户,供应科会将运输的任务委托给他;同时,他还是一家大型超市的供应商,负责将货物运输给超市。显然,我们不能在一个数据库中为张飞创建三条冗余的数据记录。运输科主任、供应科客户和超市供应商都是张飞担任的角色,无论他担任了什么角色,他都是该公司的一名员工。

在创建数据模型时,应该将角色属性从员工剥离出去,分别形成数据表 t_employee 与 t_role;又因为员工和角色之间存在多对多的关系,需要引入一个关联表 t_employee_roles。这个数据模型如下图所示:

enter image description here

当数据模型出现多对多关系时,之所以要引入一个关联表,是因为多对多关系会引入数据表之间的交叉关联。这个数据项模型中的 t_employee_role 并无映射的业务概念,引入该表,纯粹是数据库实现细节对模型产生的影响。

有时候,承载多对多关系的关联表也可以具有一些附加的属性,这样的关联表往往代表了业务逻辑中的一个业务概念,例如学生(Student)与课程(Course)之间的多对多关系,可以用课表(Curriculum)关联表来表达。Curriculum 属于学习领域的业务概念,但同时它又能有效解除 Student 与 Course 之间的交叉关联。

有的数据建模者甚至建议针对一对多关系也建立关联表,因为关联表的引入使得这种关系更容易维护。例如产品(Product)和图片(Picture)是一对多关系,直接定义 t_product 和 t_picture 数据表即可,但如果引入 t_product_picture 关联表,就可以在数据库层面更好地维护二者之间的关系。有时,一对多关系体现了父—子关系,例如订单(Order)与订单项(OrderItem),它们之间的一对多关系其实代表了“每个订单项必须是一个也只是一个订单的一部分”。

在确定数据项模型时,还需要考虑访问关系数据库的性能特性,从而决定数据的粒度与分割。通常,需要考虑数据表的规范化,避免设计出太多过小的包含少量数据的数据表。一个数据表的粒度较小,就会导致程序在访问数据库时频繁地在多张小表之间跳转。这个访问过程既要存取数据,又要存取索引以找到数据,导致I/O的过度消耗,影响到整体的性能。因此,数据模型很少具有一对一关系,即使现实世界的概念存在一对一关系,也应该尽量通过规范化将两张表的数据组织在一起,合到一个实体中。例如,我们说一位员工有一个家庭电话号码和工作电话号码,若站在领域概念角度,就应该建模为拥有两个不同电话号码(PhoneNumber)的员工(Employee)对象:

img

数据模型却不能这样建立,因为我们需要考虑分开两张表带来的 I/O 开销。虽然家庭电话号码和工作电话号码都是相同的 PhoneNumber 类型,但却属于两个不同的属性,将它们合并放到 t_employee 数据表,并不会破坏数据库范式。

当然,这种合并并非必然,有时候还需要考虑数据访问的频率。例如一个银行账户,账户地址、开户日期与余额都是规范化的,按理就应该合并到 t_account 物理表中。但是,余额与其他两项属性的访问频率差异极大,为了使 I/O 效率更高,数据的存储更加紧凑,就应该将规范化的表分解为两个独立的表:

enter image description here

NoSQL 的数据项模型

如果数据库选择了 NoSQL,数据项模型会有所不同。由于 NoSQL 数据库是一种无样式的数据结构(Schemaless Data Structures),这使得它对数据项模型的约束是最少的。诸如 MongoDB、Elasticsearch 这样的 NoSQL 数据库,它所存储的 JSON 文档,可以在属性中进行任意嵌套,形成一种能够自由存取的文档结构。所以 Martin Fowler 又将这样的 NoSQL 数据库称之为“文档型数据库”。

当然,即使是没有样式的 NoSQL,也无法做到随心所欲地建立数据模型,尤其针对表之间的关系,同样要受到实现机制的约束。例如在 MongoDB 中,可以选择使用 Link 或 Embedded 来维护关联关系,这时就需要结合具体业务场景来选择正确的关联关系。

假设我们要开发一个任务跟踪系统,需要能够查询分配给员工的任务。采用 Embedded 方式,Employee 数据模型如下所示:

{name: 'Kate Monster',ssn: '123-456-7890',role: 'Manager',tasks : [{ number: '1234', name: 'Prepare MongoDB environment', dueDate: '2019-01-15' },{ number: '1235', name: 'Import Test Data', dueDate: '2019-02-15' },]
}

如果需要查询员工的任务信息,就可以直接获得内嵌在员工内部的任务数组,无需执行多次查询。这时,选择 Embedded 就是合理的。倘若需要支持如下功能:

  • 显示所有明天到期的任务
  • 显示所有未完成的任务

显然,这两个功能要查询的任务与员工无关,而采用 Embedded 方式建立的数据模型却明确地表达了 Employee 与 Task 之间的父子关系,反而为任务的查询制造了障碍。倘若改用 Link 方式来建立二者之间的关联,情况就完全不同了:

//Tasks
[{_id: ObjectID('AAAA'),number: 1234,name: 'Prepare MongoDB environment',dueDate: '2017-01-15'},{_id: ObjectID('BBBB'),number: 1235,name: 'Import Test Data',dueDate: '2017-02-15'},
]//Employees
{_id: ObjectID('E00001'),name: 'Kate Monster',role: 'Manager',tasks : [ObjectID('AAAA'),ObjectID('BBBB')]
}

通过 Link 建立的数据模型相当于关系数据库建立的主外键关系,去掉了嵌套关系,任务可以被独立查询,如前所述的功能就变得格外简单。但调整后的数据模型又不利于支持查询员工任务的场景了,它会因为关联的原因导致执行两次查询。

选择 Embedded 或 Link 不仅会影响执行效率和执行的简便性,还可能因为错误的建模方式导致数据的冗余。仍然以前面的任务跟踪系统为例,倘若一个任务可以分配给多个员工,就会从一对多关系变为多对多关系。由于 Embedded 方式是将 Task 的数据直接嵌入到 Employee 中,如果别的 Employee 包含了相同的 Task,就会导致 Task 数据的冗余。

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

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

相关文章

ADAS感知摄像头的分辨率与帧率选择分析

说明:可以作为对智能驾驶爱好者对摄像头参数理解或者从业工程人员对设计硬件选型参考 前言 在当前智能驾驶中,基于摄像头的 ADAS 因其应用、更高的可靠性和对新要求的适应性而被广泛采用。 ADAS 摄像头通常部署在汽车的前部、侧面和后部,提…

【代码随想录-哈希表】有效的字母异位词

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学习,不断总结,共同进步,活到老学到老导航 檀越剑指大厂系列:全面总结 jav…

爬什么值得买的榜单——爬虫练习题目一(问)

爬虫题目你敢试试吗? 引言具体原因网站思路总体 我让AI给个框架1. **项目初始化与依赖安装**2. **定义数据模型**3. **网络请求模块**4. **页面解析模块**5. **数据存储模块**6. **主程序流程** 结尾 引言 最近在做什么呢 建立一套完整的信息输入输出系统 在我上一…

Flutter canvas 画一条会动的波浪线 进度条

之前用 Flutter Canvas 画过一个三角三角形,html 的 Canvas 也画过一次类似的, 今天用 Flutter Canvas 试了下 感觉差不多: html 版本 大致效果如下: 思路和 html 实现的类似: 也就是找出点的位置,使用二阶…

图论练习3

内容:过程中视条件改变边权,利用树状数组区间加处理 卯酉东海道 题目链接 题目大意 个点,条有向边,每条边有颜色和费用总共有种颜色若当前颜色与要走的边颜色相同,则花费为若当前颜色与要走的边颜色不同,…

一篇文章了解区分指针数组,数组指针,函数指针,链表。

最近在学习指针,发现指针有这许多的知识,其中的奥妙还很多,需要学习的也很多,今天那我就将标题中的有关指针知识,即指针数组,数组指针,函数指针,给捋清楚这些知识点,区分…

你所不知道的关于库函数和系统调用的那些事

系统调用和库函数的区别 相信大家在面试或者刷面试题的时候经常能看到这样的问题,“简述一下系统调用和库函数的区别”。 系统调用是操作系统提供给用户的接口,能让用户空间的程序有入口访问内核。而库函数数一组标准函数,比如复合 POSIX 或…

机器翻译后的美赛论文怎么润色

美赛论文的语言表达一直是组委会看重的点,清晰的思路和地道的语言在评审中是重要的加分项。 今天我们就来讲讲美赛论文的语言问题。 我相信有相当一部分队伍在打美赛的时候,出于效率的考量,都会选择先写中文论文,再机翻成英文。 …

基于JAVA的宠物管理系统

技术架构: Servlet JSP MySQL 有需要该项目的小伙伴可以私信我你的Q。 功能介绍: 系统主要分为前台和后台两大模块 前台主要由用户体验使用: 用户登录 注册 查找商品 商品类别等功能导航; 后台…

vulhub靶机activemq环境下的CVE-2015-5254(ActiveMQ 反序列化漏洞)

影响范围 Apache ActiveMQ 5.x ~ Apache ActiveMQ 5.13.0 远程攻击者可以制作一个特殊的序列化 Java 消息服务 (JMS) ObjectMessage 对象,利用该漏洞执行任意代码。 漏洞搭建 没有特殊要求,请看 (3条消息) vulhub搭建方法_himobrinehacken的博客-CSD…

移动WEB开发之rem布局

1,rem基础 rem是一个相对单位,类似于em,em是父元素字体大小 不同的是rem的基准是相对于html元素的字体大小 rem的优点就是可以通过修改html里面的文字大小来改变页面中元素的大小,可以整体控制 html{font-size: 14px; } div{w…

自动化测试报告生成【Allure】

之前尝试使用过testNG自带的测试报告、优化过reportNG的测试报告,对这两个报告都不能满意。后经查找资料,发现有个神器: Allure(已经有allure2了,笔者使用的就是allure2),生成的测试报告与上述…