1 基本概念与元素

数据流图由四种基本元素构成,它们共同构建了系统逻辑模型的核心骨架。这些元素各自承载特定语义,通过组合与连接,描述数据在系统中的动态行为。

1.1 数据流

数据流(Data Flow)是系统内部数据传输的路径,用带箭头的线段表示。它承载着一定结构的数据,从一个“节点”(加工、数据存储或外部实体)流向另一个“节点”。数据流必须在两端标注命名,以说明所传递数据的业务含义,例如“顾客订单”“库存查询请求”。一个数据流不可命名过于抽象(如“信息”),也不应未标注而留白,否则易导致语义模糊。数据流的方向指示数据的迁移路径,但并不意味着物理上的“发送”细节,它仅关注谁向谁传递了什么。

1.2 加工(计算节点)

加工(Processing,或称功能节点)是数据流图的核心活动单元,用圆形或圆角矩形表示。它接收输入数据流,执行特定的转换逻辑,然后产生输出数据流。每个加工都应有一个简洁、精确的命名,格式通常为“动词+宾语”,例如“验证密码”“计算折扣”“更新库存”。加工体现了“做什么”,而不是“怎么做”,因此其内部实现细节不在DFD中描述。一个加工可视为系统功能分解的最小处理单元,在层次化建模中会被进一步细化。

1.3 数据存储

数据存储(Data Store)用于表示数据在系统内部的“暂存位置”,如数据库表、文件或缓冲区。它用双线或开口矩形表示,并赋予一个有意义的名词命名,例如“用户表”“订单队列”。数据流可以指向数据存储(表示写入/更新操作),也可以从数据存储引出(表示读取/查询操作)。数据存储不涉及存储介质、索引或具体数据结构,只关心数据在逻辑上的组织与访问。同一个数据存储可能出现在多个加工之间,作为数据共享的“中转站”。

1.4 外部实体

外部实体(External Entity)是系统边界外的人、组织或系统,用矩形表示,并标注实体名称,如“顾客”“银行系统”“管理员”。外部实体与系统发生数据交互,但本身不属于系统的部分。它们提供了系统的输入数据,或接收系统的输出数据。外部实体是DFD层次化建模的起点和终点:在顶层图中,系统唯一与外部实体直接交互;在底层图中,加工不再与外部实体直接连接,而是通过父图传递的数据流实现交互。

2 层次化建模

数据流图采用“自顶向下,逐层细化”的层次化建模策略,将一个复杂的系统分解为若干层次,每层描述不同粒度的处理细节。这种结构类似于金字塔:顶层最抽象,底层最具体。

2.1 顶层图(上下文图)

顶层图,又称上下文图(Context Diagram),是整个系统最高层次的DFD表示。它只包含一个加工节点(代表整个系统),以及所有与此系统直接交互的外部实体。系统的所有输入数据流从外部实体指向系统,所有输出数据流从系统指向外部实体。上下文图的作用在于界定系统的“边界”,回答“系统做什么事,与世界如何连接”的问题。它通常不包含数据存储,因为数据存储属于系统内部逻辑。

2.2 中层图(0层图)

0层图是上下文图的第一个细化层次。它将系统的单一加工分解为若干子加工,并引入中间数据存储,同时保留与外部的输入输出边界。一个0层图通常包含3至7个加工,每个加工对应系统的一个主要功能模块或业务流程。0层图必须保持与上下文图一致的输入输出流集,这一约束被称为“平衡”。

2.2.1 父图与子图的平衡

父图(如上下文图)与子图(如0层图)之间必须满足“数据流平衡”原则:父图中一个加工的输入输出流,在子图中必须全部被保留,且方向、命名完全一致。例如,若父图中的“顾客订单”流入系统加工,那么在0层图中,同样必须存在一条从边界引向某个子加工(或经过数据存储)的“顾客订单”流。若子图新增了数据流,则必须说明其来源和去向,否则视为“不平衡”。平衡检查是DFD建模中的重要质量保障手段。

2.3 底层图(细化图)

底层图是对某个上层加工的进一步分解,直至每个加工都达到“足够简单”的程度。底层图的粒度取决于系统的复杂度和建模目的。例如,一个“验证密码”加工,若其内部只有简单的查表比对,可以保留为一个原子加工;若包含多次校验和日志记录,则可展开为子图。底层图通常对应程序中的一段独立功能模块或一个子程序。

2.3.1 最小加工粒度原则

