☰
数据流图入门:从加工数据流到分层绘制的工程实践
2026/11/3 21:37:57 网站建设 项目流程

简介:这份PPT面向系统分析与设计初学者及需要梳理信息处理流程的师生,围绕数据流图(DFD)的读图与绘图展开,重点解决外部项、加工、数据流、数据存储四类符号的识别,以及自顶向下逐层分解时的表达规范问题。压缩包内仅含1个PPT文件,大小约312KB,以课程讲义式页面组织知识点,便于课堂讲解或自学时按页浏览。内容覆盖DFD基本符号、数据流命名与流向、加工编号规则、数据存储与外部项的表示,并给出关联图、顶层图、二层图与三层图的分解过程示意;绘制步骤部分强调先确定系统界面和输入输出,再划分主要信息处理功能,逐层细化并反复检查。讲义还归纳了明确系统界面、合理布局、数据流必须经过加工等原则与注意事项,并以银行取款处理为例演示从关联图到下层DFD的展开。已有626人学习,适合用来建立数据流图的规范画法,并借助实例理解分层分解与图形检查的思路。

1. 数据流图到底是个什么东西:先把它想成一张“管网图”

装修师傅给你讲方案,说水管从总阀进来,先过滤,再分两路,一路进厨房,一路进卫生间,中间留个三通。你未必看得懂施工图,但这句描述你能听懂,因为脑子里自动浮出一张管网图。数据流图干的是同一件事,只不过管道里跑的不是水,是取款单、订单、账目这些数据;节点不是阀门,是加工和数据存储。它用一张几乎不设技术门槛的图,把“系统到底要处理哪些信息、从哪里来、到哪里去”讲明白,不碰代码,也不碰服务器。也正因为它把技术细节全剥干净了,懂技术的人和不懂技术的人,能坐在同一张桌子前指着同一张纸说话。

2. 为什么非要画这张图:数据流图存在的理由

2.1 系统开发里最贵的一笔开销,是“说不清”

假设某公司要做一套内部报修系统。业务方描述得很轻松:报修、派单、修完、评价,四步。开发听完觉得简单,排了三周工期。上线第一天,业务方一句话让进度归零——备件从仓库领用要扣库存,库存不够得转采购流程。问题不在于业务方故意隐瞒,而在于她脑子里“报修”这件事天生就包含备件领用,她不认为这需要专门说出口。

这类翻车在系统建设里几乎属于日常。代码返工的工作量往往只占两三成,真正吃时间的是反复确认、反复推翻、反复“我以为你说的是那个意思”。需求文档写得再厚,本质还是一串线性排列的句子,而句子天然有歧义;一段话里“系统接收订单并检查”到底是把订单当整体处理,还是拆开逐条核对,光靠文字很难锁死。

数据流图解决的就是这一层。它逼着双方把“有哪些数据、从谁手里来、被谁处理、存到哪里、最后交给谁”一条条画出来。画的过程中,那些原本藏在脑子里、觉得“这还用说吗”的隐含前提会自动暴露。前面那个备件库存,只要画到“派单”这个加工时追问一句“它需要读什么”,仓库台账就会浮出来。

2.2 把技术细节全部剥掉之后,剩下的才是真问题

数据流图最反直觉的一点是:它明确不涉及硬件、软件、数据结构与文件组织,跟系统的物理描述无关。换句话说,画这张图的时候,你不需要知道将来是用关系数据库还是用文件系统,不需要知道前端是网页还是客户端,也不用管并发量多大、部署在哪。

打个比方,装修一上来先讨论的是格局:几间房、厨房放哪、动线怎么走;至于瓷砖选什么牌子、电线用几平方,那是后面的事。格局定错了,瓷砖再贵也得砸墙重铺。数据流图就是系统建设里的“格局图”,它只回答一件事:这个系统在信息处理方面要做什么。

