ER 模型背后的建模哲学

2023-09-17 14:35:32 浏览数 (1)

将具体的业务场景数字化,首先需要对场景进行抽象和设计。业务场景中的概念及其联系,落到硬盘上就是数据库中的一张张表,加载到内存中便是编程语言的一个个类。因此,对具体场景进行建模时,最重要的便是数据库表的设计和软件类图的设计,而他俩又基本上是一一对应的。

比如,对于一个“二手书管理系统”,总得设计仓库、书籍、订单、用户、配送等等概念,对应到数据库中就是相应的表,再映射到编程语言上,便是一个个类。前者常使用 ER 模型进行辅助设计,识别问题域中关键的概念和联系,进行图形化的、精确化的描述;后者当然有很多 ORM 框架和 UML 类图之类的来表示。

虽然这些都是在前现代时期,开发企业软件时,常所需要遵循的流程。而在当下互联网快速迭代环境中,已经很少严格使用这些工具一板一眼的进行设计了。但 ER 模型中识别物理场景中的关键概念和联系的手段,在我们对实际问题域进行理解时,确有诸多可借鉴之处。

基本概念

ER 模型中基本概念比较少:

  1. 实体(Entity)
  2. 关系(Relation)
  3. 属性(Attribute)

可以看出这些概念和属性图[1](property graph)中的一致。这至少说明两个问题:

  1. 这几个概念是数据建模的核心元素。
  2. 使用 ER 建模之后,既可以实现为关系型数据库、也可以实现为图数据库。

实体(entity)是物理世界中一些可区分的对象。根据场景,可大可小,可以拆分和合并。比如要实现一个“学生信息管理系统”,大学中的学生就是一个实体。每个实体可以包含一组属性(properties),其中一些属性或者属性集,可以用于在该问题域中将一个实体从任意其他实体中区别出来,我们通常称之为主键(primary key)。比如学生可以有学号、姓名、性别、年龄、入学年份、所学专业等基本信息,其中学号能在该学校中唯一定位一个学生。

实体是一个概念,可以对应编程语言中类,也可以理解为一个 Excel 中由表头确定的一个表。而实体的一个对象,则对应编程中的一个类的实例,也对应 Excel 表格中的一行。

在不同实体间,可能会存在某种关系(relation)。比如,学生和课程——由于专业不同,学生要学习不同的课程。则学生—学习—>课程 就是一个关系。关系很像一个谓词,当然也能名词化——将关系转化为一个实体。比如我们可以将“学习”这个关系转化为实体,然后给其附加一些属性,比如所在学期、上课教室、授课老师等等。

一个学生管理系统的类图

说到转化,属性本身也可以转化为实体,这其实就是一个建模粒度的问题。比如,一开始我们对场景的建模不尽精细,比如“上课地点”就用一个字符串类型的属性来标识,但随着建模的完善,上课地点也可以细化为一个包含教“学楼”、“楼层”、“教室号”等属性的实体。

总结下,取决于我们建模的理解方式和精细程度,实体、关系和属性都是可以互相转化的。通过合理使用这三种概念,我们可以在一定程度上抽象出问题域中所涉及到基本概念,以及概念的内涵(属性)和外延(与其他概念的关系)。通过这些定义,我们最终会将某个场景中我们所关心的点进行数字化。当然,如果随着软件的迭代,如果我们发现遗漏了一些概念,或者某些概念需要细化,则可以及时调整建模。

实体的分类

ER 模型把实体分为强实体(strong entity)和弱实体(weak entity),也可以理解为独立实体依赖实体

举个例子,在“宠物医院信息管理系统”的场景中,会涉及人和宠物两个实体。人通常有 ID(比如手机号),然后人也会给所养的宠物起一个名字,通常一人的所有宠物名不会重复,但是不同人的宠物名很可能会重,比如“小强”。这也就是为啥你去宠物医院带宠物看病时,前台总会留下你的手机和宠物的名字。在这个场景中,人是一个强实体,其手机号是一个主键(primary key,可以唯一定位一个人);宠物是一个依赖人的弱实体,其名字是一个部分主键(partial key),需要依赖对应强实体(手机号 宠物名)才能够被唯一确认。

宠物医院类图

关系的特点

实体与实体间关系的一个最重要特征便是基数(cardinality)和参与度(participation)。前者就是我们常说的:一对一的,一对多的,还是多对多的关系。后者就是说,在该关系中,一个实体对于另一个实体来说,是必要的还是可选的

以上面“宠物医院”为例,

基数:人和宠物之间是 1:N的关系,即一个人会养多个宠物,但一个宠物一般来说只有一个主人。

参与度:每个宠物必须有个主人,否则就是野生或者流浪动物了,但人可以不养宠物。也就是说,对于宠物来说,人是必须的;但是对于人来说,宠物是可选的。

让我们重新理解下上图,对于 Pet 来说,Person 是 1..1,前面的 1 是参与度,意味着对于宠物来说,人是必须的;后面的 1 是基数,意味着一个宠物(一般来说)最多有一个主人。

关系还有一个(degree)的概念,与图中入度出度的概念类似,一般我们常见到的都是二元关系(binary relation),即关系中只涉及两个实体。但也有一些高维关系,比如:大作业检查,同时涉及“助教”、“学生”和“大作业”课程三个实体。但一般来说,高维关系都能拆成二元关系,就跟多叉树都有二叉树的等价表示同理。

属性的类型

最常见的就是简单属性。稍微复杂一点的有:

  1. 复合属性(composite attribute):一个属性包含几个子属性,这是典型的可以转换为实体的属性。比如一个学生的家庭住址,可能包含邮政编码、省、市、区、街道、小区、楼层、门牌号等等子属性。
  2. 多值属性(multi-value attribute):一个属性里可以塞多个值,这种属性我们常将其拆为关系。比如一个导师会带一个到几个学生,这几个学生可以作为多值塞到一个属性里,可以单独拆出一张表示师门关系的表中。

可以看出,用属性还是用实体、关系,无非就是一个度的问题。如果属性本身还算简单、建模比较粗糙,完全就可以用属性来表达稍微复杂一点的语义。如果属性太复杂,则就要考虑拆成实体或关系了。

小结

无论是对数据进行建模,还是梳理代码中类的关系,其本质都在于:在一种合理的现实(或者隐喻)下,界定好每个概念的内涵(属性)和外延(关系),用尽可能简单的方式(比如消除一些传递依赖造成的冗余)对我们所关心的点进行采样建模(类似于对物理世界的一些部分信息建立了一个视图)。

参考资料

[1]

属性图: https://xiaobot.net/post/23f0bf11-e167-4f80-8415-2eb4ab1797b5

0 人点赞