最小加工粒度原则是指,一个加工应细分到“其逻辑可以不再分解,且具有明确的单一功能”为止。通常的判断标准是:该加工若用自然语言或伪代码描述时,不超过三至五条动作。过于细碎的分层(如将一个“加法”拆出三个子加工)会增加图件数量而无实质收益。实际操作中,建议每个底层图的加工数控制在5±2个,以保证可读性

3 绘制规范与步骤

数据流图的绘制需要依据公认的符号和规则,以确保团队成员之间的一致性理解。以下介绍两种主流的符号体系以及通用的绘制步骤。

3.1 符号体系

3.1.1 Yourdon/DeMarco符号

Yourdon和DeMarco提出的符号体系使用圆形(或圆角矩形)代表加工,双横线(或开口矩形)代表数据存储,矩形代表外部实体,箭头代表数据流。该体系强调简洁和直观,是学术界和早期结构化分析中的标准。其特点包括:加工编号采用数字层次(如2.1.3),数据存储名称首字母大写,以及数据流必须标注方向。

3.1.2 Gane/Sarson符号

Gane和Sarson的符号体系在工业界更常见。它使用矩形(左上角切角)表示加工,左开口矩形表示数据存储,矩形(圆角)表示外部实体,箭头表示数据流。两种体系在语义上完全等价,仅图形不同。Gane/Sarson体系更偏“工程化”,常配合系统设计文档使用。选择哪种体系取决于团队习惯,但需在同一项目中保持统一。

3.2 常见规则

3.2.1 数据流命名与方向

每条数据流必须有一个唯一的、有意义的名称,通常使用名词短语。数据流名称应与数据内容保持一致,例如“订单细节”而不是“信息”。数据流的方向必须明确,不应出现双向数据流(若需要双向交互,应拆分为两条独立的数据流)。数据流不能“交叉”,若必须交叉,可使用“跳线”(如U形曲线)来避免混淆。

3.2.2 加工编号规则

每个加工必须具有唯一的数字编号,以反映其层次关系。常见规则包括:“1”表示上下文图中的系统加工;“1.1”“1.2”表示0层图中的子加工;“1.1.1”“1.1.2”表示更细的子加工。编号应简洁,避免过长(如1.1.1.1.1),且在同一张图中不重复。编号仅用于定位,不代表执行顺序或优先级。

3.3 绘制流程

3.3.1 识别外部实体

首先明确系统的边界外所有交互者:用户、第三方系统、设备、与其他系统等。列出它们与系统之间的数据交互(输入和输出)。此步通常通过需求收集和用例分析得出。例如,一个图书管理系统可能的外部实体包括“借阅者”“管理员”“图书供应商”。

3.3.2 确定顶层输入输出

根据外部实体列表,绘制上下文图:将所有外部实体置于图画四周,中央放置系统加工(通常命名为系统名称,如“图书管理系统”),然后用带箭头的线段连接所有输入输出流。每一条数据流都需要命名,例如“借阅请求”“归还通知”。

3.3.3 逐层分解加工

从上下文图出发,选择第一个加工进行分解:将其拆分为若干子加工,添加必要的数据存储,并确保子图与父图“平衡”。重复该过程直至每个加工都满足最小加工粒度。建议每次分解只处理一个加工,即“一次只拆一个”,避免同时分解多个加工导致结构混乱。每张子图应尽量控制在7个加工以内,并附加工编号。

4 应用场景

数据流图广泛应用于软件工程的多个阶段,帮助团队捕获、沟通、分析系统需求与设计。

4.1 需求分析阶段

4.1.1 功能建模

在需求分析初期,DFD被用于绘制系统的“功能蓝图”。分析师通过与用户访谈、阅读文档,首先识别外部实体和主要输入输出(上下文图),然后逐层细化(0层图、底层图),以明确系统必须提供的每一个功能及其数据依赖关系。这种建模方式避免了过早陷入算法界面细节。

4.1.2 与用户沟通验证

DFD的图形化和层次化特性使其成为与用户沟通的有效工具。用户无需理解编程细节,即可通过看数据流图判断“数据从哪里来”“到哪里去”“经过什么处理”。分析师常邀请用户“走读”数据流图,让用户指出遗漏或错误的数据流、加工或实体。

4.2 系统设计阶段

4.2.1 模块划分依据

DFD的层次化结构天然可作为系统模块分解的依据。例如,0层图中的每个加工可以映射为一个独立的子系统或程序模块;子加工可对应模块内的函数或过程。数据存储则对应数据库表或文件结构。通过DFD,设计人员能直观地确定模块之间的接口(数据流)和职责。

