一、数据流图和数据字典是用来干啥的?
2、数据字典(Data Dictionary)
二、详细介绍数据流图和数据字典
(Ⅱ)数据流图设计的原则
(3)、守恒加工原则(前两条都是针对加工而言)
⑦、很容易被忽视的一点:数据存储不可能凭空出现在数据库管理系统中,必须通过操作系统从磁盘中读取相应的文件载入内存,当对数据存储文件操作完成之后,再写入磁盘。但是正是因为所有的数据流图都有这一类数据流,所以常常被作为枝节被省略,这导致在研究细节的时候发现很多数据流图都没有遵守守恒加工原则;所以完整的数据流图应该是这样(用虚线表示省略的):
这个时候我们就可以理解为:从操作系统中读取的文件与外部实体给予的信息进行组合(数据加工),最后形成了新的文件并写入磁盘中。
(4)、父图与子图应该统一输入输出流:父图可以看做是一个整体,也就是一个黑盒子,其中包含了很多个子图,那么子图的输入输出流当然就源自黑盒子(父图);比如学生选课后出了成绩:
一共分了两个区域(上下),上部分为整体的局部数据流图,数据处理由一个父图构成;下部分即为父图中更加细节的子图数据流图。这个时候我们可以看到父图由外部数据流(\(CourseSchedulingInfo\)、\(ScoreInfo\)、\(CourseInfo\)、\(StudentInfo\))的参与产生了一个新的数据存储(\(Student\_Course\)),必须将其提出放在父图的外部,如果不这样做的话就会违反守恒加工原则。由父图子图流一致原则我们可以得出另一重要的原则:加工细节隐蔽原则,就是说没有必要一味地对父图进行拆分,可以适当地只保留父图不去关心子图的内在联系(类比整体法)。
(5)、简化加工之间的关系加工间的数据流越少,各个加工就越相对独立、耦合度就越低,如果数据流很多的话,虽然可以实现较为复杂的功能但是也增加了运维成本,甚至可能造成动一发而牵全身的混乱局面。这就要求我们做到。
(6)、均匀分解父图尽量不要出现对数据处理分解的两极化,比如一个分了七八层而另一个只分了两三层,这样会造成轻重不一的局面存在考虑不周的潜在隐患。
(7)、是数据流而不是控制流数据流是控制流上的操作表示,只有在控制流上进行的数据流分析才有价值。也就是说数据流图只需要表达出数据的结构、来源、流向、加工,并不关心数据流在融入控制层之后进行的逻辑处理与程序跳转的结果(程序元素逻辑执行的先后顺序)。
在这些原则中的当属:保持父图与子图平衡,保持数据平衡,加工细节隐蔽。
2、数据字典
我们言归正传,数据结构的描述通常采用如下表中的符号:
比如我们要表示学生这个实体集(或者学生表)时,就可以这样:
\(StudentEntity=studentID+studentName+studentIDCard+studentSex+\{studentInterest\}+(studentInfo)\),
再比如我们新建一个可以实现查询的任务,包括查询学生信息、课程信息以及学生选课信息,这是当数据库管理员(或者教务系统管理员)向教务管理系统发出查询请求(数据流)的时候就可以这样表示:
\(selectRequestInfo=[selectStudentInfo\ |\ selectCourseInfo\ |\ selectStudent\_CourseInfo]+\{IllegalRequest\}\),
三、数据流图 & 数据字典 综合应用问题
(2)、注销师生和课程学生毕业、老师退休以及课程结课的时候需要分别编制《学生毕业单》、《老师退休单》、《课程结课单》,然后分别修改《学生表》、《教师表》、《课程表》中的注销时间以及是否注销(默认值为\(NO\),现改为\(YES\))。
(3)、学生选课出成绩学生选课时需要编制《学生选课申请单》和《学生最新选课单》。
假设选课权重在同一学号记录中不能重复,且为[1, 6]之间的整数,当学生提交《学生选课申请单》时系统给出选项,学生自行选择,即限定每个学生的选课门数最多为6门。此外系统应该有三层过滤网(这三层过滤可以放置在一个加工中——加工细节隐蔽原则):
经过系统的三层排除冲突之后的《学生最新选课单》方能写入《学生选课表》。之后学生考试填写试卷,教师批阅提供分数信息,将分数信息与选课信息合并存入《学生选课表》。
(Ⅱ)信息查询功能:查询教师学生和课程的基本信息、学生成绩
2、数据流图
(Ⅰ)顶层图:
(Ⅱ)第0层图:
(Ⅲ)加工的分解:
3、数据字典
\(Excel\)查看传送门:数据字典-教务管理系统部分功能
\(Excel\)下载传送门:数据字典-教务管理系统部分功能。
四、数据字典的补充
数据字典不单单是用于解释数据流图,还能在数据存储文件设计的时候提供援助。当现实世界中的主体有不断变化的属性时(属性的数量和属性的取值),尤其是变化得非常频繁的时候,就会引入数据字典辅助数据表设计。
这里简单地介绍一下由\(rongwenbin\)先生总结的两种用于辅助设计数据库表的数据字典,原文传送门:数据字典。为了更好理解我将先生用到的实例换做我们常见的教务管理系统,其主要功能为管理并查询学生、教师、课程……等实体集的基本信息。
在构建数据库管理系统之前,我先将两种数据字典摆出来:
我们来看这样一个需求:假设我们已经设计出了该教务管理系统的逻辑模型初稿,其中有一个模式为“学生(学号,姓名,系别名称)”。在这一模式中体现出了“学生”实体和“学生属于系别”联系,虽然一箭双雕提高了查询的效率,但是这里很明显存在一个问题:系别的名称如果更改,则学生表中的"系别名称"属性的取值都要做出相应的调整,这系别名称还好,如果是国籍呢,比如前苏联到俄罗斯,这就要涉及到上亿份数据。怎样解决这一问题呢?先生指出我们可以参考(Ⅰ)数据字典,新建一张《系别表》,其中存放"系别\(ID\)"和"系别名称",这样在学生表中直接引入外键"系别\(ID\)"即可,这是更改系别名称就只用在《系别表》中更改"系别名称"而"系别\(ID\)"不用改,保证了《学生表》的稳定性。上述文字转换为数据表的动态变换就是:
更改之前的数据库表《学生表》及实例:
更改之后的数据库表《学生表》及实例:
新建的《系别表》及实例:
根据上级的命令更改数据,将“地理信息系统”改为“地理信息科学”这样的话就会有:
更改之后的数据库表《学生表》及实例:
新建的《系别表》及实例:
显然《学生表》没有任何改动。
这样很\(nice\)但是有没有想过如果一个主体中的属性不是两三个,而是几十个甚至上百个,那么每一次查询都涉及到上百个夺标连接操作,这时的查询效率简直不敢恭维。于是先生又提出了第二种方案:(Ⅱ)数据字典,将属性数据表进行合并,但是并不是将所有的数据表进行合并,而是针对模式(结构)一样的一组表。这样就能将查询所涉及到的表大幅度的减少,从而提高了查询的效率。下面我们来看一个案例,解释(Ⅰ)的缺点和(Ⅱ)。
我们现在有一个需求:假设我们更新了模式,最后变为“学生(学号,姓名,证件类型,证件号,国籍,民族,系别名称,政治面貌)”,根据(Ⅰ)的分解,我们可以将模式继续升级为“学生(学号,姓名,证件类型\(ID\),国籍\(ID\),民族\(ID\),系别\(ID\),政治面貌\(ID\))”、“证件类型(证件类型\(ID\),证件类型,证件号)”、“国籍(国籍\(ID\),国籍)”、“民族(民族\(ID\),民族名称)”、“系别(系别\(ID\),系别名称)”、“政治面貌(政治面貌\(ID\),政治面貌名称)”,就这样一直被分解,如果只是5个左右的表那查询起来也不是很费劲,但是一个学生显然不可能只有这样几个属性,所以如果继续分解下去就会带来过于沉重的查询计算量。
既然我们的目的是为了提高查询效率,那个合并数据表显然是一个不错的选择,但是我们知道一个数据表的模式是定死了的,并且属性的取值是必须规定在同一个域,所以只有表结构相同、对应属性的取值范围相同的表才能够合并。我们将目光转移至分解之后的属性表,发现除了《证件类型》这张表之外都很相似,模式都是“属性的名称(ID,属性的值)”,那我们就可以合并了。回过头看《证件类型》这张表,不难发现"证件号"可以作为主码,从而代替"证件类型\(ID\)",这样《证件类型》表的模式为“证件类型(证件号,证件类型)”。这时我们整合这些属性表,得到一个新的表模式“属性(属性\(ID\)号,属性分类\(ID\)号,属性取值)”,构造一个实例:
《系统属性代码表》
《学生表》
《属性表》
这样在查询任意一个学生的时候最多也就是3张表的查询,一张差姓名、另外两张查找其他属性\(ID\)以及对应的内容,这样查询效率是不是就大大提升了呢?但是细心的同学会发现这样做的后果就是造成了最开始的问题:对数据库进行更改很麻烦。所以这里我想做的一点补充就是:这两种数据字典的思想要相结合,我们可以在需求分析阶段调查不易改变的属性名称,将这些属性名称利用(Ⅱ)数据字典整合成为一张表;相应地将容易改变的属性名称利用(Ⅰ)数据字典构造一张新的属性表。就拿上面这个例子来说,对于“国籍”、“证件类型”、“民族”、“政治面貌”对于我们来说在相当长的一段时期内属性的名称是不会变化的(可能我们会变成党员,但是团员还是叫做团员),而“系别”可能就会有所调整,所以我们可以构建这样4张表:“学生(学号,姓名)”、“系别(系别\(ID\),系别名称)”、“系统属性代码(属性\(ID\)号,属性分类,属性取值)”、“属性表(学生\(ID\) ,\(ID\)属性\(ID\))”,其中表示系的时候在《系统属性代码表》中体现:
《系统属性代码表》
《系别表》
数据流图 && 数据字典就到这了,不知道你们有没有弄懂?(反正我是明白了【狗头保命】)