这件事听起来抽象,落到实际场景里非常具体。比如图书预订系统,业务上会描述成“顾客填订单、系统检查、分优先和正常两种处理、最后汇总发出版社”。这句话里没有任何技术词,但它已经包含了三个加工、若干数据存储和两条外部数据流。把它画成图,等于把业务语言直接翻译成逻辑结构,中间不经过任何技术转换,所以业务方看得懂,开发方也不会理解偏。

2.3 为什么偏偏是图,而不是再写一份文档

因为图形描述简明、清晰,而且自带约束。一段文字说“订单经检查后处理”,读者可以自由脑补出十种流程;一张图里如果“检查”这个加工只有一条出来的数据流,那“不合格订单退回”这条路就无处可藏——要么补上这条流,要么承认你没想过。

更关键的是面向用户这一点。数据流图所描述的内容是面向用户的,即使完全不懂信息技术的业务人员也容易理解。这不是说他们能画出标准的图,而是说他们看得懂“这个方框在干什么、这条箭头递的是什么”,并能立刻指出“这里不对,我们实际是先看客户等级再看数量”。这种即时纠错的能力,是任何技术文档都给不了的。

所以数据流图在方法论上的位置很明确:它是系统分析人员与用户之间进行交流的有效手段,同时也是系统设计的主要依据之一。前面承接的是模糊的业务诉求,后面承接的是具体的物理实现,中间这一段,靠图来固定。

3. 数据流图的四个零件:加工、数据流、数据存储、外部项

3.1 加工:图上唯一“干活”的方框

加工又叫处理或变换,表示对数据流的操作。它的符号分成上下两部分:上面是标识部分,写加工编号,编号以 P 开头且必须唯一;下面是功能描述部分,写加工名。

这个“上下分工”的设计有讲究。编号唯一,是为了让不同层级的图能对上号——父图里的 P2 分解之后,子图里的加工就该叫 P2.1、P2.2,一眼能看出谁是谁的孩子。加工名则要求简单、能概括地说明对数据的加工行为,详细描述不写在这里,而是放到数据词典里定义。

初学者最容易在这里写崩。常见的加工名有“处理数据”“进行校验”“执行逻辑判断”,这类名字等于没写,因为它没有说明到底是什么变换。合格的写法是“审核取款单”“按出版社汇总订单”“按客户等级分类”,动词加宾语,读一遍就知道进来什么、出去什么。

加工还有一条硬要求:要逐层分解,直到分解后的加工功能简单、易于理解。什么叫“简单”?一个实用的判断标准是:这个加工能用一句话说清它的处理规则,且不需要再分情况讨论。如果写完还得接一串“如果是 A 就……如果是 B 就……”,那它还该继续往下拆。

3.2 数据流:管道里跑的东西

数据流由一个或一组确定的数据组成,可以是单个数据项,也可以是一个数据结构。名字应当直观地反映它的含义,“取款单”“汇总订单”“明细账”都是好名字。

这里有几条容易被忽略的规则。第一,数据流可以同名,也可以有相同的数据结构,但必须有不同的数据或不同的含义。同一个“订单”在两个加工之间可能指的是待检查的原始订单,在另一处指的是已通过检查的合格订单,名字一样但内容不同,这时要么改名,要么在数据词典里说清楚。

第二,两个符号之间可以有多个数据流同时存在,而数据流图并不表明它们之间的任何关系,诸如次序、主次。这一条经常被误解成“图里画了两条箭头,就说明先走这条再走那条”。不是的。图只表达“这两份数据在这两个东西之间流动”,谁先谁后是流程图的事,数据流图不管。

第三,避免错误的命名方法。通俗地说,就是别用“数据”“信息”“结果”“内容”这类空词,它们不携带任何信息量;也别把动作混进名字里,写成“输入取款单”“发送订单”,那是加工该干的事,数据流只需要说明流的是什么。

3.3 数据存储:开口长方框里的账本

