☰
数据流图从入门到平衡:结构化分析与图书借阅实验指南
2026/10/2 3:05:57 网站建设 项目流程

软件工程导论这门课,不少人是在 educoder(头歌)平台上第一次正式接触结构化分析方法,而数据流图基本就是卡住大多数人的第一道坎。我自己带过几届学弟学妹做这个实验,也帮人改过几十份提交上去的图,慢慢摸出一个规律:真正难的地方从来不是"怎么在画图软件里把箭头拉出来",而是"拿到一段几百字的需求描述,怎么判断哪些是外部实体、哪些是加工、哪些数据该往哪流"。平台上的实验通常只给一段业务描述和几个空图框,判定规则全部靠你自己,判题又相对严格,命名含糊、层级不平衡、加工只有输入没有输出,都可能直接被判错。

这篇内容想做的事情很具体:把数据流图这套东西,从"为什么要画"到"每一层怎么落笔"再到"提交前怎么自查"完整走一遍。我会用图书借阅管理这个典型场景贯穿全文,因为它实体少、数据流清晰,适合当作入门模板;套路掌握了,换成选课系统、订单系统、挂号系统,骨架是一模一样的。不管你是第一次做这个实验,还是图能画出来但总在平衡性上翻车,下面的思路都可以直接照着走。

1. 数据流图在结构化分析方法里的位置

1.1 结构化分析方法到底在分析什么

结构化分析方法(Structured Analysis,SA)的核心思想只有一句话:把一个复杂的系统,按照"自顶向下、逐层分解"的方式拆到人能看懂为止。它面向的是数据,而不是控制流程,所以产出的主力模型是数据流图,配套的还有数据字典和加工说明。这三样东西是绑在一起的:图负责告诉你"数据从哪来、经过谁、到哪去",字典负责告诉你"每一条数据流里面到底装了什么",加工说明负责告诉你"这个圆圈内部的计算或判定逻辑是什么"。

很多人做实验时只画图,字典随便糊两句,加工说明干脆不写,结果就是图本身看着像模像样,但一到检查环节就被问倒。因为一张只有箭头和圆圈的图,信息量其实是不够的——"借书信息"这四个字可以指书名、可以指借书证号加日期,不同人理解完全不同。结构化分析方法之所以要求在图的旁边补齐字典和说明,就是为了消除这种歧义。

还有一个容易混淆的点:结构化分析方法属于需求分析阶段的方法,它的产物是给人和后续设计看的逻辑模型,不是程序流程图。数据流图里没有循环、没有判断框、没有先后顺序,这点后面还会反复提到,因为初学的人最喜欢往里面加"先判断再执行"这种时序信息,一加就错。

1.2 数据流图在整个课程链条里的前后关系

把这门课从头到尾串一遍,你会看到一条很清晰的链路:需求分析阶段用结构化分析方法产出数据流图和数据字典,接着做数据流图向软件结构图的映射(变换分析、事务分析),得到模块结构图,再往下才是详细设计、编码、测试。也就是说,数据流图不是孤立的练习题,它是后面结构设计的输入。你在这一关卡画得越清楚,后面做结构图映射的时候就越省事;反过来,这里含糊过去,后面模块划分就只能靠猜。

提示:做这一关实验时,别只盯着"这次能不能过",顺手想一下如果要把这张图映射成模块结构图,哪些加工会变成模块、哪些数据流会变成模块间的参数传递,后面的实验会轻松很多。

阶段主要模型关注点
需求分析数据流图、数据字典、加工说明数据怎么流动、系统做什么
概要设计模块结构图系统拆成哪些模块、怎么调用
详细设计流程图、PDL、判定表每个模块内部怎么做
编码测试源码、测试用例实现与验证

这张表的意义在于划清边界。数据流图属于第一列,只描述"做什么",不描述"怎么做",也不描述"做的顺序"。一旦你在图里写出"如果书没被借走则登记"这样的分支语义,你已经在越界写详细设计了,判卷的人一眼就能看出来问题。

1.3 为什么课程实验偏爱用图书借阅这类场景

原因有两个。第一,它的外部实体天然清晰:读者、管理员,最多再加一个"图书供应商"或者"财务系统",不需要复杂的角色权限推导。第二,它的数据流数量可控:借书、还书、查询、管理图书,四条主线就能覆盖,既够画分层图,又不至于让新手一开始就淹没在二十条箭头里。

但要注意,这只是入门场景的便利,不代表数据流图只能画这种小系统。真实项目里几百个加工的图也存在,只是必须严格分层,一层一层摊开,否则没人看得懂。课程实验因为篇幅限制,通常只要求做到一到两层分解,这也是为什么"平衡性"和"命名"的权重会被放得特别高——图小,每一笔都在评分范围内。