4.2.2 数据库接口设计

DFD中的每个数据存储都需要在数据库设计中落实。设计人员可根据数据存储的命名、输入输出流向,确定表的字段、索引和关系。例如,若一个数据存储同时被多个加工读写,则需考虑并发控制缓存机制。

4.3 逆向工程与文档化

面对遗留系统或缺乏文档的旧代码,开发团队可反向分析系统行为并绘制DFD。通过追踪代码执行路径、观察日志或讨论,逐一识别外部实体、加工和数据存储,最终形成系统逻辑模型。此类DFD可用于系统重构、迁移或维护的蓝图。对于新项目,DFD也常作为需求规格说明书的附录,帮助新成员快速理解系统整体。

5 衍生物与变体

经典DFD经过多年发展,衍生出一些针对特定需求的变体,以适应不同抽象层次或含控制逻辑的场景。

5.1 物理数据流图

物理数据流图(Physical DFD)关注“如何实现”系统的功能,而非“做什么”。它包含物理细节,如文件存储位置、程序模块名称、通信协议、界面形式等。例如,一个物理DFD中可能出现“MySQL数据库”“AJAX请求”“登录窗口”等与具体技术相关的标注。物理DFD通常用于系统设计后期或开发阶段,指导编码和部署。

5.2 逻辑数据流图

逻辑数据流图(Logical DFD)则保持抽象,只关注“什么功能”和“什么数据”,不涉及技术实现。它是需求分析阶段的首选工具,便于与业务人员沟通。逻辑DFD中,数据存储仅用“数据存储”表示,加工命名使用业务术语(如“校验订单”),不出现“XML解析”“REST调用”等技术词。在系统设计时,通常先构建逻辑DFD,再将其转化为物理DFD。

5.3 扩展DFD(含控制流)

经典DFD只处理数据流,但有些系统中存在“控制信号”或“事件触发”逻辑。扩展DFD(Extension DFD)引入控制流(Control Flow)和状态机,以描述系统行为的时序或条件。控制流用虚箭头表示,专门传递布尔值或事件信号,而非结构化数据。例如,一个“温度传感器”的DFD中,可以用控制流表示“温度超标”事件触发“报警加工”。扩展DFD通常与其他建模语言(如状态图、活动图)配合使用。不过,一些学者认为过度加入控制流会破坏DFD的简洁性,因此建议仅在必要时使用。

6 常见问题与技巧

绘制数据流图时常遇到歧义、复杂度膨胀或与其他图的混淆问题。以下提供一些实战应对技巧。

6.1 数据流歧义处理

数据流歧义主要源于命名不具区分性或流向不明确。解决方法是:每条数据流必须单独定义其数据结构,并在图中补充数据字典条目。例如,若两条名为“用户信息”的数据流流向不同加工,应在数据字典中说明两者的字段差异(如“用户信息(A)”包含姓名与密码,“用户信息(B)”仅包含用户名与年龄)。此外,数据流不应“穿越”跨层级的父图,以免丢失上下文。

6.2 复杂度控制

复杂系统的DFD层数可能很大,每层10+个加工,导致图件臃肿难读。控制复杂度的方法包括:减少0层图的加工数量(建议5±2个),避免孤立的“数据孤岛”,以及合理合并相似加工(如“生成报告A”和“生成报告B”可合并为“生成报告”)。另外,使用编号注释和颜色区分不同层次也有助于理解。

6.2.1 每个加工的输出/输入数量限制

一个加工不应该有过多输入或输出数据流,经验规律是:输入不超过3条、输出不超过3条,合计不超过6条。若超出,说明该加工承担职责过多,存在“上帝加工”风险。此时应将该加工拆分为多个子加工,或重新设计数据流结构。这一限制源于人类短期记忆的7±2原则,过多数据流会降低可读性与可维护性。

6.3 与用例图、流程图的区别

数据流图与用例图(Use Case Diagram)的功能层面重叠:两者都用于描述系统功能。但DFD更关注“数据的流向与转换”,倾向于结构化分析;用例图更关注“参与者与系统目标的交互”,倾向于面向对象或业务场景。DFD的一条数据流可能对应多个用例的执行路径。流程图(Flowchart)则描述算法的步骤次序,包含控制流(如分支、循环),而DFD不描述顺序,只描述数据依赖。简单来说:DFD是舞台地图(数据在哪、怎么走),流程图是剧本(故事如何一步步发生)。在项目实践中,三者常配合使用以覆盖不同视角。