4、结构化分析方法:数据流图(DFD)的绘制、数据字典的构建、加工说明
好,咱们进入第四章。这一章讲的是结构化分析,说白了就是一套把复杂需求「拆碎」的方法论。我个人觉得,这是整个需求分解环节里最「硬核」的部分,也是我当年从程序员转型做架构时,第一个啃下来的硬骨头。
结构化分析的核心就三样东西:数据流图(DFD)、数据字典、加工说明。这三者缺一不可,就像三脚架,少一条腿都站不稳。咱们一个一个说。
4.1 数据流图(DFD)的绘制
数据流图,英文叫 Data Flow Diagram,简称 DFD。它不关心控制逻辑,不关心谁先谁后,只关心一件事:数据从哪里来,经过什么处理,最后到哪里去。
我在项目中遇到过不少新手,一上来就画流程图,结果画着画着就变成了「程序逻辑图」。嗯,这里要注意:DFD 不是流程图,它不画判断分支,不画循环。它只画数据流动的管道。
4.1.1 DFD 的基本符号
DFD 的符号其实很简单,就四种图形。我习惯用 Yourdon 和 DeMarco 的表示法,因为最直观:
| 符号 | 名称 | 含义 |
|---|---|---|
| 圆形或椭圆 | 加工(Process) | 对数据进行变换或处理 |
| 矩形 | 外部实体(External Entity) | 系统之外的人或系统,数据的来源或终点 |
| 箭头 | 数据流(Data Flow) | 数据在加工之间、实体之间的流动方向 |
| 双横线(或开口矩形) | 数据存储(Data Store) | 数据停留的地方,比如数据库、文件 |
你想想看,这四种符号就能描述一个完整的业务系统。是不是很神奇?
4.1.2 分层绘制的原则
DFD 不是一张图画到底的。它要分层。我见过最糟糕的 DFD,一张 A0 纸上密密麻麻画了上百个加工,谁也看不懂。正确的做法是「由外向内,逐层分解」。
一般分三层:
- 顶层图(上下文图):只画一个加工,代表整个系统。外部实体和这个加工之间的数据流,就是系统的输入和输出。
- 中层图(0层图):把顶层那个加工拆成 3-7 个主要加工,画出它们之间的数据流。
- 底层图(子图):对中层图的每个加工继续分解,直到每个加工都足够简单,可以用一段结构化语言描述清楚。
核心原则:每个加工在父图中有一个编号,在子图中被分解后,子图的编号就是父图编号加小数点。比如父图加工编号是 3,子图就是 3.1、3.2、3.3…… 这样一层层下去,不会乱。
我曾经在一个银行项目中,因为没遵守这个编号规则,导致后期需求变更时,根本找不到对应的加工在哪一层。那次教训让我养成了一个习惯:画 DFD 之前,先把编号体系定好。
4.1.3 绘制 DFD 的避坑指南
我曾经踩过几个坑,分享给你:
- 坑一:数据流和控制流混在一起。 DFD 只画数据流,不画控制流。比如「如果余额不足则拒绝交易」——这个「如果」是控制逻辑,不要画在 DFD 上。DFD 上只画「交易请求」和「交易结果」这两个数据流。
- 坑二:数据流没有命名。 每个箭头都必须有名字,比如「订单信息」「支付结果」。不能只画一条线,什么都不写。
- 坑三:加工没有输入输出。 每个加工至少有一个输入数据流和一个输出数据流。如果一个加工只有输入没有输出,或者只有输出没有输入,那它要么是多余的,要么是画错了。
4.2 数据字典的构建
DFD 画完了,但光有图还不够。图上的每个数据流、每个数据存储、每个加工,都需要在数据字典里给出精确的定义。说白了,数据字典就是 DFD 的「说明书」。
数据字典里要记录什么?我一般要求团队至少包含以下内容:
- 数据流条目:数据流的名称、别名、组成(由哪些数据项构成)、来源、去向、数据量。
- 数据存储条目:存储的名称、组成、组织方式(比如按主键索引)、存取频率。
- 数据项条目:最小的数据单元,比如「客户姓名」「订单金额」。要定义它的类型、长度、取值范围。
举个例子,一个「订单信息」数据流的字典条目可能是这样的:
数据流名:订单信息
别名:OrderInfo
组成:订单编号 + 客户编号 + 商品编号 + 数量 + 总金额 + 下单时间
来源:外部实体「客户」
去向:加工 2「订单处理」
数据量:日均 5000 条
我的个人习惯:数据字典最好用工具来维护,比如 Excel 或者专门的 CASE 工具。别用手写,也别用 Word 文档。因为需求一变,数据字典的更新频率很高,手写根本跟不上。
4.3 加工说明:结构化语言、决策表
DFD 里的每个加工,最终都要用文字说清楚它到底做了什么。这就是加工说明。加工说明有三种主流方式:结构化语言、决策表、决策树。这里我重点讲前两种,因为最常用。
4.3.1 结构化语言
结构化语言,说白了就是「用编程语言的逻辑结构,加上自然语言的描述」。它不像伪代码那么精确,也不像自然语言那么随意。它介于两者之间。
结构化语言只用三种结构:顺序、选择、循环。举个例子:
加工编号:3.2
加工名称:计算订单总金额
过程:
1. 读取订单明细列表
2. 初始化总金额 = 0
3. 对每一条订单明细,执行:
3.1 计算小计 = 单价 × 数量
3.2 总金额 = 总金额 + 小计
4. 如果总金额 >= 100 元,则:
4.1 应用满减优惠,总金额 = 总金额 - 10
5. 返回总金额
你看,这里用了顺序(1→2→3→4→5)、循环(对每一条...)、选择(如果...则...)。逻辑清晰,业务人员也能看懂。
注意:结构化语言不要写得太像代码。不要出现变量声明、函数调用、指针操作。它的读者是业务分析师和客户,不是程序员。我见过有人把结构化语言写成了 C 语言,结果客户完全看不懂,需求评审会开成了编程培训课。
4.3.2 决策表
当加工的逻辑涉及多个条件、多个结果时,结构化语言就有点力不从心了。这时候,决策表是更好的选择。
决策表长什么样?我直接给你看一个例子。假设一个「审批贷款」的加工,有三个条件:信用评分、收入水平、是否有抵押物。结果有两种:批准、拒绝。
| 条件/动作 | 规则1 | 规则2 | 规则3 | 规则4 | 规则5 |
|---|---|---|---|---|---|
| 信用评分 >= 700 | Y | Y | N | N | N |
| 收入 >= 5000 | Y | N | Y | N | Y |
| 有抵押物 | - | Y | Y | Y | N |
| 批准贷款 | ✓ | ✓ | ✓ | ✓ | ✗ |
| 拒绝贷款 | ✓ |
你看,决策表把所有的条件组合都列出来了。规则5就是典型的「三无」情况——信用低、收入低、没抵押物,直接拒绝。规则1到规则4,只要满足任意一种组合,都批准。
为什么会这样?因为决策表能保证逻辑的完备性。你用结构化语言写,很容易漏掉某个条件组合。但决策表是穷举的,所有组合都在表里,一个都跑不掉。
我个人习惯是:条件不超过 4 个时用决策表,超过 4 个时先考虑能不能合并条件,实在不行再用决策树。因为条件太多,决策表的行数会爆炸(2 的 n 次方)。
4.4 三者如何配合
最后,我总结一下这三者的关系:
- DFD 告诉你系统有哪些加工、数据怎么流动——这是骨架。
- 数据字典 告诉你每个数据流、每个存储长什么样——这是血肉。
- 加工说明 告诉你每个加工内部怎么干活——这是灵魂。
三者缺一不可。我在做需求评审时,如果发现团队只画了 DFD 但没有数据字典,或者只有加工说明但没有 DFD,我会直接打回。因为这样的需求文档,根本没法落地。
好,这一章就到这里。下一章我们讲「面向对象分析方法:用例图与类图的绘制」,那是另一种完全不同的思维方式。咱们到时候见。