数据存储用来存贮数据。在分层图里,数据存储一般只属于某一层或某几层,所以又叫局部文件——意思是它不必在每一层都出现,只在需要读写它的那几层画出来即可。

它的写法有几条约定:名字写在开口的长方框内,要概要地说明文件中主要存的是什么,写“账目库”比写“数据库1”强得多;数据存储上一定要有数据流,进来或出去至少得有一条,一个孤零零没有任何流连接的数据存储,基本可以判定是画错了或者多余;为便于说明和管理,数据存储也要编号,编号写在符号左端的小方格中,以 D 开头。

还有一条实用技巧:为避免图里出现交叉线,同一个数据存储可以在多处画出,用一个表示重复的符号标注即可。这条看着是排版问题,其实是可读性问题。一张线缠成麻花的图,业务方看两眼就放弃了,前面所有的沟通价值瞬间归零。

3.4 外部项:站在系统门口的甲乙双方

外部项又叫源点和终点,是系统外的实体。它们存在于环境之中,与系统有信息交流:从源点到系统的信息叫系统的输入,从系统到终点的信息叫系统的输出。同一个端点既可以是人,也可以是其他系统,编号以 S 开头。

引入外部项的目的很单纯——便于理解系统,所以不需要详细描述它们。你在图里画一个“储户”,不需要说明他多大年纪、用什么方式填单,只需要说明他递给系统什么、从系统拿回什么。

外部项最重要的作用是划边界。一张数据流图里,凡是被画成外部项的东西,都在系统之外;凡是没画的,默认系统要负责。所以“到底把不把仓库算进系统”这种争论,最后都会落到图上:画成外部项,它就是外部接口;画成加工加数据存储,它就是系统的一部分。这个决定必须在画图早期做掉,否则越往后改代价越大。

零件符号形态编号前缀回答的问题常见写错的地方
加工上下两段的方框P谁对数据做了变换名字写成“处理数据”,或迟迟不分解
数据流带箭头的线F什么数据在谁和谁之间移动用空词命名,或误以为箭头表示先后
数据存储开口长方框D数据在哪里落脚画了却没有任何流连接,或漏编号
外部项方框S系统的边界在哪里描述过细,把系统内部的东西画到外面

4. 自顶向下怎么个“下”法:分层绘制的推演过程

4.1 关联图:先把整个系统当成一个黑匣子

绘制数据流图的第一步,是确定所开发系统的外部项,也就是数据的来源和去处。这一步看似简单,实则决定了后面所有工作的边界。做法是先问:这个系统跟谁打交道?谁会往里送东西,谁会从里拿东西?

第二步,确定整个系统的输出数据流和输入数据流,把系统整体当成一个加工环节,画出关联图。关联图里只有一个加工,就是系统本身,周围一圈是外部项,箭头是进出的数据流。

拿银行取款来说。储户把填好的取款单和存折交给银行,银行处理完把存折、利息单、结算清单和现金交还储户。关联图里就是两个外部项“储户”,中间一个“取款系统”,左边流进取款单和存折,右边流出存折、利率单、结算清单。

这里有个坑值得单独拎出来:现金是实物,不能作为数据流。取款场景里现金确实从系统交到储户手上,但它不是数据,所以不能画成箭头。这一条初学者几乎必踩,因为从业务视角看,现金就是最重要的“输出”。判断标准很简单:这份东西会不会被加工成另一份数据?会,才算数据流;不会,它只是业务动作的附带结果。

4.2 顶层图与二层图:分解的界限在哪

第三步,确定系统的主要信息处理功能,按此把整个系统分解成几个加工环节,同时确定每个加工的输入输出数据流,以及和这些加工有关的数据存储。第四步,按自顶向下、逐层分解的原则,对上层图中全部或部分加工进行分解。第五步,重复上一步,直到分解结束。