2. 四类图元和命名规则,先把砖头备齐

2.1 外部实体、加工、数据存储、数据流

数据流图一共就四种元素,任何一张图都逃不出这四类。外部实体是系统边界之外、与系统有数据交换的人、组织或外部系统,它只能发出数据或者接收数据,不能同时既被拆解又被展开;加工是系统内部对数据做的变换,比如"校验借书证"、"登记借阅记录";数据存储是系统内部静止的数据,比如"读者信息表"、"图书目录";数据流是这四者之间的数据搬运,用带箭头的线表示方向。

判断一个东西属于哪一类,最快的办法是问自己:它有没有"内部结构"?外部实体和存储都不在本系统的加工范围内,所以画的时候只写名字,不展开;加工是本系统要实现的逻辑,所以需要编号、需要分层展开。这个判断标准比死记定义好用得多。

图元是否可分解常见错误写法正确写法
外部实体否读者表读者
加工是读者管理2.1 登记借阅记录
数据存储否加工图书数据图书目录表
数据流否数据、信息借书请求单

2.2 加工命名:动词加名词,拒绝"处理数据"这类空话

加工名称是整个图里最容易被扣分的地方。规则其实很朴素:加工名应该是"动词 + 名词"的短语,能让人一眼看出它对数据做了什么变换。"处理数据"、"进行管理"、"系统操作"这类词的问题在于,它们没有传递任何信息——读者看到这个名字,完全不知道这个圆圈内部做了什么,也就无法判断它的输入输出是否合理。

对照一下:"处理借阅信息"不合格,"登记借阅记录"合格;"管理图书"不合格,"更新图书库存"合格。差别在于后者限定了动作的对象和结果。当图上有五六个加工时,命名规范与否直接决定这张图是"能读"还是"读不下去"。

还有一个小细节:同一个加工在不同层级的名称要保持一致。父图里的"2 处理借还书"分解到子图后,子图里的加工应该编号 2.1、2.2、2.3,而父图那个加工的输入输出流必须与子图的边界流完全对应,这就是后面要讲的平衡原则。

2.3 数据流命名:用名词,别用"信息""数据"

数据流是一根箭头,箭头本身不会说话,全靠名字交代它搬运的内容。所以数据流的名字必须是名词或名词短语,而且要有区分度。"借书请求单"、"逾期通知"、"可借图书列表"都是合格的名字;"信息"、"数据"、"结果"这类词如果出现在图上,基本等于没写。

有个实用的自检方法:把数据流的名字念出来,问一句"这个东西能不能被装进一个信封寄出去?"能,就说明它是一个完整、明确的数据集合;不能,说明名字太抽象,需要再具体化。另外,同一个数据流在父子图之间出现时,名字要完全一致,不能父图叫"借书请求单"、子图叫"借阅申请",这种不一致会被当作平衡性错误。

注意:数据流的名字要避免和加工名"撞车"。比如加工叫"登记借阅记录",那它输入的数据流就不该也叫"登记借阅记录",应该改成"借书请求单"或者"待登记借阅信息",否则读者分不清哪个是动作、哪个是搬运内容。

3. 从一段业务描述推导出上下文图

3.1 上下文图的作用:先把系统框成一个黑盒

上下文图也叫顶层数据流图,它只包含一个加工节点——整个系统本身,编号通常写作 0,再加上所有与系统交互的外部实体以及它们之间的数据流。它的价值在于划边界:哪些事归系统管,哪些事系统不碰,在上下文图上就定死了。

新手常犯的错误是把外部实体的数据流画得太细。上下文图上写"读者提交借书请求单"就够了,不需要写"读者提交含借书证号、ISBN、日期的借书请求单"——那是数据字典的活。上下文图追求的是"一眼看全",细节要留给下一层。

3.2 怎么定外部实体:从"谁受益、谁提供数据"两边找

面对一段需求描述,我通常用两个问题去筛外部实体。第一个问题:谁从这个系统得到结果或者服务?第二个问题:谁给系统提供原始数据?从这两端出发,把名词捞出来,再逐一判断它是不是位于系统边界之外。

以图书借阅管理为例,描述里出现"读者可以查询图书并借阅,管理员负责图书入库和读者账户维护,系统每月向财务部门提交超期罚款汇总"。捞出来的候选项有:读者、管理员、财务部门、图书、借阅记录、账户。后三个属于系统内部要维护的数据,不是外部实体,所以最终外部实体是读者、管理员、财务部门三个。

判断的关键在于:外部实体在图上不会因为它"有很多属性"就需要展开。读者这个实体,不管需求描述里写了他有多少字段,在图中就是一个方框,写着"读者"两个字。字段信息属于数据字典。

