从入门到实战:画法、规范与常见错误)
1. 为什么非要把数据流动这件事画清楚被要求画数据流图的人通常分为两种一种是刚接手需求分析、被文档规范逼着交图的开发或产品另一种是系统已经上线、要改造却说不清现网数据走向的维护者。两者的共同点是嘴上都能聊业务落笔就卡壳。这不是手笨而是脑子里的业务本身是糊的。数据流图Data Flow DiagramDFD的全部价值就是逼着你在画图之前先把数据从哪来、经过谁处理、存到什么地方、最终递给谁这条链路想清楚。它跟平时写的需求文档不一样文档允许你含糊其辞说系统进行校验数据流图不允许——因为你必须画出校验的输入是什么、输出是什么、数据流从哪个环节流到哪个环节含糊的地方在图上一目了然。我在实际项目里见过最典型的场景业务方说我们要做一个订单查询功能开发听成了写个接口查数据库结果做出来只能查订单表。但真正跑业务的时候发现订单还要关联用户信息、涉及库存扣减记录、还要对接支付回调的状态更新整个数据的流转路径远不止一张表。如果画过数据流图这个需求从一开始就不会被简化成查表因为你会被迫画出订单状态变更时数据流经的每一个加工环节。1.1 数据流图和程序流程图到底是不是一回事这是新手最容易混淆的问题。程序流程图Flowchart关心的是程序先执行哪一步、判断什么条件、走到哪个分支它有一条明确的控制主线强调时间顺序和逻辑分支。数据流图完全不关心这些它关心的只有一件事数据对象在不同处理环节之间的流动和变换。举个例子。一个登录功能程序流程图会画输入账号密码 - 格式校验 - 查询用户表 - 密码比对 - 登录成功/失败每一步都在一条时间轴上串行。数据流图则会画成用户外部实体把登录请求数据流交给认证处理加工认证处理从用户存储数据存储读取账号信息然后输出登录结果数据流给用户。它不标注先做什么后做什么因为数据流图是逻辑模型不是流程模型。这个区分直接影响画图的质量。我在评审时经常看到有人把数据流图画成了带菱形判断框的流程图那就是把两个维度的事混在一起了。数据流图里允许出现的数据元素只有四个外部实体、加工、数据存储、数据流。如果你发现自己在图里画了菱形、画了IF/ELSE、或者画了循环虚线说明你没有在画数据流图而是在画流程图。1.2 什么人、什么时候需要用到数据流图数据流图不是软件工程课上应付作业的产物。它至少能在三类场景里真正起到作用第一需求分析阶段帮助分析师和业务方对齐业务边界。我经历过一个ERP采购模块的改造业务方讲需求时用了两个小时的PPT听完之后每个人理解的都不同。后来我花了半天时间把现有流程画成一张零层数据流图业务方一看就发现了三个流程描述与实际操作不一致的地方。图比文字更擅长暴露分歧。第二系统设计阶段作为模块划分和接口设计的依据。数据流图里的每一个加工基本都可以映射为一个功能模块或者服务数据流对应模块间的接口数据存储对应需要落库的数据实体。有了数据流图做架构设计时就不用拍脑袋定模块边界。第三系统维护和交接阶段。老系统没有文档代码又难读把程序跑起来抓日志、顺着数据流把系统画出来是比看源码更快的理解方式。我接手过一个十年的老系统当时就是靠一张数据流图快速定位了数据异常问题——顺着数据流从源头查到目标端发现问题出在两个加工之间的数据流转上而这正是画图时最容易暴露的盲区。2. 四个基础构件和那套容易忽略的语法规则画数据流图先在白板上写下四个词外部实体、加工、数据存储、数据流。整个图就是这四个元素的组合没有第五种。2.1 外部实体系统外面的人和系统外部实体是数据流图的起点和终点它是系统边界之外、但与系统有数据交互的人、组织或外部系统。比如一个图书管理系统中读者是外部实体图书管理员是外部实体如果要对接校园卡系统那么校园卡系统也是一个外部实体。判断一个对象是不是外部实体有一个简单标准它是否在本系统内部执行处理。如果读者只是提交借书请求、接收借书结果他自己不参与系统的任何处理逻辑那他就是外部实体。如果图书管理员要在系统内部进行图书入库操作但他本人不会写代码、不会处理数据他仍然是外部实体——真正负责处理的是图里的图书入库管理加工。外部实体的命名一般直接用名词比如读者供应商银行系统微信支付平台。不用加动词因为外部实体本身不做处理。很多新手把外部实体和加工混在一起画出一个数据来源方框既接收数据又输出处理结果这是错误的。记住外部实体只负责提供原始数据和接收最终结果一切计算、判断、变换都发生在加工里。2.2 加工核心中的核心加工是数据流图里唯一能对数据进行变换的环节是整张图的心脏。它的本质是输入数据流 处理逻辑 输出数据流。一个加工最少需要一条输入数据流和一条输出数据流没有输入就没有数据来源没有输出就说明处理没有结果。加工的命名是数据流图最见功力、也最容易偷懒的地方。规范是动词宾语越具体越好。比如验证读者身份比处理读者信息好计算逾期罚款比罚款管理好。处理管理操作这类动词信息量为零我看到标着数据处理的加工就知道画图的人没想清楚这个环节到底在干什么。加工还有一个容易被忽视的点编号。在分层数据流图中顶层加工编号为0零层图的加工编号为1、2、3……更下一层的子加工编号则为1.1、1.2、2.1、2.2这样的多级编号。编号的作用不只是标识更重要的是建立父子关系方便从上层图追踪到下层图形成完整的层次体系。2.3 数据存储静止的数据数据流图里的数据存储代表数据的静止状态比如数据库表、文件、缓存甚至业务上的一组数据集合。数据存储同样需要命名用名词比如读者档案图书目录借阅记录。有两个关于数据存储的规则新手经常踩雷。第一条数据流不能直接在两个数据存储之间流动必须经过加工。因为数据存储本身不会主动产生数据发出数据流所有对存储的读写都必须由某个加工来驱动。第二条数据流也不能直接从外部实体流到数据存储外部实体访问存储同样必须通过加工。你可以把加工想象成唯一能伸手碰数据存储的角色。我在画图时经常被问到一个加工同时读写同一个数据存储该怎么画答案是画两条数据流一条从存储指向加工读一条从加工指向存储写。方向必须清楚不能只画一条没有方向的线因为读和写在业务上是两个不同的动作。2.4 数据流一切关系的载体数据流是连接前三个元素的纽带它表示一组在特定方向上流动的数据比如借书申请查询条件库存记录罚款通知。数据流的箭头方向就是数据的流向永远不能画成没有方向感的线。数据流有几个容易忽略的细节。第一不要用双向箭头。业务中确实存在请求——响应这种一来一回的交互但这是两条独立的数据流每条都有各自的方向不能合并成一条双向箭头因为你丢失了请求在前、响应在后这种先后语义之后细化的时候会很难处理。第二数据流必须有名字没有名字的箭头在评审时一定会被追问这里面到底传的是什么。流的名字要和数据实体对应不要叫数据信息这种空泛的词。第三数据流不能直接从外部实体连到另一个外部实体也不能直接从存储连到另一个存储理由和前面一样——必须经过加工。2.5 命名规范和编号规则把命名和编号单独拿出来说一段是因为这是数据流图和普通示意图最本质的区别。数据流图的读者不只是人它最终要对齐到系统设计所以每个元素都必须有一致的、无歧义的标识。加工编号在多级分解时容易出问题。比如零层图里有加工1借书处理加工2还书处理如果借书处理继续分解出子加工那子加工的编号应该是1.1、1.2、1.3而不是重新编1、2、3。这个规则的目的在于任何一个子加工都能通过编号回溯到它在父图中的位置形成完整的追溯链。审查的时候我会拿着父图和子图逐一核对最怕的就是子图画完忘了编对应关系结果无法确认哪些加工被特别展开了。对于外部实体和数据存储可以在命名前加上特定的标签外部实体用E1、E2标识很多教材直接用名字不强制编号数据存储用D1、D2标识。加上编号的最大好处是方便在数据字典里引用比如D2 图书目录字段包括ISBN、书名、作者、馆藏数量、可借数量。看图的时候看到D2就能第一时间定位到数据字典里的详细定义。3. 上下文图与逐层分解把大系统拆成能落地的模块数据流图最核心、也最需要练的方法论就是自顶向下的分层分解。一套完整的数据流图通常包含上下文图Context Diagram、零层图Level 0 Diagram以及更细的子图Level 1、Level 2……。这个思想一点都不玄你平时画架构图也是先画整体框再拆内部模块数据流图只是把这个过程规范化了。3.1 上下文图整个系统就是一个加工上下文图又叫顶层图它只包含一个加工用来表示整个系统加工编号为0。图的周围布置所有与系统交互的外部实体用数据流把它们和这个唯一的加工连接起来。上下文图的价值在于确定系统边界。画上下文图的时候你要回答一个问题哪些数据交互属于系统内部、哪些属于系统和外界的交互凡是与外部实体连接的数据流就是系统的输入输出边界凡是系统内部的数据流动暂时不画。我在项目里的习惯是上下文图一定手画不用工具。让业务方参与进来在白板上画一个大的圆角矩形代表系统让业务方指出谁会给系统提供数据系统会给谁输出数据这一步做完系统边界就已经清楚了。边界不清是项目后期需求蔓延的温床上下文图是最便宜的防御手段。3.2 零层图第一次真正的分解零层图是把上下文图里那个大而化之的加工0分解为若干个子加工这些子加工共同完成系统的主要功能。每个子加工的输入输出数据流必须和整个系统对外的输入输出数据流能够对应上——这就是父图与子图平衡原则的第一次应用。举例来说图书借阅系统的上下文图里读者向系统发出一条借书申请数据流。到了零层图借书申请这条数据流必须出现在某一或某些子加工上不能凭空消失。读者发出借书申请在零层图里它就进入了加工1借书处理读者发出的查询请求则进入了加工3书目查询。每条上下文图里的数据流在零层图里都能找到归宿。零层图分解数量的把握很考验功力。我把子加工的数量控制在7±2个以内——这是认知心理学里一个常用参考值超过这个范围看图的人就很难在一次浏览里记住整个系统的全貌。如果系统功能确实很多优先考虑把其中复杂的加工继续下钻而不是在零层图里堆二十个加工。3.3 子图分解的边界和编号方法当一个加工的内部逻辑仍然复杂比如借书处理里有身份验证、库存检查、借阅登记、超限判断多个步骤就应该对它继续分解生成下一层的子图。子图里是这个加工的更详细展开它的内部由若干子加工和若干数据存储组成。子图的数据流方向有一点要特别注意子图只描述被分解的那个加工的细节所以子图的边界就是父图中该加工的边界。子图的输入输出数据流必须和父图中该加工的输入输出数据流保持一致。父图中加工1借书处理的输入是借书申请输出是借书结果那么子图里从外部进到子图里的数据流必须是借书申请出子图的数据流必须是借书结果。中间新增的内部数据流和数据存储则画在子图内部这些在父图中不出现——它们属于加工内部细节。3.4 父图子图平衡原则怎么自检父图子图平衡原则是数据流图正确性的核心检查项。原则的标准说法是父图中的某个加工分解成子图后子图的输入输出数据流必须与父图中该加工的输入输出数据流在数量和名称上完全一致。这里的一致是硬性约束不是差不多。父图中加工1有两条输入数据流借书申请和读者档案查询结果那条子图里就必须正好出现这两条输入不能多一条管理员指令也不能少一条读者档案查询结果。多了少了都说明你的分解改变了系统的对外接口属于逻辑错误。我在 REVIEW 时见过最典型的平衡错误是父图中加工1有一个输出借书结果子图里却画成了借书成功通知和借书失败通知两条输出。看起来业务上没问题——借书结果不就是成功或失败吗但在数据流图的语法里这是三条不同的数据流借书结果不仅能表达成功/失败还能包含失败原因、应还日期这些信息另外加输出意味着接口发生了变化。要找子图画通顺的方案可以在子图内部用加工1.4生成借书结果来汇总向外输出仍然保持父图指定的借书结果这一条子图内部再怎么分叉都不影响对外接口。这就是平衡原则的实际运用子图内部可以任意复杂但对外边界要完全继承父图。4. 实战案例图书借阅系统的完整画图过程讲完概念我们用同一个案例走通全部画图流程。选图书借阅系统是因为它的业务逻辑足够日常同时又包含了多外部实体、多数据存储、多加工之间的复杂交互能覆盖大部分画图场景。4.1 需求概况和系统边界确认场景需求是这样学校图书馆要做一个借书还书管理系统。读者可以在系统里查书目、借书、还书、查自己的借阅记录。图书管理员负责录入新书、下架旧书、处理读者罚款。第一步先识别外部实体和系统边界。读者肯定是外部实体图书管理员也是。那罚款通知是系统发给读者的数据流还是系统内部的动作答案是系统内部的加工产生罚款通知然后通过数据流发给读者这个外部实体。读者和图书管理员都在系统边界之外系统内部只存在加工、存储和数据流。边界确认这一步不能省。如果有业务方说读者还需要能在线支付罚款那在线支付的加工就要新增一个外部实体支付平台。边界确定了后面的图和开发工作量估算就直接挂钩。4.2 第一步画上下文图上下文图只有一个加工编号0名字就叫图书借阅系统。外部实体有两个E1读者、E2图书管理员。读者和系统之间的数据流包括借书申请读者→系统、借书结果系统→读者、还书申请读者→系统、还书结果系统→读者、书目查询请求读者→系统、书目信息系统→读者、借阅记录查询请求读者→系统、借阅记录系统→读者、罚款支付请求读者→系统、罚款支付结果系统→读者。图书管理员和系统之间的数据流包括新书信息管理员→系统、入库结果系统→管理员、图书下架请求管理员→系统、下架结果系统→管理员。这已经是上下文图的完整内容了。检查一下图上只有一堆外部实体和一个大加工所有数据流都是外部实体和加工之间的直接连接没有任何存储出现在图上——存储是系统内部概念在上下文图阶段不需要暴露。4.3 第二步画零层数据流图零层图把加工0拆成5个主要加工加工编号加工名称主要输入数据流主要输出数据流相关数据存储1借书处理借书申请借书结果D2图书目录、D3借阅记录2还书处理还书申请还书结果D3借阅记录、D4罚款记录3书目查询书目查询请求书目信息D2图书目录4图书入库管理新书信息、下架请求入库结果、下架结果D2图书目录5借阅记录管理借阅记录查询请求借阅记录D3借阅记录数据存储在这里出现了D2图书目录、D3借阅记录、D4罚款记录再加一个D1读者档案——借书时要验证读者资格得查读者档案。读者档案的读写主要由加工1处理还书超期时加工2也要读读者信息所以加工2也连到D1。先把外部实体的数据流对应到具体加工再把加工之间的数据流也画出来。比如读者发起借书申请进入加工1加工1处理时读D1读者档案、D2图书目录写D3借阅记录然后输出借书结果给读者。这一步是整个系统最核心的数据流转关系一旦画错后面的细节都会错。4.4 第三步对关键加工继续分解以借书为例加工1借书处理在零层图里仍然是一个黑盒需要继续分解成一层子图。分解后的加工1包括四个子环节子加工编号名称说明1.1验证读者借阅资格读取D1读者档案判断读者是否存在、是否有逾期未还记录、借阅数量是否达到上限1.2校验图书可借状态读取D2图书目录判断图书是否在馆、是否被预约1.3登记借阅信息写入D3借阅记录同时更新D2图书目录中该图书的状态1.4生成借书结果汇总前面环节的结果生成通知数据流返回给读者子图边界检查父图中加工1的入边借书申请在子图里从外部进入1.1父图中加工1的出边借书结果在子图里由1.4输出到外部。入边出边各一条与父图完全一致——平衡。子图内部的数据流读者资格核验结果从1.1流向1.2还是1.4取决于业务逻辑的先后关系这属于子图细节不用上升到父图层面。画到这一步借书流程已经细化得足够精准了。1.1到1.4每一个子加工将来都能对应到具体的功能模块或者服务接口。4.5 配套的数据字典让图不再有歧义数据流图画完只完成了工作的一半。图上的每一个数据流、数据存储、加工都要在数据字典里有明确定义否则看图的两个人对借书申请这四个字可能有完全不同的理解。数据字典的记录至少包含这几个字段数据项名称、别名如果有、类型、长度如果有限制、取值范围可选项、来源、去向、业务含义。一节数据流字典的示例数据项含义组成结构借书申请读者发起借书时提交的信息读者ID 图书ID 申请时间借书结果系统返回给读者的借书处理结果读者ID 图书ID 处理结果 失败原因 应还日期读者档案读者的个人及状态信息读者ID 姓名 联系方式 最大借阅数 当前借阅数 状态图书目录图书馆在架图书信息ISBN 书名 作者 馆藏数量 在馆数量 状态数据字典的完整程度直接决定开发时会不会反复拉扯。我之前吃过亏图上的数据流写订单信息数据字典里没有定义结果前端说订单信息包含商品ID数组后端说订单信息只是订单主表ID两边对不上项目延期了两周。所以我的习惯是图和数据字典一次性画完写完不允许只交一张图。5. 最常见的五个错误和修正方式画数据流图最大的困惑在于图画完了怎么判断画得对不对以下五个错误是我在项目评审中最常遇到的每个都有明确的特征和修正方法。5.1 黑洞、奇迹、灰洞数据流图的三条死路这三个词是数据流图质量检查里最经典的概念黑洞Black Hole加工只有输入数据流没有输出数据流。数据流进去了就消失了这个加工是无效的因为它没有对输入做任何处理的产出。奇迹Miracle加工只有输出数据流没有输入数据流。输出凭空产生找不出数据来源这通常是画图时漏画了输入。灰洞Grey Hole加工既有输入又有输出但输入不足以产生输出。比如计算罚款的输入只有还书申请但罚款金额的计算还需要借阅记录和罚款标准缺了这些数据流输出就不可能正确产生。修正方法也很直接。遇到黑洞追问自己这一步处理完要给出什么结果补上输出遇到奇迹反问自己生成这个输出需要什么数据支撑补上输入遇到灰洞把加工内部完整推演一遍把遗漏的输入数据流和数据存储补齐。每次画完图按这三个词逐一检查每个加工大概率能揪出七八成的问题。5.2 把控制流当数据流最常见的语义混淆数据流图上经常出现一种误画把一个加工触发另一个加工的关系画成数据流。比如还书处理完成后触发罚款计算有人就把还款通知当成数据流从还书处理指向罚款计算。但触发通知调用是控制流不是数据流。控制流表达的是发生后接下来做这件事的关系数据流表达的是这份数据交给下一个环节处理的关系。怎么区分看这条线上有没有数据载荷。如果两个加工之间只存在调用关系没有实际的数据内容传递那就不该出现在数据流图上。我在实践中的处理办法是把触发罚款计算改成还书信息作为数据流从还书处理流向罚款计算这样语义就对了——罚款计算需要还书信息才能知道还了哪本书、还书日期是什么数据流有了具体载荷触发含义就隐去了。记住一条数据流图上每一条线都必须有名字、有方向、传递某种具体数据画不出来的信息传递就不要画。5.3 双向箭头和数据流的直接跨越两种常见的结构错误。第一种是用双向箭头表示请求/响应两条方向相反的数据流。这种画法看似简洁但读者无法分辨数据的先后顺序也无法为两条方向相反的数据流分别命名。数据字典里也没法定义一条双向流。修正方法是拆成两条数据流比如借书申请读者→系统和借书结果系统→读者。第二种是数据流跨越。看看图上有没有一条数据流横穿其他元素或者一条数据流连接了不该连接的对象。比如两个外部实体之间直接连数据流、两个数据存储之间直接连数据流、外部实体直接连数据存储——这些都是违反语法规则的。数据流必须要么连接外部实体和加工要么连接加工和加工要么连接加工和数据存储。没有任何一条数据流能绕过加工存在因为加工是数据变换的唯一场所。5.4 命名含糊、没有编号、分层断链命名是数据流图最容易被低估的质量标准。信息数据处理这类命名等于没命名。一个读者看到订单信息和订单数据两个名字会不确定它们是不是同一种数据流。命名要满足两个条件唯一性和一致性。同一份数据在整个图里只能有一个名字另外同义词要收敛数据字典里统一指定。订单信息和订单数据在数据字典里明确为同一条数据流之后图中只能选一个名字贯穿使用。编号是另一个常见问题。加工没有编号、编号跳号、子加工编号和父加工编号对应不上这些看起来是细节问题但会导致整张图的追溯链断裂。零层图加工5借阅记录管理如果想继续分解子图里却找不到任何一个子加工编号带5.的前缀那父图和子图的对应关系就断了。分层数据流图的顺序追踪完全依赖编号这个索引编号乱了图就废了。5.5 过度分解和分解不足分解到什么程度才算合适我常用的判断标准是当一个加工的内部逻辑可以用一句自然语言说清楚时就不需要继续分解了。计算逾期罚款这句话已经足够清晰就不需要拆成读借阅记录读罚款标准执行乘法返回结果四个加工。反过来如果处理借书这种加工内部包含了资格验证、库存校验、登记、状态更新那明显还需要拆。过度分解会带来维护成本骤增的问题。我有一次接过别人一张画到第四层的图一张A3纸密密麻麻全是加工框和数据流每个加工的内容其实就一两行逻辑。这种图的信息密度严重超出人脑的短时记忆容量看图的人很难建立整体认知后续修改也容易漏改链条中的环节。合理的粒度是每一层子图呈现的加工数量在7个以内单个加工能够用一句话说清它的输入、处理和输出关系。如果新手拿不准我的建议是宁可略微分解不足也不要过度分解——因为后续重构中往上合并远比往下拆要难。5.6 查询修改数据流图时的维护问题这里要单独提一下网上搜到的那个热搜词查询修改数据流图。它的本质是指在系统上线之后业务发生变化需要对已有的数据流图进行查询定位和修改。这个场景下最常见的麻烦是改了一张图忘了改关联的图和数据字典。改图的正确顺序是先定位变更点涉及的数据流、加工、存储然后在相应层级的图上修改再检查父图与子图的平衡是否被破坏最后同步更新数据字典。比如新增了一个图书预约功能零层图新增加工6预约管理同时读者这条外部实体上新增数据流预约申请和预约结果如果预约会影响图书状态加工6还要连到D2图书目录——牵一发而动全身图上改完不是终点数据字典里新增的预约申请记录也必须跟上。如果不做这层联动数据流图就会长成和实际系统脱节的僵尸图比没有图更害人。6. 画图工具、检查清单和收尾技巧画数据流图的工具有很多选择但工具从来不是重点。不过还是简单说一下我自己的推荐和取舍。6.1 工具怎么选我的建议是分场景不要迷信某一个工具。白板或纸笔用来画上下文图和第一版零层图。这是讨论草稿阶段重点是快速迭代和团队共识不是画得漂亮。draw.iodiagrams.net免费、网页版、支持协作文件可以存本地或者同步到各类网盘。我绝大多数正式图都是用它画的。它内置数据流图的基本图形导出SVG/PNG都很方便和代码一样可以进版本管理。ProcessOn国内访问速度快模板多适合团队协作和分享。界面比draw.io精致一些但免费版有文件数限制。Visio微软生态里比较稳的选择适合企业标准化环境但价格不低而且文件格式在团队协作时有一定门槛。PlantUML代码化画图工具用文本描述图形适合极客风格的开发者。优点是可以写进Markdown文档里、可以做版本diff缺点是需要记语法。亿图图示国产工具模板多上手简单适合不太熟悉画图工具的人。无论用哪个工具我建议最后导出的格式里一定包含SVG或者PDF向量格式不要只留一个图片格式否则后续修改时没法编辑。6.2 画完之后十项检查清单图和数据字典都完成后我会按下面这十项逐一自检你也可以把这十项当作数据流图评审的标准问题序号检查项检查要点1加工是否都有编号编号是否连续、是否与父图对应2数据流是否都有名称命名是否符合业务语义、是否含糊3每个加工是否有输入有输出排查黑洞、奇迹、灰洞4父图与子图是否平衡输入输出数据流数量、名称是否一致5是否有双向箭头有则拆分为两条方向相反的单向数据流6数据流是否直接连接存储到存储不允许必须经过加工7数据流是否直接连接外部实体到实体不允许必须经过加工8数据存储是否都有读写加工没有加工连接的孤儿存储需要处理9加工之间的传递是否真的传递了数据区分数据流与控制流10数据字典是否完整每条数据流、存储、加工都有定义第六条和第七条是我自己在评审中重点盯的。它们是最容易犯的结构性错误也是最容易被工具检查出来的错误——很多画图工具不支持这种数据流图特有的约束规则不能指望工具代劳。6.3 从数据流图到系统设计的过渡画完数据流图系统的逻辑模型就完型了。接下来自然要进入设计阶段数据流图可以作为三件事的依据第一模块划分。数据流图上的加工可以直接映射为功能模块加工之间的数据流关系就是模块间的接口关系。我在做系统设计时会先照着零层图的加工列表排模块清单基本能覆盖九十以上的功能范围。第二数据库设计。数据存储对应数据库表或表集合数据流上流动的数据项对应字段。数据字典里每个存储的组成结构拿过来就是建表语句的字段清单。这一步衔接特别顺手几乎不需要额外转换。第三接口设计。外部实体与系统之间的数据流就是对外接口清单。上下文图里有多少条外部数据流基本就对应多少个API或界面交互场景。我在确认接口阶段会再把上下文图和外部数据流逐条过一遍防止遗漏外部系统对接需求。有一个容易忽视的点数据流图是逻辑模型它不关心技术实现。同一个加工将来可以用一个服务、一个函数、甚至一段SQL实现——图里不需要考虑这些。但反过来如果一个加工在实现时需要依赖外部服务的响应那么这个外部服务就要作为外部实体画进图里。这个边界很多人画完图之后就忘了等做设计时才发现漏了外部接口又要回去改图。我的建议是画完上下文图先停一下把外部实体清单列出来发给所有相关方确认一遍确认无误再继续往下画。边界确认这一步省不了因为它一错所有层级数据流都会跟着错。最后分享一点实际经验我在实际项目中画过不下几十张数据流图也评审过别人画的不少图。最大的体会是数据流图的难点从来不在图本身而在于画图的人是否真的把业务流程想通了。如果你发现某个加工怎么画都不顺输入输出来回对不上先别急着调整图——回到业务现场找业务方把实际的流转路径问清楚大概率是业务本身存在模糊或者冲突。另一个小技巧是正式成图之前好歹在纸上画三遍。第一遍自己凭直觉画第二遍拿着纸找业务方对流程第三遍根据反馈修正后再用工具画电子版。直接开工具画图的效率反而是最低的因为大部分人边画边改的时候注意力都会被工具的格式、对齐、配色带走反而忽略了数据流本身是否合理。等图画完退一步看整张图数据流像是血液一样在系统里循环自然流畅没有断点没有堵点没有凭空出现的产出那这张图就基本上合格了。最后叮嘱一句画完图一定要生成PDF发给团队和业务方确认签字别让它只躺在你个人的绘图工具里。数据流图的价值在沟通和共识不在图本身。一张被团队一起看图、一起讨论、一起确认过的数据流图比百页需求文档更能防止项目后期的不确定性和返工。