这就是分层图的骨架:关联图只有一个加工,顶层图把它拆成 P1、P2、P3,二层图再把其中某个 P 拆成 P2.1、P2.2、P2.3、P2.4,以此类推。分解到什么时候停?停在一个加工已经简单到能用一句话说清、不需要再分情况讨论为止。

分层最容易出的问题是“父子对不上”。父图上 P2 有两条输入、两条输出,拆到子图里,输入少了一条,或者凭空多出一条父图没有约定的输出。前者说明子图漏了来源,后者说明要么父图当初就漏画了,要么子图越界处理了不该它管的事。

def check_balance(parent, child): """检查父图与子图之间的数据流是否平衡 parent / child 均为集合,元素是数据流名(含编号,如 "F1 取款单")。 只比较跨边界的流:从子图外部进入的、从子图内部送出的。 子图内部加工之间的流、以及读写数据存储的局部流,不参与比较。 """ missing_in = parent["in"] - child["in"] # 父图有、子图没接住的输入 missing_out = parent["out"] - child["out"] # 父图有、子图没产出的输出 extra_in = child["in"] - parent["in"] # 子图凭空多出来的输入 extra_out = child["out"] - parent["out"] # 子图凭空多出来的输出 return { "漏接输入": missing_in, "漏产输出": missing_out, "越界输入": extra_in, "越界输出": extra_out, } parent = {"in": {"F1 取款单、存折"}, "out": {"F2 存折、利率单、结算清单"}} child = {"in": {"F1 取款单、存折"}, "out": {"F2 存折、利率单、结算清单", "F3 不合格存折、取款单"}} result = check_balance(parent, child) print(result) # 越界输出里会报出 F3,提示要么父图补上退回流,要么子图多画了

上面这段代码把“平衡”这件事写成了差集运算,逻辑很直白:父图约定的进出,子图必须一条不少地接住和产出;子图多出来的那些,就得回去核对到底是谁错了。参数说明方面,parent["in"]和parent["out"]是父图上进出这个加工的流,child的两个集合只装跨子图边界的流。数据存储在子图里被读写产生的流,属于局部流,父图上本来就不出现,所以不参与比对——这一点搞混了,会得到一堆假报警。

顺带说一句,这段检查逻辑在实际工作中往往靠肉眼完成,图一多就容易漏。能用脚本跑一遍的,别省这一步。

4.3 银行取款:一个可以完整走通的例子

把前面的规则套进一个具体场景。储户将填好的取款单、存折交银行,银行的处理是:审核并查对账目,不合格的存折和取款单退回储户,合格的送取款处理;取款处理修改账目,把存折、利息单、结算清单及现金交储户,同时将取款单存档。

第一步画关联图:两个外部项都是储户,F1 是取款单和存折,F2 是存折、利率单、结算清单,现金不画。

第二步逐层分解。顶层图里,P1 是取款审核,P2 是取款处理。P1 从储户接收 F1,输出 F1.1 合格存折、取款单给 P2,输出 F1.2 不合格存折、取款单退回储户;P1 还要读 D1 账目库来查对。P2 修改 D1,写入 D2 取款记录,向储户输出 F2。

这张图里有几个值得注意的设计选择。D1 账目库被两个加工同时访问——P1 只读,P2 读并写,这正符合“数据存储一般作为两个加工环节的界面来安排”的做法。D2 取款记录则专门承接“取款单存档”这个动作,把业务描述里一句话带过的存档,落成了一个明确的数据存储。

再看加工编号。P1 和 P2 是同一层的兄弟,编号连续且各自唯一。如果 P2 还要往下拆,子图里就该出现 P2.1、P2.2,而不是重新从 P1 开始编。编号的连续性,是分层图可读性的地基。

4.4 图书预订系统:什么时候必须多分一层

再看一个层次更深的例子。书店向顾客发放订单,顾客填好交系统处理;系统首先依据图书目录对订单进行检查,对合格订单进行处理;处理过程中根据顾客情况和订单数目,把订单分为优先订单与正常订单两种,随时处理优先订单,定期处理正常订单;最后根据所处理的订单汇总,按出版社要求发给出版社。

