ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

数据流图(DFD)核心解析:从建模思想到微服务边界的实战指南

数据流图(DFD)核心解析:从建模思想到微服务边界的实战指南 1. 从“流程图”到“数据流图”一个被误解多年的核心工具很多刚接触系统分析或软件设计的朋友一听到“数据流图”Data Flow Diagram, DFD第一反应可能就是“哦不就是画流程图嘛用Visio或者Draw.io拖几个框连几条线就行了。” 我刚开始做项目的时候也是这么想的结果在第一次和业务方对需求时就被问懵了——我画的那个“精美”的流程图业务方看了半天指着其中一个环节问“这个‘审批’动作它具体需要哪些单据审批完成后这些单据的数据是消失了还是变成了新的什么状态流到下一个环节” 我当场语塞。这就是DFD和普通流程图的本质区别。流程图Flowchart关注的是控制流即“先做什么后做什么在什么条件下跳转到哪一步”它描述的是处理逻辑的顺序和分支。而数据流图DFD关注的是数据流即“数据从哪里来经过什么处理变成了什么新数据最后到哪里去”。它不关心时间顺序比如A处理和B处理谁先谁后它只关心数据的变换和流动。对于一个系统分析师或软件架构师来说DFD是理解系统“数据本质”和定义系统边界即系统到底该管什么不该管什么的基石性工具。它强迫你从数据的视角而不是从操作步骤的视角去解构一个业务系统。举个例子一个简单的“员工报销”流程。用流程图画你会画出提交报销单 - 部门经理审批 - 财务审核 - 出纳付款 - 结束。但用DFD来画你需要思考的是流程的起点是一张包含了员工信息、报销明细、金额的“原始报销单”数据流。这个数据流进入“提交报销”这个处理过程输出的是一个“待审批的报销申请”数据流。这个新的数据流流入“部门经理审批”处理过程经理的“审批意见”另一个数据流作为输入处理后会输出一个“已审批的报销申请”可能附加了审批状态和意见。同时这个过程中可能还会产生一个“审批记录”数据存储。你看DFD让你清晰地看到了数据的“变形记”而不仅仅是动作的接力赛。2. DFD的四大核心元素不是图形是建模思想要画好DFD绝不能停留在死记硬背几个图形符号上。你必须理解每个符号背后所代表的建模思想。DFD的核心元素有四个外部实体、处理过程、数据流和数据存储。每一个都有其严格的语义用错了图就失去了意义。2.1 外部实体系统的边界在哪里外部实体External Entity代表的是与系统交互但系统不对其进行改变的人、组织或外部系统。它位于我们正在分析的目标系统的边界之外。在图中通常用正方形或矩形表示有些规范用矩形内部写上角色名如“客户”、“供应商系统”。这里最容易犯的错误是混淆“外部实体”和“内部处理”。比如在分析一个“电商订单系统”时“顾客”肯定是外部实体因为系统记录顾客信息但并不管理顾客的生老病死。但“库存管理系统”呢这取决于你的系统边界。如果你画的是整个公司级的“电商平台DFD”那么“库存管理系统”可能是一个内部的处理过程或数据存储。但如果你画的是专注于“订单处理”的子系统的DFD那么“库存管理系统”就是一个需要交互的外部实体。所以在画第一张DFD之前必须明确且唯一地定义你的系统边界这是所有分析的起点。注意数据流只能在处理过程与外部实体、处理过程与数据存储、或两个处理过程之间流动。外部实体之间不能直接有数据流因为它们之间的交互不经过我们定义的系统不属于系统分析的范畴。2.2 处理过程数据的“加工厂”处理过程Process是DFD的核心代表了对输入数据流进行变换以产生输出数据流的功能或活动。它通常用一个圆角矩形或圆形表示内部需要有一个动宾短语的名称如“验证订单”、“计算运费”、“生成报表”。这个名称必须明确表达“做什么”而不是“是什么”如“订单验证模块”就是一个坏名字。处理过程的编号规则体现了DFD的层次性。顶层图的处理过程就是整个系统编号为“0”。将其分解后得到一级DFD其中的处理过程编号为“1”、“2”、“3”… 将处理过程“1”再分解得到二级DFD其内部的过程编号则为“1.1”、“1.2”、“1.3”… 依此类推。一个处理过程必须有输入也有输出因为它的使命就是变换数据。如果一个处理过程只有输入没有输出那它就是个“黑洞”如果只有输出没有输入那它就是个“神迹”在现实系统中都不合理。2.3 数据流数据的“高速公路”数据流Data Flow代表了数据在系统内部的移动路径用带箭头的线段表示。箭头方向即数据流向。数据流上必须标注其承载的数据内容名称通常是名词或名词短语如“客户订单”、“库存查询请求”、“付款确认通知”。这里的关键细节在于数据流的内容必须足够具体且与前后环节匹配。比如从“顾客”到“提交订单”处理过程的数据流应该叫“订单信息”包含商品ID、数量、收货地址等而不是笼统地叫“数据”或“请求”。同时要理解“打包”和“拆分”的概念。一个数据流可以是一个包含了多个字段的数据包如“员工信息”包含姓名、工号、部门也可以是一个单一的数据项。但一个数据流不能代表多个毫无关联的数据集合。2.4 数据存储数据的“仓库”数据存储Data Store代表系统内需要持久化保存的数据集合可以理解为数据库中的表、文件系统中的一个文件或者一个缓存区。通常用两条平行线或一个缺少右边线的矩形表示。数据存储必须有一个名词性名称如“客户档案”、“订单表”、“库存记录”。数据存储与处理过程之间的数据流方向揭示了数据的存取操作指向数据存储的箭头写入代表创建、更新或删除数据如“更新库存”。从数据存储指出的箭头读取代表查询、检索数据如“读取产品信息”。双向箭头代表在同一处理过程中既读取又更新该数据存储。一个常见的误区是把数据存储当成一个主动的“处理过程”。数据存储是被动的它不会主动发送数据只有在被处理过程“读取”时数据才会流出。3. 绘制DFD的实战心法从顶层上下文图到逐级分解掌握了基本元素就像拿到了乐高积木的零件。但要搭出正确的模型必须遵循科学的构建方法。DFD的绘制是一个自顶向下、逐层精化的过程。3.1 Level 0上下文图——划定战场范围上下文图Context Diagram是最高层次的DFD也称为Level 0 DFD。它的核心任务只有两个定义唯一的系统边界将整个待分析的系统视为一个大的处理过程编号为“0”并给它起一个能概括其核心功能的名称如“在线零售系统”。识别所有外部实体及主要数据流找出所有与这个“大系统”交互的外部实体并画出它们与系统之间进出的关键数据流。上下文图必须保持极度简洁。它只有一个处理过程即系统本身不显示任何内部的数据存储和处理细节。它的价值在于让项目干系人尤其是非技术的业务方在5秒内就达成共识我们这个项目/系统到底要和哪些外部对象打交道交换哪些最基本的东西。这是避免后期范围蔓延的第一道防线。3.2 Level 1一级细化图——勾勒核心骨架将上下文图中那个唯一的“0”号处理过程进行分解就得到了一级DFDLevel 1 DFD。这一步的目标是揭示系统内部的**主要功能模块处理过程**以及它们之间、它们与外部实体、它们与核心数据存储之间的数据流动关系。在这一层你需要识别出3到7个主要的高层处理过程。心理学研究表明人脑一次性处理7±2个概念比较舒适超过这个数就会显得杂乱。例如对于一个订单系统主要过程可能是“订单录入”、“库存检查”、“支付处理”、“发货安排”。引入系统内部的关键数据存储。比如“产品目录”、“客户数据库”、“订单库”。保持数据流的平衡。上下文图中进出系统的每一个数据流都必须在一级DFD中找到其来源或去向。例如上下文图中顾客输入的“订单信息”在一级DFD中必须流入某个处理过程如“订单录入”。3.3 Level 2及以下逐级分解——深入肌理细节如果一级DFD中的某个处理过程仍然比较复杂内部包含了多个逻辑步骤就需要对它进行进一步分解产生二级Level 2、三级Level 3DFD。这就是“逐层精化”。例如将一级DFD中的“支付处理”过程编号2进行分解2.1 验证支付信息输入“支付请求”输出“已验证的支付信息”或“验证失败消息”。2.2 调用支付网关输入“已验证的支付信息”输出“支付网关响应”。2.3 更新订单状态根据响应向“订单库”写入支付状态。分解的原则也是容易踩坑的地方输入/输出平衡原则子图下级DFD的输入流和输出流必须与父图中对应处理过程的输入输出完全匹配。子图可以展示这些数据流在内部是如何被使用和产生的但不能无中生有也不能让父图中定义的输入输出在子图中消失。编号一致性原则子图中的处理过程编号必须继承父过程编号。如父过程是“3”则其子图中的过程编号为“3.1”“3.2”等。到功能为止原则分解到什么程度停止一个经验法则是当一个处理过程可以用一段简单的、明确的程序逻辑或一个函数/方法来实现时就可以停止分解了。例如分解到“计算折扣金额”这种一个公式就能说清的过程就无需再分解为“读取折扣率”、“计算原价金额”、“相乘”等步骤。4. 高级技巧与常见“坑点”诊断画了几十张DFD后你会发现比画图更难的是判断一张图画得“对不对”、“好不好”。下面分享一些高阶心法和典型错误。4.1 数据存储的“幽灵读写”与“黑洞过程”幽灵读写一个数据存储只有流入或只有流出的数据流。例如一个“日志记录”数据存储只有从各个处理过程写入日志的流入箭头却没有一个处理过程去读取它。这虽然在物理上可能日志用于日后审计平时不读但在逻辑DFD中这暗示该数据存储可能不是当前系统功能的核心或者你遗漏了一个“查看系统日志”的功能。反之如果一个“用户配置”数据存储只有读取流那它的数据是从哪来的是不是漏了一个“管理用户配置”的过程黑洞过程一个处理过程只有输入数据流没有输出数据流。比如你画了一个“处理错误”的过程只有“错误信息”流入。那么处理完之后呢错误信息被吞掉了实际上它至少应该输出一个“错误日志”写入数据存储或者“错误提示”流向外部实体或另一个过程。4.2 数据流命名的“艺术”数据流名称是DFD可读性的关键。坏的名字如“数据”、“信息”、“结果”好的名字如“带有折扣码的订单申请”、“库存不足告警信号”。技巧想象你是一个快递员数据流就是你运送的包裹。包裹上必须贴有清晰的标签告诉下一个处理环节“这里面是什么”。这个标签数据流名要尽可能具体。实战案例在画“用户登录”时从外部实体“用户”到处理过程“验证凭证”的数据流不应该叫“登录数据”而应该叫“用户名和密码”。从“验证凭证”到数据存储“用户表”的数据流如果是查询可以叫“用户查询条件”如果是验证成功后更新最后登录时间则可以叫“用户登录状态更新信息”。4.3 逻辑DFD vs. 物理DFD切勿混淆的视角这是另一个关键概念。我们上面讨论的一直是逻辑DFDLogical DFD。它只关心业务功能和数据逻辑不关心技术实现。图中的“数据存储”代表逻辑上的数据集合而不是具体的MySQL表或Redis缓存“处理过程”代表业务功能而不是具体的Java类或微服务。而物理DFDPhysical DFD则展示了系统是如何在物理上实现的。它会包含“Web服务器”、“数据库服务器”、“消息队列”、“打印模块”等物理实体数据流会具体到“HTTP请求”、“JDBC连接”、“Kafka消息”。核心原则先画逻辑DFD再推导物理DFD。逻辑DFD是稳定的它描述业务本质不随技术变迁而大变。物理DFD是易变的它依赖于当前的技术选型。很多设计混乱源于一开始就陷入了物理细节的争论“这个功能是用一个服务还是两个服务”而忽略了业务数据流的本质。5. 在现代系统分析中的应用与工具实践你可能觉得DFD是结构化分析时代的“老古董”在敏捷和微服务时代过时了。恰恰相反它的核心思想——以数据流为中心定义系统边界和模块职责——在当今更加重要。5.1 DFD在微服务边界划分中的价值微服务设计的关键难点之一是服务的拆分边界。拍脑袋拆分的结果就是“分布式单体”服务间耦合严重。DFD可以作为一个强大的分析工具绘制当前单体系统的逻辑DFD理解核心的数据流和处理过程。寻找高内聚、低耦合的切割点观察DFD那些数据流密集、与外部交互简单的一组处理过程往往可以成为一个候选的微服务。例如系统中所有与“支付”相关的处理过程支付验证、执行、对账、退款以及它们紧密关联的“支付交易记录”数据存储自然构成了一个“支付服务”的边界。定义服务接口原来在DFD内部的数据流在微服务拆分后就变成了服务间的API调用或消息传递。DFD清晰地定义了这些接口需要传输的数据内容。5.2 实用工具推荐与绘图规范虽然用纸笔或任何绘图工具都能画DFD但使用专业工具能提升效率和规范性。Draw.io / diagrams.net免费、开源、在线功能强大有专门的DFD图形库非常适合个人和团队快速协作。是我目前最常用的工具。Microsoft Visio老牌工具模板丰富适合企业环境与Office套件集成好但需要付费。Lucidchart优秀的在线协作图表工具体验流畅团队功能强同样需要订阅。绘图规范建议保持整洁避免连线交叉可以使用“弯曲点”来调整连线路径。使用图例在图纸角落说明使用的符号体系如矩形外部实体圆角矩形过程。分层管理对于复杂的多级DFD利用工具的“图层”或“页面”功能将不同层级的图分开存放并通过超链接关联保持清晰。版本控制将DFD文件纳入Git等版本控制系统跟踪其随着需求演化的变更历史。5.3 从DFD到其他设计产物的桥梁DFD不是分析的终点而是多个后续设计活动的跳板数据字典DFD中出现的每一个数据流、数据存储其内部的具体数据结构字段、类型、约束都需要在数据字典中详细定义。这是数据库设计的基础。处理过程说明对于底层、不再分解的处理过程需要用结构化语言如伪代码、决策表或决策树来描述其具体的处理逻辑。状态迁移图对于某些核心的数据存储如“订单”其状态待支付、已支付、已发货等的变化可以结合DFD中相关的处理过程用状态迁移图来进一步细化描述。画DFD的过程是一个不断向业务和自身认知提问的过程“这个数据从哪来”“经过这个处理它到底变成了什么”“这个数据存储真的需要吗”这个过程本身的价值往往大于最终产出的那张图。它迫使你剥离技术的表象直击业务的本质数据关系这是构建一个清晰、健壮、可持续演进系统的根本。下次当你开始一个新项目或分析一个复杂功能时不妨先别急着写代码或画原型拿起笔从一张上下文图开始问问自己“这个系统的数据到底是怎么流的”
返回列表