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

news2024/12/28 22:17:01

在 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.coloradmin.cn/o/1434473.html

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

相关文章

【INTEL(ALTERA)】为什么在编译 HDMI 英特尔® FPGA IP设计示例 VHDL 变体时看到错误 (13879)?

说明 由于英特尔 Quartus Prime Pro Edition 软件版本 23.2 存在一个问题,您在编译 HDMI 英特尔 FPGA IP设计示例的 VHDL 变体时可能会看到以下错误: 错误 (13879): VHDL 绑定指示 hdmi_rx_ram_1port_intel_mce_2010…

Java设计模式大全:23种常见的设计模式详解(一)

本系列文章简介: 设计模式是在软件开发过程中,经过实践和总结得到的一套解决特定问题的可复用的模板。它是一种在特定情境中经过验证的经验和技巧的集合,可以帮助开发人员设计出高效、可维护、可扩展和可复用的软件系统。设计模式提供了一种在…

缩略图保持加密(TPE)论文

文献: R.Zhao,Y.Zhang,Y.Nan,W.Wen,X.Chai,andR. Lan, “Primitively visually meaningful image encryption: A new paradigm,” Inf. Sci. (Ny), Vol. 613, pp. 628–48, 2022. DOI: 10.1016/j.ins.2022.08.027. (1) 第1行:原始图像 第2行:加密图像 加密的目标: 原始…

synchronized内部工作原理

作者简介: zoro-1,目前大二,正在学习Java,数据结构,javaee等 作者主页: zoro-1的主页 欢迎大家点赞 👍 收藏 ⭐ 加关注哦!💖💖 synchronized内部工作原理 syn…

运维监控之MySQL死锁查询及监控

死锁是指两个或两个以上的事务在执行过程中,因争夺资源而造成的一种相互等待的现象,若无外力作用,它们都将无法推进下去,此时称系统处于死锁状态或系统产生了死锁。 为了监控MySQL的死锁情况,可以使用以下方法&#xf…

【论文解读】Point Transformer

Point Tranformer 摘要引言方法实验结论 摘要 自注意网络已经彻底改变了自然语言处理,并在图像分析任务(如图像分类和对象检测)方面取得了令人印象深刻的进展。受这一成功的启发,我们研究了自注意网络在三维点云处理中的应用。我…

流浪动物救助|基于Springboot的流浪动物救助平台设计与实现(源码+数据库+文档)

流浪动物救助平台目录 目录 基于Springboot的流浪动物救助平台设计与实现 一、前言 二、系统功能设计 三、系统实现 1、用户信息管理 2、动物信息管理 3、商品评论管理 4、公告信息管理 四、数据库设计 1、实体ER图 五、核心代码 六、论文参考 七、最新计算机毕设…

常用Hallmark及KEGG、GO基因查询

文献:The Molecular Signatures Database (MSigDB) hallmark gene set collection - PMC (nih.gov) GSEA | MSigDB | Browse Human Gene Sets (gsea-msigdb.org)通过msigdb数据库可以查看各个Hallmark、KEGG、GO具体包含的基因细节。 Hallmark nameProcess categor…

python中的三种程序控制结构-顺序结构、分支结构、循环结构

程序控制结构 一、顺序结构二、分支结构三、循环结构条件循环-while遍历循环-for循环控制-break、continue 一、顺序结构 顺序结构是指程序在执行时按照代码的顺序逐一执行,每一行代码只执行一次,然后依次执行下一行代码。顺序结构是程序最基本的执行方式…

springboot果蔬配送商城

技术架构: java mysql bootstrap jquery mybatis springboot 有需要该项目的小伙伴可以私信我你的Q。 功能介绍: 系统基于Java技术进行开发,后台数据库使用MySQL,在Windows环境下使用idea开发工具进行开发,主…

异地办公必不可缺的远程控制软件,原理到底是什么?

目录 引言远程桌面连接软件的作用与重要性 基本概念与架构客户端-服务器模型网络通信协议 核心技术组件图形界面捕获与传输输入转发会话管理 性能优化策略带宽优化延迟优化 引言 远程桌面连接软件的作用与重要性 在当今这个高度数字化和网络化的时代,远程桌面连接软…

基于springboot智慧养老平台源码和论文

首先,论文一开始便是清楚的论述了系统的研究内容。其次,剖析系统需求分析,弄明白“做什么”,分析包括业务分析和业务流程的分析以及用例分析,更进一步明确系统的需求。然后在明白了系统的需求基础上需要进一步地设计系统,主要包罗软件架构模式、整体功能模块、数据库设计。本项…

Yarn常见问题处理

任务出现container OOM异常导致作业失败 原因 Container内存不足或者作业数据倾斜 解决方案 检查Container相关参数,判断是否设置过小(低于4GB)。如果Container小于4GB,优先考虑调大当前作业container大小,如果是Tez任务,还需要同步调整以下参数 # tez container size…

教你一招如何半小时把C语言的 scanf printf sscanf sprintf fscanf fprintf wscanf wprintf 玩出花来

本篇会加入个人的所谓‘鱼式疯言’ ❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言 而是理解过并总结出来通俗易懂的大白话, 我会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的. 🤭🤭🤭可能说的不是那么严谨.但小编初心是能让更多人能…

SpringBoot注解--04--@Repository 和@Mapper的区别

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 1.Repository的作用1.1 含义1.2 Repository与Service和Component有什么区别?1.3 使用场景单独使用Repository,需要配合使用MapperScannerCon…

微信小程序的图片色彩分析,窃取网络图片的主色调

1、安装 Mini App Color Thief 包 包括下载包,简单使用都有,之前写了,这里就不写了 网址:微信小程序的图片色彩分析,窃取主色调,调色板-CSDN博客 2、 问题和解决方案 问题:由于我们的窃取图片的…

【ArcGIS微课1000例】0102:面状要素空洞填充

文章目录 一、实验描述二、实验数据三、实验步骤1. 手动补全空洞2. 批量补全空洞四、注意事项一、实验描述 在对地理数据进行编辑时,时常会遇到面数据中存在个别或大量的空洞,考虑实际情况中空洞的数量多少、分布情况,填充空洞区域可以采用逐个填充的方式,也可以采用快速大…

安全SCDN有什么作用

当前网络安全形势日益严峻,网络攻击事件频发,攻击手段不断升级,给企业和个人带来了严重的安全威胁。在这种背景下,安全SCDN作为一种网络安全解决方案,受到了广泛的关注。那么,安全SCDN真的可以应对网络攻击…

十分钟掌握前端获取实时数据的三种主流方式

前端获取实时数据的三种主流方式 本文聊聊前端获取实时数据的三种主要方式。想象一下,我们在网上购物时,经常能看到最新的优惠信息弹出,或者在社交媒体上看到朋友的最新动态更新。这些都是因为后端在默默地向我们的页面推送了最新的消息。那…