画完顶层图会发现一个问题:P2 订单处理这个加工,无论怎么描述都绕不开“分类”和“两种处理节奏”这两件事,它不是一句话能说清的基本加工。这就是“必须再分一层”的信号。

二层图里,P2 被拆成四个:P2.1 数目统计、P2.2 订单分类、P2.3 随时处理、P2.4 定期处理。数据存储也跟着充实起来:D1 图书目录供订单检查用,D2 合格订单、D3 待发出订单、D4 出版社要求、D5 订单数目、D6 顾客情况、D7 优先订单、D8 正常订单。

这个例子里有一个特别值得琢磨的点:D5 订单数目和 D6 顾客情况,是为分类加工准备的两个依据。业务描述里“根据顾客情况和订单数目”这半句话,如果只停在文字上,很容易被当成一句无关紧要的修饰;一旦画成图,它立刻变成两个必须有来源的数据存储,你就不得不追问:顾客情况从哪来?是系统里存的,还是每次现查?

判断“要不要再分一层”,实用的标准有三条:这个加工是否需要分情况讨论;它的输出是否依赖多个来源的数据;它内部是否明显包含两个以上可以独立命名的动作。三条里中一条,就该往下拆。拆得太浅,图看不懂;拆得太深,图变成代码,业务方又看不懂了。

5. 常见误区与易混概念:这几组最容易搞混

5.1 数据流图与流程图的区别

易混点:两者都带箭头、都有方框,画在白板上远看几乎一样。很多人第一次接触时,会下意识把数据流图当成流程图的简化版。

为什么混:名字里都有“流”,工具里也常常挨着放。更麻烦的是,业务流程里确实既有数据的移动,也有步骤的推进,两件事在现实里同时发生,脑子一糊涂就画到一起去了。

怎么区分:看箭头表达什么。流程图里的箭头是时间顺序,有开始、有结束、有判断分支,读法是“先做这个,再做那个,如果条件成立走这边”。数据流图里的箭头只是数据的移动方向,图里没有开始和结束,也没有判断菱形,两个加工之间画三条箭头,不代表有先后,只代表有三份数据在流动。一个验证方法:把数据流图上所有箭头的方向反过来读,如果读起来像“流程倒放”,那说明你画成流程图了;真正合格的数据流图反过来读只是不通,不是倒放。

5.2 数据流与控制流的区别

易混点:都是从一个方框指向另一个方框的箭头,上面都写着字。业务讨论里“发个通知”“传个指令”“触发一下”这类说法,让人分不清该不该画成箭头。

为什么混:很多动作在口语里是混着说的。比如“审核通过后通知取款处理”,这句话里,“合格取款单”是数据,“通知”听起来像信号,实际干活时两者常常一起发生。

怎么区分:问一句“这份东西本身会被加工吗”。会被读取、判断、改写、存档的,是数据流,比如合格存折与取款单、汇总订单;只是一个触发动作、不携带被处理内容的,是控制流,数据流图里不画。上面那句“审核通过后通知取款处理”,落到图上应该是 P1 输出一条“合格存折、取款单”给 P2,前面那半句“通知”被吸收进这条数据流里了,不需要单独画。初学者常见的错误是在这条线上再补一条“处理指令”,结果图里凭空多出一个谁也不知道内容是什么的箭头。

5.3 数据存储与数据库表的区别

易混点:都叫“存数据的地方”,画图时很容易直接把数据库表名抄进数据存储里,一个 D 对应一张表,觉得这样最省事。

为什么混:项目落地之后,数据存储确实大多落在表上,回头看图对表,一一对应看起来很自然。加上很多画图工具的图标本身就长得像数据库。