3.3 输入流与输出流:给每个实体列一张进出清单

确定实体之后,逐个列清单。我习惯用表格来做这一步,把每个实体"发出什么"和"接收什么"都写清楚,这样不容易漏。

外部实体向系统发出从系统接收
读者借书请求、还书请求、查询条件借阅结果、查询结果、逾期通知
管理员图书入库信息、账户维护指令操作确认、库存清单
财务部门无超期罚款汇总表

列完这张表,上下文图基本就画完了:中间一个圆,写"图书借阅管理系统",三个方框分布在外,箭头按表格对应画过去。这里要特别注意方向——"财务部门"只有接收、没有发出,那就只画一根出来的箭头,不要为了对称硬凑一根进去。

3.4 手绘草稿比直接上软件快

我自己的习惯是先在纸上或者白板上把实体和箭头摆一遍,确认没有漏项、没有重复,再打开绘图工具正式画。原因是软件里拖动一个框、调整一根箭头的位置,成本比纸上画一笔高得多;等你改到第五遍,耐心早就没了。草稿阶段只求逻辑正确,不求好看,等到逻辑冻结了再考虑排版。

4. 自顶向下分解:0层图与1层图的画法

4.1 什么时候该继续分解

分解的本质是把一个加工替换成一组更小的加工加上它们之间的数据流。判断标准有两条:第一,如果这个加工内部还包含多个明显不同的业务动作,就该拆;第二,如果这个加工的输入输出无法用一两句话说清它做了什么变换,也该拆。

拆到什么程度算够?经验法则是:拆到每个加工都对应一个可以独立实现的功能模块,而且它的逻辑可以用一页说明写清楚。课程实验里通常拆到 0 层图(系统分解为若干主要加工)或者再往下一层就够了,不需要拆成原子操作。

以图书借阅管理为例,0 层图可以拆成四个加工:1 管理图书信息、2 办理借阅、3 办理归还、4 处理逾期与罚款。这四个各自职责清晰,相互之间的数据流也不复杂,作为一级分解非常合适。

4.2 平衡性:父图子图之间的数据守恒

平衡原则是数据流图里最硬的规则,也是最容易出错的地方。它的表述是:父图中某个加工的输入数据流和输出数据流,必须与它的子图边界上的输入输出流完全一致,数量一致、名称一致、方向一致。

举一个反面例子。父图里"2 办理借阅"接收"借书请求单"、输出"借阅结果",那么子图展开后,这个子图的边界上也必须只有这两条流。如果子图里多出一条"库存更新确认"流出去,或者少了一条"借书请求单"流进来,就打破了平衡。新手最常见的做法是把子图内部的细节流当作边界流画出去,一眼就能被看出来。

4.3 数据字典:给每根箭头填上内容

数据字典是把图上元素定义清楚的工具,常用的符号不多,但必须写对。来看一段示例,用的是图书借阅场景:

借书请求单 = 借书证号 + ISBN + 请求日期 借阅结果 = [借阅成功单 | 借阅失败通知] 借阅成功单 = 借书证号 + ISBN + 应还日期 借阅失败通知 = 借书证号 + 失败原因 读者信息 = 借书证号 + 姓名 + {联系方式} + 账户状态

符号含义是:=表示定义,+表示顺序连接,[ ]表示从中选择其一,{ }表示重复出现,( )表示可选。这里{联系方式}表示一个读者可能有多个联系方式。写字典的时候要克制,只定义图上真正出现过的数据流和数据存储,不要顺手把整个数据库的字段都列一遍,那属于数据库设计的活。

提示:平台实验里如果要求同时提交数据字典,务必保证字典里出现的每一个数据流名字,都能在图上找到对应的箭头;反过来,图上每一根箭头也都要在字典里有定义。两边对齐是最容易拿分、也最容易被忽略的一环。

4.4 加工的输入输出不能缺

除了平衡性,还有一条硬规则:任何一个加工,都必须至少有一条输入数据流和至少一条输出数据流。只有输入没有输出的加工被称为"黑洞",数据流进去就消失了;只有输出没有输入的加工被称为"奇迹",数据凭空产生。这两种情况在评审中都是硬伤。

有人会问,那"生成报表"这种加工岂不是只有输出?不是,它必然有输入——它读的是某个数据存储或者某条上游数据流。正确的画法是:从数据存储拉一根流出来指向这个加工,加工再输出报表给外部实体。数据存储到加工、加工到数据存储的流都算数。

5. 常见错误与排查技巧实录

5.1 语义类错误速查表

我整理过一份在批改作业时出现频率最高的错误清单,基本覆盖了八成的扣分点。

