⌨️ 第五章 从设计到测试
📄 本篇摘要

两张设计阶段的图纸:E-R 图画【数据长什么样、彼此什么关系】(静态);DFD(数据流图)画【数据从哪来、流过哪、到哪去】(动态)。图形是客户和工程师之间的通用语——文字歧义,图不歧义。

📝 关系

上一节:测试驱动开发与 XP | 下一节:构建与 make

一、E-R 图:数据的骨架

E-R 图(实体-联系图)三要素:

数据库课 5-5/5-6 用整章练过:实体怎么从需求里认出来、关系怎么定基数。这里补上全局视角:E-R 图是数据库表结构的蓝图——实体变表、属性变列、多对多关系变中间表。图错了,建出来的库跟着错。

  学生 ──< 选修 >── 课程        多对多:一个学生选多门课,一门课多个学生
  (中间表:成绩 —— 选修这个关系自己也有属性)

二、DFD:数据的动脉

DFD(Data Flow Diagram,数据流图)四要素:

符号 名字 含义 例
圆/圆角矩形 加工 处理数据的动作 【计算平均分】
箭头 数据流 数据的流向 【成绩单】
双横线/开口矩形 数据存储 数据停留的地方 【学生成绩表】
矩形 外部实体 系统外的人和系统 【教师】

画法纪律:每个加工都要有进有出(只进不出=黑洞,只出不进=奇迹)——数据守恒是 DFD 的体检标准。分层展开:顶层一张总图,逐层细化到每个加工能落地为止。

三、两张图怎么配合

典型设计流程:DFD 画清楚业务流程(数据怎么流转)→ E-R 图定清楚数据结构(流转中沉淀下什么)→ 由此落地到程序模块与数据库表。教材观点:图不是画给客户看的装饰,是逼开发者把模糊想法想清楚的工具——画不出图=需求没想明白。

四、动手 Demo:把图翻译成代码

# 需求:教师录入成绩,系统计算平均分并保存,学生可查询
# DFD:  教师 --成绩--> [录入并计算] --记录--> [成绩库] ; 学生 --查询--> [成绩库] --分数--> 学生
# E-R:  学生 --< 参加 >-- 考试 ; 考试 --< 属于 >-- 课程   (参加 这个关系带属性:分数)

db = {"exams": [], "scores": {}}   # 数据存储

def record_scores(exam, name_score):        # 加工:录入并计算
    db["exams"].append(exam)
    db["scores"][exam] = dict(name_score)
    avg = sum(name_score.values()) / len(name_score)
    return avg                              # 数据流:平均分流回教师

def query(exam, student):                   # 加工:查询
    return db["scores"].get(exam, {}).get(student)

avg = record_scores("期中数学", {"波仔": 88, "小红": 92, "小明": 75})
print("教师侧·平均分:", avg)
print("学生侧·波仔查分:", query("期中数学", "波仔"))
print("学生侧·查无此考:", query("期末数学", "波仔"))

沙箱实跑输出:

教师侧·平均分: 85.0
学生侧·波仔查分: 88
学生侧·查无此考: None

看到什么算成功:平均分 85.0(88+92+75=255÷3)、查询与查无分别返回 88 和 None。

读结果:代码的每个函数对应 DFD 的一个加工、每个变量对应一个数据存储——图和代码是一一映射的。查无此考返回 None(不是报错)也是设计决定:查询类加工【查不到】是正常输出流,不是异常。

五、30 秒实验

给 Demo 加一个加工【统计不及格名单】:输入成绩库、输出名单——先在纸上画 DFD(一个加工+两条数据流),再照着写函数。体验【先图后码】的顺滑。

六、常见误区

误区 真相
图是给客户看的宣传品 图主要是逼自己想清楚的工具;客户能看懂是副作用
多对多直接连线建表 多对多必须拆中间表(数据库课 5-6 的铁律)
DFD 里加工可以只有输出 数据守恒:每个加工有进必有出,否则是设计漏洞
自测三问(点击展开) 1. **E-R 图三要素?** 答:实体(矩形)、属性(椭圆)、联系(菱形+基数)。 2. **DFD 四要素?** 答:加工、数据流、数据存储、外部实体。 3. **多对多关系在数据库里怎么落地?** 答:拆成中间表,关系自身的属性(如成绩)放中间表里。

相关笔记