怎么区分:数据流图里的数据存储是逻辑概念,不涉及数据结构与文件组织。一个数据存储可能对应好几张表,也可能只是一个文件、一本台账、一张纸质登记簿;反过来,一张表也可能被拆到两个数据存储里,因为它们在逻辑上服务不同的加工。判断时看用途而不是看形态:如果某个存储的存在理由是“某个加工需要读它”,那它就是一个逻辑存储,名字该按业务含义起,比如“账目库”“出版社要求”,而不是按物理形态起。

5.4 加工分解与功能模块划分的区别

易混点:两者都在把一个大东西切成小块,画出来都是层层展开的树状结构,看起来只是叫法不同。

为什么混:系统设计阶段确实两种切法都会用到,而且切完之后大小差不多,团队讨论时经常混着说“这个模块”和“这个加工”。

怎么区分:加工分解的判据是数据变换对不对得上,一个加工必须能说清“吃进什么、吐出什么”,父子之间的数据流要守恒;模块划分的判据是职责归拢,讲的是高内聚低耦合、谁调用谁。一个加工在实现时可能由好几个模块协作完成,一个模块也可能同时承担两个加工的部分工作。落到图上有个简单区别:数据流图的分解结果必须经得起前面那段平衡检查,模块图不检查这个,它检查的是接口和依赖。

5.5 关联图与顶层图的区别

易混点:两张图看起来都是“一个中心加一圈外部项”,很容易被当成同一张图的两个叫法。

为什么混:关联图确实只有系统一个加工,顶层图第一眼也常常只有一个大框,差别不明显;而且不少资料在讲的时候把这两步合并成一步带过。

怎么区分:关联图里整个系统就是一个加工,没有编号,没有数据存储,只有外部项和进出的数据流,它的任务是划边界。顶层图是分解动作的第一步,系统的加工已经被拆成 P1、P2、P3 若干个子加工,加工之间开始出现数据流,数据存储也开始登场,它的任务是给出系统内部的第一层结构。一句话记:关联图回答“系统跟外界交换什么”,顶层图回答“系统内部先分成几块”。

6. 什么时候该画、什么时候别画:几条判断边界

6.1 值得动手的场面

第一种是需求确认之前。业务方能说清流程,但说不清数据从哪来到哪去,这时候画一张关联图加一张顶层图,比开三次会都管用。第二种是系统边界模糊的时候,尤其是“这块归不归我们管”争论不休的项目,把候选边界画成外部项或加工,争论立刻变成选择题。第三种是交接和留档,人员变动时,一张标好编号的分层图能让接手的人半天摸清结构,比读几十页文档快得多。

6.2 别硬画的场面

接口契约已经写得极清楚的项目,不必再补一张图来复述;纯算法或数据处理的内部逻辑,数据流图帮不上忙,它管的是逻辑功能层面,再往下就该换工具了;还有一种最常见——团队里没人会读这张图,画出来只为交作业,那它的沟通价值是零,不如把时间花在写清楚数据词典上。

6.3 画完先过一遍这几条

检查项合格标准常见不合格
数据流路径每条流必须经过加工外部项直接连数据存储,绕过加工
数据存储位置一般作为两个加工之间的界面一个存储只被一个加工读写,且无必要
编号体系P / F / D / S 各自独立,父子对应子图重新从 P1 编号,父子对不上
系统界面外部项与加工界限分明同一实体一会儿画成外部项一会儿画成加工
布局无交叉线,同层加工排布均衡线缠成一团,业务方放弃阅读

最后一条最容易被跳过:和用户交流,在对方完全理解图的内容之后再征求意见。图是给人看的,看不懂就是没画完。

我第一次独立画分层图时,自信满满交了顶层图,被一句“这个数据存储谁写它”问住——我画了个只有读、没有写的账目库。从那以后我每次收尾都强制走一遍:每条流从哪来到哪去、每个存储谁写谁读、父子编号对不对得上。希望帮到你。

本文还有配套的精品资源,点击获取

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

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

立即咨询