数据流图怎么画:DFD分层分解、工具实操与常见错误排查
1. 数据流图到底在画什么——先把本质吃透再动手数据流图这个词很多人第一次接触是在软件工程课或者系统分析课上老师讲了一堆圆圈、方框、箭头当时听懂了回头自己动手画一个图书管理系统或者订单系统的数据流图立刻卡壳。问题出在哪儿不是符号记不住而是没搞清楚数据流图到底在描述什么东西。数据流图英文是Data Flow Diagram简称DFD它描述的是一个系统内部数据怎么流动、怎么被加工、最终流向哪里。注意它描述的是“数据”的流动不是“控制”的流动也不是“步骤”的先后顺序。这是最容易被混淆的地方。很多人画着画着就把if-else、循环、判断条件画进去了结果画出来的东西既不像数据流图也不像流程图成了四不像。我自己的经验是理解数据流图要抓住三个关键词数据、加工、流动。数据从外部进来经过一系列加工处理最后输出到外部或者存储起来。整个过程关注的焦点是“数据变成了什么”而不是“程序怎么执行”。打个比方数据流图就像快递分拣中心的监控录像——你看到包裹从卡车上卸下来经过扫码、分拣、装车最后送到另一个城市你不需要知道分拣员什么时候喝水、什么时候休息你只关心包裹去了哪儿、变成了什么状态。那数据流图到底能干什么用最核心的用途有两个一是需求分析阶段和用户沟通用户不懂类图、不懂时序图但你画一张数据流图告诉他“您的订单数据从这儿进来经过库存检查、价格计算最后存入订单库同时通知发货”他立刻就能明白系统要做什么二是系统设计阶段梳理数据加工逻辑帮助开发者理清每个加工步骤的输入输出避免遗漏或者重复处理。适合谁来学我觉着三类人最需要第一类是软件工程、计算机相关专业的学生课程设计、毕业设计里数据流图几乎是必考内容第二类是刚入行的系统分析师、产品经理需要和业务方对齐需求第三类是工作几年后回头补基础的老手发现自己画图全凭感觉想系统梳理一遍。不管你属于哪一类接下来的内容我都会从最基础的符号讲到分层分解的完整流程再落到工具操作和常见坑的排查力求让你看完就能上手画出一张像样的数据流图。1.1 四种基本符号记住含义比记住形状重要数据流图的符号体系有好几套最常见的是Yourdon-DeMarco和Gane-Sarson两种。学校教材里用得比较多的是Yourdon-DeMarco工具里Visio默认模板两种都有。但符号形状其实不是重点重点是每个符号背后的含义。我把四种基本元素整理成表格你对照着理解。元素名称常见符号形状核心含义常见错误外部实体矩形或带阴影矩形系统之外的参与者如用户、其他系统把系统内部的模块当成外部实体加工圆圈或圆角矩形对数据进行的处理动作把加工写成“判断是否合法”这种带条件的描述数据存储开口矩形或双横线数据的静态存放位置把临时变量、队列也画成数据存储数据流带箭头线段数据在元素之间的流动方向箭头没有名字或者名字写成“数据”这种废话外部实体是数据的源头或者终点它不在系统边界之内。比如一个电商系统顾客、支付平台、物流系统都是外部实体而“订单管理模块”是系统内部的不能画成外部实体。加工是对数据做变换的动作命名要用“动词名词”的形式比如“校验订单”“计算总价”“生成发货单”而不是“订单校验模块”这种名词性描述。数据存储是数据停下来待着的地方通常是数据库表、文件、缓存命名用名词比如“订单表”“用户信息库”。数据流是数据在动的过程中必须有名有方向名字要具体比如“订单详情”“支付结果”不能只写“数据”。记住一个原则数据流图里没有“控制流”也没有“时序”。如果你发现自己在箭头上标注“如果库存不足则……”那说明你画错了应该把这个逻辑放到加工的内部说明里去。1.2 为什么数据流图容易画成流程图这个问题我被问过太多次了。根本原因在于很多人习惯用“步骤思维”去描述系统而数据流图要求的是“数据思维”。举个例子用户登录这个功能步骤思维是用户输入用户名密码→系统查询数据库→比对密码→返回登录成功或失败。如果你按这个顺序画成图看起来就像流程图。但数据流图应该这样描述外部实体“用户”产生数据流“登录凭证”流向加工“验证登录”这个加工从数据存储“用户表”读取“用户记录”然后输出数据流“登录结果”给外部实体“用户”。你看没有先后顺序只有数据从哪来到哪去。我自己的做法是画图之前先列一张数据清单这个系统里有哪些数据每个数据从哪来经过哪些加工最后到哪去列完这张清单再往图上摆符号就不会跑偏。这个习惯帮我省了很多返工的时间尤其是画大型系统的数据流图时清单比图本身还重要。2. 分层分解——别想一口气画完整个系统刚学数据流图的人最容易犯的毛病就是试图在一张图上把整个系统的所有加工和数据流都画出来。结果就是图大得像蜘蛛网谁看谁晕。正确的做法是分层画从最顶层开始一层一层往下分解。这个思路叫“自顶向下逐层分解”是结构化分析方法的核心。2.1 顶层图上下文图——一句话说清系统边界顶层图也叫上下文数据流图整张图只有一个加工就是代表整个系统的那一个圆圈周围是所有的外部实体箭头表示系统和外部实体之间的数据交换。这张图的作用是划定系统边界哪些是系统要处理的哪些是系统之外的。画顶层图的步骤很简单第一步确定系统名称写在中间那个圆圈里第二步找出所有和系统有数据交互的外部实体画在两边第三步画出它们之间的数据流并给每条流起名。关键在于外部实体不要找太多通常三到七个就够了。有人把每个用户角色都当成一个外部实体管理员、普通用户、游客全画上其实如果他们对系统的数据交互方式一样可以合并成一个“用户”。顶层图里绝对不能出现数据存储。因为顶层图描述的是系统和外界的交互数据存储是系统内部的东西放到顶层图里就破坏了“黑盒”视角。2.2 0层图——把系统拆成主要加工顶层图只有一个加工太笼统下一步就是把这个加工拆开变成若干个主要加工这就是0层图。0层图里可以出现数据存储了因为我们现在是在看系统内部。拆分的依据是什么呢通常是按业务功能拆比如一个电商系统可以拆成“订单处理”“库存管理”“支付处理”“用户管理”几个加工。拆的时候要注意两点第一加工之间的数据流要闭合。也就是说父图顶层图里系统跟外部实体之间的那些数据流在子图0层图里必须还能对得上。第二加工的数量控制在三到七个太少了没必要拆太多了说明你拆的粒度不对应该继续往下分层。我见过很多人0层图画得特别随意加工之间只有输出没有输入或者某个加工凭空产生数据。这不行。每个加工必须有输入数据流也必须有输出数据流。如果某个加工只有输出没有输入那它要么是数据源要么就是画错了。2.3 继续分解到1层、2层——什么时候停下来0层图之后如果某个加工内部逻辑还比较复杂可以继续分解成1层图甚至2层图。但并不是越细越好分解到什么时候停我的经验标准是当每个加工都能用一段简短的文字说明或者一个判断表、判断树把逻辑讲清楚的时候就可以停了。再往下分解就变成程序设计级别的内容了不属于数据流图的范畴。另外还有一个平衡原则父图里某个加工的输入输出数据流在它的子图里必须完全对应。不能父图里输入是“订单信息”子图里变成了“订单编号”和“订单明细”两个流除非你在子图里通过某个加工把它们重新组合了。这个平衡检查是数据流图审核里最容易出问题的地方我在实际项目中见过太多父子图不平衡的情况最后排查起来非常痛苦。2.4 分层编号的规范做法分层之后加工需要编号否则说不清哪个加工在哪一层。顶层图的加工通常编号为00层图的加工编号为1、2、3……如果加工1继续分解下一层的加工编号就是1.1、1.2、1.3……依此类推。这种编号方式既清晰又能体现层次关系。数据流也有编号不过数据流的编号不是必须的很多教材里不强调。但如果项目比较大建议给数据流也编号方便在数据字典里管理。数据字典是数据流图的配套文档用来定义每个数据流、每个数据存储、每个加工的详细说明。很多人画完图就完事了不写数据字典结果图上的名字别人看不懂或者同一份数据在不同地方叫不同名字这种问题在实际协作中非常常见。3. 手把手操作——从零画一张订单处理数据流图光讲理论不够我们拿一个具体场景从头到尾走一遍。场景是一个简化的订单处理系统顾客下单系统检查库存、计算价格、生成订单然后通知仓库发货。我们按分层分解的流程一步一步画出来。3.1 第一步画顶层图确定边界先确定系统名称订单处理系统。然后找外部实体顾客、仓库系统、支付平台。顾客向系统提交订单信息系统向顾客返回订单确认系统向支付平台发送支付请求支付平台返回支付结果系统向仓库系统发送发货通知仓库系统返回发货状态。顶层图里只有一个加工“订单处理系统”三条数据流进三条数据流出。这里要注意支付平台和仓库系统虽然是外部系统但它们确实是外部实体因为它们不在我们系统的边界之内。很多初学者觉得“支付平台也是系统的一部分”但在这个场景里我们只是调用支付平台的接口它本身不归我们开发维护所以是外部实体。画完之后检查一下每条数据流都有名字吗外部实体有没有多画系统边界清晰吗没问题就进入下一步。3.2 第二步分解0层图拆出主要加工把“订单处理系统”拆成四个加工1. 接收订单、2. 检查库存、3. 计算价格、4. 生成发货单。数据存储有三个订单表、库存表、商品价格表。数据流是这样的顾客提交订单信息流向加工1“接收订单”加工1把订单数据写入订单表同时输出订单明细给加工2“检查库存”加工2从库存表读取库存数据输出“库存可用”信息给加工3“计算价格”加工3从商品价格表读取价格输出“订单总价”给加工4“生成发货单”加工4写入订单表更新订单状态同时输出发货通知给仓库系统。这里有一个细节加工1和加工4都跟订单表有交互一个写一个更新这是合理的。数据存储可以被多个加工读写只要逻辑上说得通就行。3.3 第三步继续分解加工2“检查库存”假设“检查库存”内部逻辑比较复杂需要校验库存数量、检查库存锁定状态、判断是否需要补货。那我们把它分解成1层图加工编号为2.1、2.2、2.3。2.1“校验库存数量”输入订单明细从库存表读取当前库存输出“数量校验结果”。2.2“检查锁定状态”输入订单明细从库存表读取锁定信息输出“锁定校验结果”。2.3“生成库存结论”输入前面两个结果输出“库存可用”或“库存不足”给父图的加工3。注意这里的平衡父图加工2的输入是“订单明细”输出是“库存可用”或“库存不足”。子图里2.1和2.2的输入都是“订单明细”2.3的输出就是父图的输出。数据流完全对应平衡检查通过。3.4 参数与命名规范——让图能被人看懂画数据流图不是画画命名规范直接影响图的可用性。我总结了几条实操中特别有用的规则。加工命名用“动词宾语”结构不要用“名词模块”。比如“校验库存”比“库存校验模块”好“计算总价”比“价格计算”好。如果加工是“接收订单”那它的输入数据流应该叫“订单信息”或者“订单请求”输出数据流叫“订单明细”或者“已接收订单”这样读起来就是一句完整的话“接收订单”把“订单信息”变成“订单明细”。数据存储命名用名词而且要跟数据库表名或者文件命名保持一致。比如“订单表”“用户信息库”“商品价格表”。不要在图上写“订单数据存储”这种模糊的名字。数据流命名最忌讳的是“数据”“信息”“结果”这种万能词。一条数据流叫“数据”谁知道你传的是什么应该叫“订单编号”“支付金额”“库存数量”这种具体的名字。如果两条数据流内容一样可以起一样的名字但最好加个方向说明比如“订单详情查询”和“订单详情返回”。4. 工具实操——Visio、draw.io和PlantUML怎么选画数据流图的工具很多Visio、draw.io、ProcessOn、PlantUML、StarUML都能画。我重点讲三个我用得最多的Visio、draw.io和PlantUML各有各的适用场景。4.1 Visio模板齐全但要注意版本兼容Visio是很多公司标配的绘图工具它的“软件和数据库”模板里有专门的“数据流图”模板四种符号直接拖拽就能用。用Visio画图的好处是排版规整导出图片清晰。但有两个坑要注意第一Visio的版本兼容问题2016版和2019版的模板位置不一样有时候同事发来的文件你打不开第二Visio默认的连接线有时候会自动绕路画出来的箭头弯弯曲曲的需要在“设计”里把连接线样式改成直线。在Visio里画数据流图我习惯先画好所有加工和外部实体再用连接线工具连数据流。连接线一定要加箭头Visio默认的连线可能是双向箭头或者无箭头需要手动改。另外Visio里的“数据流”形状有时候会被识别成“流程”形状导出的时候要注意检查。4.2 draw.io免费、跨平台、适合团队协作draw.io现在叫diagrams.net完全免费浏览器打开就能用也可以下载桌面版。它的“软件”分类里有数据流图模板但符号不是特别标准需要自己调整。我通常是自己画几个基本形状保存成模板以后直接复用。draw.io最大的好处是协作方便可以导出成XML或者PNG也可以直接分享链接给同事一起编辑。对于小团队来说比Visio省事。它的对齐和分布功能也很好用按住Ctrl可以多选元素然后一键对齐画出来的图很整齐。4.3 PlantUML代码画图适合版本管理PlantUML不是专门画数据流图的工具但可以用组件图或者自定义形状来模拟数据流图。它的优势是纯文本可以放到Git里做版本管理改起来也快。如果你的团队习惯用代码管理文档PlantUML是个不错的选择。用PlantUML画数据流图的大致写法是用component表示加工用rectangle表示外部实体用database表示数据存储用箭头表示数据流。虽然不如图形化工具直观但改起来很快而且不会出现排版错乱的问题。工具适合场景优点缺点Visio传统企业、正式文档模板标准、排版好收费、版本兼容问题draw.io小团队、快速协作免费、跨平台、易分享符号需自己调整PlantUML代码化管理、技术团队文本化、可版本控制学习成本、不直观我的建议是如果公司有Visio授权就用Visio如果团队小、预算有限draw.io完全够用如果你们团队习惯用Git管理文档PlantUML值得一试。4.4 一个Visio实操小技巧在Visio里画数据流图很多人会遇到一个问题连接线交叉太乱图看起来像一团麻。我的处理办法是尽量把数据存储画在图的中间偏下位置加工围在周围外部实体放在最外侧。这样数据流的方向基本是从外到内、从内到外交叉会少很多。另外可以用不同颜色区分不同类型的元素比如加工用浅蓝色、数据存储用浅黄色、外部实体用浅灰色视觉上清晰很多。导出图片的时候Visio默认导出分辨率可能不够在“另存为”里选择PNG然后点“选项”把分辨率调到300dpi以上这样放到文档里不会模糊。5. 常见错误与排查——这些坑我基本都踩过数据流图看起来简单但真正画好需要避开不少坑。这一节我把自己和身边同事踩过的典型问题整理出来对照着排查能省很多时间。5.1 父子图不平衡——最常见的错误父子图不平衡是数据流图审核中最常见的问题。什么叫不平衡就是父图里某个加工的输入输出数据流在子图里对不上。比如父图里加工“处理订单”有一个输入流“订单信息”子图里却出现了“订单信息”和“用户信息”两个输入流而“用户信息”在父图里根本没有。这就破坏了平衡。平衡检查的方法很简单把父图里该加工的所有输入输出流列出来再把子图里所有跟外部交互的流列出来两边必须完全一致。子图内部加工之间的流不算只检查子图边界上的流。我通常会用一张纸把父图的流抄下来然后对着子图一个一个勾虽然笨但很有效。5.2 数据流没有名字或者名字太泛这个问题新手特别容易犯。画了一堆箭头一个名字都不写或者全写“数据”。这样的图给谁看都看不懂。数据流必须有名而且名字要具体。如果一条流传输的是复合数据可以给一个概括性的名字但在数据字典里要展开说明包含哪些字段。还有一个隐蔽的问题两条数据流名字一样但内容不一样。比如两条流都叫“订单信息”一条是顾客提交的原始订单一条是系统处理后写库的订单内容其实不同。这种情况要么改名字区分要么在数据字典里注明。5.3 把控制流画成数据流这个错误我前面提过但值得再强调一次。数据流图里不应该出现“如果……则……”“循环”“等待”这类控制逻辑。如果你发现自己在图上画了一个箭头标注“库存不足时”那就说明你把控制流混进来了。正确的做法是把这个逻辑放到加工的说明里去图上只保留数据流。举个例子“检查库存”这个加工输出可以是“库存可用”和“库存不足”两条数据流分别流向不同的后续加工。这样图上没有条件判断但语义上已经表达了分支。数据流图的分支是通过多条输出流来体现的不是通过条件标注。5.4 外部实体和数据存储混淆外部实体是系统之外的人或系统数据存储是系统内部的数据存放处。但有时候边界比较模糊比如“用户数据库”如果归我们系统维护那就是数据存储如果归其他系统维护我们只是调用接口查询那它就是外部实体。判断标准是我们是否负责这个数据的存储和维护。是就是数据存储不是就是外部实体。5.5 加工只有输入没有输出或者只有输出没有输入每个加工必须有输入和输出。只有输入没有输出的加工叫“黑洞”只有输出没有输入的加工叫“奇迹”。这两种都是错误的。黑洞意味着数据进去了但没出来要么是漏画了输出流要么是这个加工根本不应该存在。奇迹意味着数据凭空产生要么是漏画了输入流要么是把外部实体误画成了加工。5.6 常见问题速查表问题现象可能原因排查方法父子图数据流对不上分解时遗漏或增加了流列出父图边界流逐条对照子图图看起来像流程图混入了控制逻辑检查箭头上是否有条件描述数据流方向混乱命名太泛或方向标错给每条流起具体名字核对方向加工数量过多或过少分解粒度不当控制在3-7个过多继续分层数据存储出现在顶层图边界划分错误顶层图只保留系统和外部实体6. 数据字典与图配套——别让图变成孤儿数据流图画完之后如果没有配套的数据字典图的可用性会大打折扣。数据字典是数据流图的说明书它定义每个数据流、数据存储、加工和外部实体的详细内容。很多人只画图不写字典结果过两个月自己都忘了图上的“订单信息”到底包含哪些字段。数据字典的写法有很多种常见的用条目式描述。比如“订单信息订单编号顾客编号商品列表下单时间”其中“商品列表商品编号数量单价”。这种形式叫数据结构的定义。加工的定义通常用判断表或者结构化语言描述比如“检查库存”的加工说明可以写成如果订单数量小于等于库存数量则输出“库存可用”否则输出“库存不足”。我自己的习惯是画数据流图的同时就在旁边开一个文档写数据字典图改一次字典也跟着改一次。这样交付的时候图和字典是配套的别人接手也能看懂。如果是团队协作数据字典还可以放到Confluence或者Wiki里方便查阅和更新。6.1 数据字典的常见条目格式数据流条目要写清楚名称、来源、去向、包含的数据项、数据量。数据存储条目要写清楚名称、编号、流入数据流、流出数据流、数据结构。加工条目要写清楚名称、编号、输入、输出、加工逻辑说明。外部实体条目相对简单写清楚名称和与系统的交互即可。6.2 一个容易被忽略的细节数据字典里的数据项定义要统一命名。很多项目里同一个字段在不同地方叫法不同比如“用户编号”和“客户ID”其实是同一个东西但在图上和字典里没统一导致开发的时候对不上。解决的办法是维护一张数据项命名对照表所有图、字典、数据库设计都从这张表里取名字。这个习惯看起来麻烦但在中大型项目里能省掉大量沟通成本。7. 从数据流图到后续设计——这张图还能怎么用数据流图不是画完就束之高阁的东西它在后续的设计阶段还有不少用处。最直接的是数据流图里的每个加工都可以进一步映射成模块结构图里的一个模块数据流图里的数据存储可以映射成数据库设计的表结构。这种映射关系是结构化设计方法的核心。虽然现在很多项目用面向对象的方法类图、时序图更常见但数据流图在需求梳理阶段仍然有不可替代的价值尤其是在业务逻辑比较复杂、数据流转比较多的系统里。我个人的做法是在需求分析阶段先画数据流图把数据流向理清楚然后再画用例图描述功能画类图描述静态结构。数据流图帮我确认“数据从哪来到哪去”用例图帮我确认“谁做什么”类图帮我确认“系统里有哪些对象”。三张图互相补充而不是互相替代。另外数据流图还可以用来做数据一致性检查。比如某个数据项在图上出现了多次但来源不一致这就可能意味着需求里有冲突。再比如某个数据存储只写不读或者只读不写也是需要确认的异常点。这些检查在大型系统里特别有用能提前发现不少需求漏洞。7.1 数据流图在敏捷项目里的简化用法有人觉得数据流图是传统结构化方法的产物敏捷项目里用不上。我不同意。敏捷项目虽然不强调写详细文档但在梳理用户故事的时候画一张简化的数据流图能帮团队快速对齐数据流向尤其是涉及多个系统交互的场景。简化用法就是只画0层图不写详细数据字典图上标注关键数据流即可。花半个小时画一张比开一个小时的会对齐效果还好。7.2 复查清单发布前过一遍最后分享一个我每次画完数据流图都会过一遍的复查清单你可以直接拿去用。顶层图是否只有一个加工且没有数据存储外部实体是否都在系统边界之外每个加工是否有输入和输出父子图的数据流是否平衡数据流是否都有名字且名字具体数据存储是否命名规范与数据库设计一致图上是否混入了控制流或时序标注是否配套了数据字典这个清单不复杂但能拦住大部分低级错误。我刚开始画数据流图的时候经常是画完自我感觉良好一对照清单发现好几个地方有问题改完才敢发给同事评审。时间长了这些检查点就变成肌肉记忆了现在画完基本不用逐条对扫一眼就知道有没有毛病。7.3 我个人在实际操作中的体会说点实在的数据流图这个东西看十遍不如画一遍。我当初学的时候教材上的例子看懂了自己动手画图书管理系统还是画得乱七八糟。后来是硬着头皮画了五六个系统的数据流图才慢慢找到感觉。建议你也别光看找个熟悉的场景比如外卖点餐、图书馆借书、酒店订房自己从头画一遍遇到卡壳的地方再回来查资料这样学得最快。还有一个心得是画数据流图一定要跟业务方确认。你自己觉得逻辑通了业务方一看说“我们实际不是这样的”那就白画了。数据流图的价值在于沟通画得再漂亮业务方看不懂或者不认可就是废纸。所以画完之后拿着图跟业务方过一遍每条数据流问一句“这个数据是从哪来的、到哪去的”确认无误再定稿。这一步花的时间比后面返工省的时间多得多。
上一篇/下一篇内容由系统自动关联
返回资讯列表 →