软件工程三图实战:DFD、ER图与状态转换图详解

发布时间:2026/9/26 1:08:12
软件工程三图实战:DFD、ER图与状态转换图详解 1. 三种图的分工先想清楚它们各管哪一段结构化分析这玩意儿说白了一句话把用户嘴巴里说的需求翻译成工程师能照着设计的东西。用户说“我要一个能借书的系统”你不能直接开始写代码你得先搞清楚数据从哪来、存成什么样、状态怎么变。于是就有了三张图——数据流图DFD、ER图、状态转换图STD它们各管一摊合起来才是完整的逻辑模型。很多人学软工栽就栽在没搞明白这三张图的分工拿到题就乱画画完自己都说不清画的是啥。我先用大白话把三张图的定位敲死数据流图回答的是“数据怎么流动”谁把什么数据交给了谁中间经过了哪些加工最后存到哪儿。它是功能视角盯着动词。ER图回答的是“数据长什么样”有哪些实体、实体有什么属性、实体之间什么关系。它是数据视角盯着名词。状态转换图回答的是“某个东西在不同条件下怎么变”比如一本书从“在架”变成“已借出”再变成“逾期”。它是行为视角盯着状态。打个比方你要描述一个食堂的打饭流程。DFD说的是“学生拿餐盘→窗口阿姨打菜→刷卡扣费→出餐”ER图说的是“学生表、菜品表、订单表以及它们的关系”状态图说的是“一个订单从‘已下单’变‘制作中’变‘已完成’”的过程。三张图合在一起食堂的运作规则才完整。考试也好、做项目也好最常见的坑就是拿到题目先画图画到一半发现哪里不对劲又推倒重来。原因是没先看题目里有几个“角色”、几个“数据仓库”、几个“关键状态”。下面我用一套完整的例题串讲把三种图从头到尾撸一遍画完你就能直接套用到任意类似题目上。2. 数据流图DFD从上下文图到0层再到1层逐层剥洋葱2.1 四个基本符号先把语言学会DFD的四个符号一定要刻在脑子里考试经常让你“指出图中错误”90%的错误都出在符号用错上符号名称作用画法要点圆角矩形或矩形加工/处理把输入数据变成输出数据必须有输入有输出不能只有输入或只有输出箭头数据流数据在流动箭头上必须标名字不能出现“控制流”或“物质流”双杠线数据存储数据暂时或长期存放通常用“D1学生表”这种编号名称方式矩形外部实体数据的来源或去向只画在图的边缘不能出现在图内部这里有个最容易翻车的点**数据流只能连接“加工”和“加工”、“加工”和“存储”、“加工”和“实体”之间不允许实体直接连实体、存储直接连存储、实体直接连存储。**我见过太多新手把“学生”直接连到“图书表”上这种图交上去基本就凉了。2.2 经典例题图书馆借阅系统题目背景几乎每个学校软工课都会出的题某图书馆借阅系统读者可查询图书、借书、还书。管理员负责图书入库、读者注册。系统需要记录读者信息、图书信息、借阅记录。借书时先检查读者是否有逾期未还的图书有则拒绝借书无则办理借书并将借阅记录写入数据库。还书时更新借阅记录若超期则计算罚款。拿到这种题第一件事不是画图而是圈关键词。我教你一个土办法拿笔在题目里圈“动词”和“名词”。动词对应加工名词对应实体或存储。圈完你就有了原材料。第一步画上下文图顶层图。上下文图是整个系统最外层的视图它只有一个加工——就是整个系统本身。你要找出所有和系统打交道的“外部实体”。这题里明显有读者、管理员。于是图就长这样读者 ——(查询请求/借书请求/还书请求)—— [图书借阅系统] ——(查询结果/借书结果/罚款单)—— 读者管理员 ——(图书入库信息/读者注册信息)—— [图书借阅系统]注意上下文图里只有加工、外部实体、数据流没有数据存储。因为存储是系统内部的细节最外层视图看不到。这是很多新手画错的地方一上来就画了好几层你得分清楚视角。第二步画0层图系统内部第一层。把“图书借阅系统”这个大加工拆成若干个子加工。拆的粒度怎么把握一个加工对应一个相对独立的功能这题拆成五个1.1 图书查询1.2 读者注册/管理1.3 图书入库1.4 借书处理1.5 还书处理外部实体还是那两个再加上数据存储D1读者表、D2图书表、D3借阅记录表、D4罚款记录表。数据流的走向要仔细读者发出“借书请求”→ 借书处理(1.4)先查D1读者表确认资格 → 再查D2图书表确认在架 → 写入D3借阅记录表 → 返回“借书成功”。这里有一个关键设计“可借资格”和“图书状态”这两条数据流是加工去读存储而不是存储自己把数据推给加工。箭头方向就是读的方向。第三步画1层图分解关键加工。比如1.4借书处理内部还可以细分校验读者资格、校验图书状态、生成借阅记录。这时候你会发现能拆出更细的加工数据流也跟着细化。1层图开始出现“非法借阅请求被拒绝”这类分支。分层的核心法则父图的加工和子图的输入输出必须一致这叫“父子图平衡”。也就是说0层图里1.4借书处理的输入是“借书请求”输出是“借书结果”那么1层图里整个子图的总输入也必须是“借书请求”总输出必须是“借书结果”不能突然多出一条“查询图书”的数据流。2.3 DFD中的“黑洞”“奇迹”和“灰洞”画DFD还有一个保命题检查加工的输入输出是否合理。三大类错误必须会认黑洞加工只有输入没有输出。数据进去就没了不合逻辑。奇迹有输入无输入也叫奇迹这里是常见说法“无输入有输出”加工只有输出没有输入数据凭空产生。灰洞加工虽然有输入也有输出但输出不是由输入推导而来比如输入是“学生姓名”输出却是“考试成绩”明显对不上。我在实战中还有一个体会数据流图上的每个箭头都要能讲出一个“动词短语”。比如“借书请求”这条箭头是“读者发出的借书请求”不是含糊的“信息”。把每条箭头的含义用中文在旁边标一下后续检查逻辑会省很多力气。考试时考官看你的图本质上就是在看你能不能把每个箭头讲圆。2.4 我画DFD的习惯流程可直接抄作业我画DFD有一套固定流程拿任何题都够用你们可以直接套读题两遍圈出所有外部实体系统外的角色。圈出所有核心业务动作动词每个动词先记成一个候选加工。圈出所有数据名词分类为“实体属性”还是“存储文件”。先画上下文图只画一个加工加外部实体。再画0层图把候选加工合并成5~7个大的加工并画出存储和数据流。逐项检查有没有黑洞/奇迹/灰洞有没有实体直接连存储有没有数据流没标名字如果0层某个加工太复杂继续分解到1层并做父子图平衡检查。这套流程我用了十年考软工的时候靠它拿的分做项目需求分析时靠它给团队讲逻辑目前还没翻过车。3. ER图把题目里的名词变成一张能建库的图3.1 实体、属性、联系三位一体ER图是数据库设计的前置工作它的核心是回答这个世界里有哪些对象、对象长什么样、对象之间怎么关联。考试考ER图其实就在考你能不能从一段文字里摸清这“三件套”。实体一个独立存在的对象类型比如学生、图书、订单。属性实体的特征比如学生的学号、姓名、专业。联系实体之间的关联分为1:1、1:n、m:n三种。画法细节也要注意实体用矩形框属性用椭圆联系用菱形。实体和属性之间用直线相连联系和参与的实体之间也要连线并在连线旁标上基数1、n、m。主键属性下方加下划线这是区分实体身份的关键。没有主键属性的实体基本画不成表。3.2 图书馆系统的ER图怎么画沿用上面的图书馆借阅系统题目我们来做ER图。先圈实体读者、图书、借阅记录还有管理员如果要为管理员建模的话。再圈属性读者读者编号主键、姓名、证件号、联系电话、注册日期图书图书编号主键、书名、作者、出版社、ISBN、库存状态借阅记录记录编号主键、借书日期、应还日期、实际还书日期、状态在借/已还/逾期联系怎么定核心问题是“一次借书涉及哪个读者和哪本图书”。一个读者可以借多本图书一本图书可以被多个读者在不同时间借阅。所以“读者-图书”之间是典型的多对多联系。但多对多联系在关系数据库里不能直接建表必须拆成“借阅记录”这个中间实体——这正好是题目里已有的实体。所以更严谨的建模是读者和借阅记录1:n图书和借阅记录1:n于是ER图的结构就清晰了读者(1)—(n)借阅记录(n)—(1)图书借阅记录本身有独立的属性。一个图书的“库存状态”有点特别如果你把状态设计成借阅记录的属性那同一本书的多条记录会有多个状态反而矛盾。正确的做法是“在架/借出”状态放在图书实体上而借阅记录上的状态是“正常/逾期/已还”。状态到底放哪儿面试官和考试特别喜欢挖这个坑。3.3 结合热词电影评分与评价系统的ER图热词里有一条“画出电影评分与评价的er图”这题也很有代表性顺手讲一下。题目大概长这样用户可以对电影打分1~10分也可以写文字评价。一个用户可以对多部电影评分一部电影可以被多个用户评分。用户和电影之间的“评分”是多对多用户和电影之间的“评价”也是多对多。实体用户用户ID、昵称、电影电影ID、片名、上映年份、评分记录评分ID、分数、评分时间、评价记录评价ID、内容、评价时间。这里有个细节**“评分”和“评价”是两个不同的联系要不要建模成两个实体**我的答案是如果评分和评价有各自的额外属性且互不影响就该拆成两个实体如果只是“一条内容里既有分数又有文字”那可以把它们合并成一个“用户评价”实体分数和文字都是它的属性。取决于题目怎么描述。这个“判断拆不拆”的能力就是软工考试拉开分差的地方。3.4 ER图怎么转成关系模式考试附赠题ER图画完很多题目还会让你“转换成关系模式”。转换规则是固定的背熟就完事联系类型转换策略1:1在任意一端加入对方的主键1:n在n端加入1端的主键m:n单独建一张表表中包含两端的主键作为联合外键再加上联系自身的属性借阅记录已经是单独实体所以转换很简单借阅记录表包含记录编号、读者编号外键、图书编号外键、借书日期、还书日期等。外键这俩字一定要写出来阅卷老师看到外键才知道你懂关系模式。我自己做项目时有过一个教训 ER图画得挺漂亮建表时才发现某个联系忘了加外键结果联表查询全是笛卡尔积排查了半天。所以你们画完ER图一定要自己问一遍这个联系如果建表外键加在哪一端问不出来就说明ER图没画严谨。4. 状态转换图让每个关键对象的状态变化无处可藏4.1 状态、事件、动作三要素一个不能少状态转换图解决的是另一个问题某个对象在生命周期里遇到什么事件会从什么状态变成什么状态同时触发什么动作。软件工程里一般用它来建模单个对象的行为而不是整个系统。三个核心概念状态对象在某个时刻的稳定情形比如“在架”“已借出”。事件导致状态发生变化的外部触发比如“读者借书”。动作状态变化时系统要执行的操作比如“扣库存”“记日志”。画法上状态用圆角矩形事件/动作标注在箭头上初始状态用一个实心小圆点表示有的教材也会用一个单独的“初始”状态终止状态用实心圆点加空心圆环表示。一个图至少要有一个初始状态可能有多个终止状态也可能没有终止状态比如系统持续运行。4.2 经典例题图书的状态转换回到图书馆借阅系统我们挑“图书”这个对象画状态图。图书的状态其实比你想的多在架可借初始状态。已借出读者借书成功后进入。逾期超过应还日期未归还由“已借出”在时间事件触发下进入。下架/遗失特殊状态下架处理。箭头这样标在架 --借书成功-- 已借出已借出 --还书-- 在架已借出 --借期超时/未还-- 逾期逾期 --归还并缴清罚款-- 在架在架或已借出 --管理员标记遗失/损坏-- 下架这里有一个特别容易漏的点“逾期”不是读者做了什么动作而是时间到了自动发生。所以画图时事件写“日期超过应还日期”而不是“读者逾期”。考试中有些同学把逾期写成借书后立刻发生那就错了——还得先借出去才能逾期。4.3 结合热词打印机状态转换图热词里有一条“打印机状态转换图”这题超级经典很多学校题库里都有。打印机这个对象的状态转换比图书稍微复杂一点但正是练手的好题。打印机的状态空闲、打印中、暂停、故障、脱机。事件和迁移可以这样理空闲 --收到打印任务-- 打印中打印中 --任务完成-- 空闲打印中 --用户暂停/缺纸-- 暂停暂停 --恢复-- 打印中打印中或暂停 --卡纸/硬件故障-- 故障故障 --维修完成-- 空闲或回到等待状态看具体设计这题的考点是一个状态可以由多个事件进入一个事件也可以触发多个状态迁移关键在于事件条件的优先级。比如“缺纸”和“卡纸”都发生在“打印中”但缺纸可能进“暂停”卡纸可能进“故障”。画图时要把事件名称写具体不能只写“出错”两个字就完事。4.4 状态转换图的检查方法检查状态图有没有画漏最实用的办法是穷举状态迁移表把每个状态、每个可能的事件都列一遍当前状态触发事件下一状态系统动作在架借书成功已借出登记借阅记录、更新图书状态已借出还书在架更新还书日期、解除借阅占用已借出超过应还日期逾期标记逾期、生成罚款逾期归还并缴款在架登记归还、清除罚款记录任何状态管理员标记遗失下架删除可借状态、记录丢失表格一列你马上就能发现有没有漏状态、漏事件。状态图最忌讳的就是“画了个大概”每个箭头都必须能回答“什么条件下、谁触发、系统干什么”这三个问题。拿表格对照着检查基本能保证不丢分。5. 三图联动一个系统从需求到建模的完整闭环附易错点5.1 三种图各画各的不行要互相校验考试的最高境界不是把三种图分别画出来而是用它们互相验证。我讲一个很多人忽略的细节借书成功这个动作在DFD里是加工“借书处理”的输出在ER图里是“借阅记录”实体的新增而在状态转换图里是图书状态从“在架”到“已借出”的事件。三张图描述的是同一个系统的三个侧面。所以当DFD里的一个个加工、ER图里的一个个实体/联系、状态图里的一个个状态迁移都对得上号时说明你的需求分析是自洽的对不上说明你漏了某个功能或某个数据。具体怎么联动先画DFD列出所有加工和存储。从DFD的存储文件里提取ER图的实体和属性。从DFD的加工逻辑里提取状态转换的事件和动作。最后用状态图的“每个事件都能在DFD中找到对应加工每个实体都能在DFD/ER中找到对应存储”来检查。我实际做项目时有一个习惯给每个核心对象建一个状态字段比如图书的status、订单的state先画状态图确认状态全集再设计表和接口。状态图没画明白就急着建表后面改表结构改到哭。5.2 常见错误清单按图索骥自查下面这十几条是我批改学生作业和评审同事需求文档时反复遇到的臭毛病。你们画完三张图对照着查一遍DFD常见错误实体直接和实体之间画了数据流。数据存储直接和外部实体相连。加工没有输入或没有输出黑洞/奇迹。数据流没标名字或箭头写着“数据”。只画了一层图就交差没有分层细化到能看清每个加工的逻辑。父子图不平衡0层图某加工的输入输出和1层图对不上。ER图常见错误实体没有主键或主键列不出来。联系类型判断错把多对多漏拆成中间表或把1对多画反。属性挂错了实体比如把“借书日期”挂到图书实体上——它明明是借阅记录这个联系的属性。一个实体里出现了重复含义的属性组比如“书籍1名称”“书籍2名称”说明你缺一个实体。忘了用菱形画联系把联系框画成了矩形。状态图常见错误没有初始状态。事件和动作混为一谈把“动作”写在箭头上却没说触发条件。漏了边界状态比如“逾期”“下架”这种非正常但真实存在的状态。没有考虑一个事件在多个状态下有不同的结果。举例子同样“还书”这个事件在“已借出”状态是正常还书在“逾期”状态就得先缴罚款才能还。只有一个状态到底完全没有状态迁移——那说明你画的不是一个状态图而是一个框。5.3 结合热词MySQL表如何导出ER图热词里有“mysql的表导出er关系图”顺手聊聊这个实操场景。考试是手画工作中是工具一键出但原理一样。最常用的工具是MySQL Workbench操作路径大致是Database → Reverse Engineer → 选择数据库连接 → 选择库 → 它会自动读取所有表的外键关系并生成ER图。遇到“外键没建全”的情况生成的ER图里表之间就没有连线这暴露了实际建表时的关系设计缺陷。所以这个功能很适合用来反向审查历史项目的表结构不只是图个好看。轻量方案是用Mermaid写代码生成ER图。语法很直白比如erDiagram 读者 ||--o{ 借阅记录 : 借阅 图书 ||--o{ 借阅记录 : 被借阅 读者 { string 读者编号 PK string 姓名 string 联系电话 } 图书 { string 图书编号 PK string 书名 } 借阅记录 { string 记录编号 PK string 读者编号 FK string 图书编号 FK date 借书日期 }Mermaid的好处是纯文本可以直接写进Markdown里放代码仓库做文档团队协作时特别方便。不过Mermaid生成的图布局有时候比较随意复杂关系还是用专业工具调整一下更美观。6. 实战串讲一道综合例题从头画到尾图书借阅系统全流程前面都是分点讲可能还有人觉得“道理我懂但实际做题还是下不了手”。这节我带你把同一个例子从头到尾走一遍感受一下拿到卷子之后的完整心态和落笔顺序。6.1 审题阶段2分钟最重要题目原文再看一遍读者查询图书、借书、还书管理员负责图书入库和读者注册借书时要检查读者是否有逾期图书有则拒绝还书时更新记录超期则罚款。审题时我在草稿纸上会迅速列三行外部实体读者、管理员。核心动作查询、借书、还书、入库、注册。核心数据读者信息、图书信息、借阅记录、罚款记录。有了这三行后面画任何一张图都不会跑偏。6.2 先画上下文DFD1分钟一个加工“图书借阅系统”左边连读者右边连管理员数据流标上请求/结果/入库信息/注册信息。完工。6.3 再画0层DFD3分钟五个加工1.1图书查询、1.2读者注册、1.3图书入库、1.4借书处理、1.5还书处理。三个存储D1读者表、D2图书表、D3借阅记录表。关键数据流读者→1.4借书请求1.4→D1读读者信息判断是否有逾期1.4→D2读图书信息判断是否在架1.4→D3写入借阅记录1.4→读者借书结果“拒绝借书”这个情况就体现在1.4返回的结果数据流里不需要单独画一个加工。6.4 画ER图5分钟三个实体读者、图书、借阅记录管理员如果要管理权限再加一个管理员实体也行考试中如果题目明确提到管理员操作建议加上。关系和基数读者 1 : N 借阅记录图书 1 : N 借阅记录属性按之前列的读者编号、图书编号、借阅记录中的记录编号、借书日期、应还日期、实际还书日期。借阅记录的联系属性别忘了“状态”和“罚款金额”。6.5 画状态转换图4分钟选“图书”作为对象。状态在架、已借出、逾期、下架。迁移事件在架 →借书成功→ 已借出已借出 →还书→ 在架已借出 →超过应还日期→ 逾期逾期 →归还缴纳罚款→ 在架已借出/在架 →管理员标记遗失→ 下架再补充说明一下如果考试要求画“借阅记录”的状态图那状态可能是借出中、已归还、逾期未还、已缴款关闭。不同对象的状态图侧重不同看清楚题目问的是谁。6.6 最后互查2分钟画完三张图快速串一遍借书这个动作在DFD里有加工1.4在ER图里有借阅记录实体承载在状态图里有“在架→已借出”的迁移覆盖。三图闭合这套题就稳了。整套流程十分钟内完成平时作业练几次考试基本不会超时。7. 给新手的一些心里话关于技术之外的认知最后说点软的。结构化分析这套东西表面上是为了应付考试、应付课程设计但当年我工作后第一次做新项目需求调研被业务方带着看他们手写的纸质登记表、Excel台账时脑子里自动浮现的居然是大学软工课上的这些图。那一刻才真正明白结构化分析的底层能力是抽象思维。数据流图带你从一团乱麻的业务描述里抽出一条清晰的流动主线ER图逼你把藏在句子里的名词捞出来并理清关系状态图强迫你去想“系统在异常情况下会怎样”。这三件事恰恰是真实开发中最值钱的三项能力——需求沟通能力、数据建模能力、异常情况处理能力。所以别觉得这些图“过时了”也别觉得它们只是“考试用的”。换成更时髦的领域驱动设计DDD里面的核心概念照样是聚合、实体、值对象本质上还是ER图和状态图的亲戚。实操的时候我建议你们在每个项目开始时哪怕是最小的demo也花半小时画一下DFD和ER图。画完之后你会发现写代码时接口该怎么定、表该怎么建、状态字段要加在哪全都清晰了。用十几分钟的前期投入省掉的是后期改接口、改表、返工的好几个小时这笔账怎么算都划算。