错误现象本质原因修正方法
外部实体直接连数据存储漏掉了中间的加工插入一个加工承担读写逻辑
两个数据存储之间有箭头数据不会自己搬家通过加工中转
加工只有输入没有输出黑洞补上输出流或合并到上游加工
加工只有输出没有输入奇迹补上数据来源
父子图数据流数量不一致破坏平衡按父图边界重画子图边界
图上出现判断分支混入了控制流把逻辑移到加工说明里
数据流名字与加工名相同命名混淆数据流改成名词短语

这张表里最值得展开说的是"外部实体直接连数据存储"。很多人觉得,读者查书嘛,直接从读者拉一根线到图书目录表不就行了。问题在于,这样画的话,系统本身就没做事了——查询条件的校验、可借状态的筛选,这些逻辑都没地方放。正确画法是读者把查询条件送给"查询图书"这个加工,加工去读图书目录表,再把结果返回给读者。

5.2 命名与格式类错误

格式类错误不像语义错误那么致命,但容易被判题系统直接拦下。常见的有:加工编号不连续、跳号,比如父图里编到"4 处理逾期",子图却从 4.2 开始;层级编号混用,把 1.1 直接写成 11 或者 1-1;同一个加工在父图和子图里名字不同;外部实体用了圆角矩形,和加工的表示撞了形状。

我的建议是:编完号之后,把每个编号抄在纸上,横着看一遍是否连续,竖着看一遍父子对应是否正确。这个动作三十秒就能做完,但能挡掉相当一部分冤枉分。

5.3 提交前的自检清单

每次提交前,我都会按固定顺序走一遍检查,这个顺序是从粗到细的。

  1. 先看边界:外部实体是不是都列全了,有没有把系统内部的数据表误当成外部实体。
  2. 再看平衡:每一对父子图的边界流,数量、名字、方向是否严格一致。
  3. 然后看每个加工:是否都有输入和输出,名字是否为动词加名词。
  4. 接着看数据流:名字是否为明确的名词短语,有没有"数据""信息"这类空词。
  5. 最后看编号与格式:层级编号是否连续、形状是否符合规范。
  6. 如果要求数据字典:图的每根箭头是否都有定义,字典的每个条目是否都在图上出现。

注意:自检顺序不要反过来。先抠命名再看平衡,很容易出现"名字改得漂亮,但父子图结构本身就是错的"这种情况,等于白改。先保证结构对,再优化表述。

6. 几个能真正省时间的实操心得

6.1 画图工具的取舍

课程实验里用哪款工具其实不重要,重要的是三点:能方便地调整线的走向、能方便地复制一个加工再改编号、导出图片够清晰。我个人的经验是,如果只要求提交图片,用任意矢量绘图工具都行;如果平台要求在网页上直接连线和拖拽,那就要提前熟悉它的连线方式,尤其是弯折线的画法,很多判定会看箭头起点和终点是否精确落在图形边缘。

还有一个细节值得提醒:网上流传的"数据流图模板"大多存在语义简化,直接抄很可能把外部实体和数据存储的箭头关系抄错。模板可以用来参考排版,逻辑必须自己重推一遍。

6.2 从数据流图往下走:映射到模块结构图

如果在做课程设计而不仅仅是一次实验,数据流图迟早要往模块结构图映射。这里有个很实用的技巧:判断一张图是"变换型"还是"事务型"。如果数据流大致是从输入一路加工到输出,那是变换型,可以按输入分支、变换中心、输出分支三段去划分顶层模块;如果图上有明显的"根据某条数据选择走不同分支"的结构,那是事务型,对应一个调度模块加若干事务模块。

判断方法很直接:看图上有没有一个数据流被送到多个不同加工、且这些加工之间互不往来。如果有,基本就是事务型。图书借阅管理里,"借书请求"和"还书请求"分别走向不同加工,这两个加工之间没有数据交换,所以它更偏事务型。把这个判断提前做掉,后面画结构图的时候就不会卡在顶层模块怎么切。

6.3 我在这个实验上踩过的坑

最后一个坑值得单独说:不要为了图好看而把数据流合并。有人觉得从数据存储到加工有三根箭头太乱,干脆合并成一根"图书相关数据"。这样做短期看着清爽,长期是灾难——数据字典没法写,加工说明没法写,映射到模块结构图时参数传递也没法定义。宁可多画几根箭头,也不要发明一个含糊的复合数据流。

另外一个坑是过度分层。有些同学觉得层数越多越显得认真,把两三个加工的系统拆到第四层,结果每一层都只有一条进出流,图反而更难看懂。分解的目的是让人理解,不是展示层数。当一层里只剩一两个加工、且它们之间没有复杂交互时,就该停下来。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询