3. 需求分析:功能需求与非功能需求、业务规则梳理、数据流图绘制、状态机建模
好,咱们进入第三章。这一章可以说是整个需求分析环节的「硬核」部分。很多新手写文档,容易把需求写得像「用户故事」一样松散。但真正的软件规格文档,必须把功能、非功能、规则、流程、状态这五样东西,像搭积木一样严丝合缝地拼起来。
我个人习惯,拿到一个需求后,先不急着写文档。我会先问自己三个问题:系统要做什么?做到什么程度?不能做什么? 这三个问题回答清楚了,后面的工作才有根基。
3.1 功能需求与非功能需求:一个都不能少
先说功能需求。说白了,就是「用户能用系统干什么」。比如登录、下单、导出报表。这些是显性的,客户通常能说清楚。
但非功能需求就麻烦了。客户往往说不出来,或者觉得「这还用说?」。比如系统响应时间、并发用户数、数据安全性。我在项目中遇到过,客户验收时突然说「怎么这么慢?」——结果一看,当初根本没约定响应时间。嗯,这就是非功能需求没写清楚的后果。
核心区别:
- 功能需求:系统「做什么」—— 动词 + 名词(如:用户提交订单)
- 非功能需求:系统「做得怎么样」—— 度量 + 约束(如:订单提交响应时间 < 2秒)
我建议,写非功能需求时,一定要带上可量化的指标。别写「系统要快」,要写「在100并发下,平均响应时间不超过1.5秒」。你想想看,没有数字的约束,开发人员怎么落地?测试人员怎么验收?
| 需求类型 | 示例(错误) | 示例(正确) |
|---|---|---|
| 功能需求 | 用户能查看订单 | 用户可按订单号、日期范围、状态筛选订单列表 |
| 非功能需求 | 系统要安全 | 用户密码需加密存储(SHA-256),传输使用HTTPS |
| 非功能需求 | 系统要稳定 | 系统可用性 ≥ 99.9%,年宕机时间不超过8.76小时 |
我的小技巧: 写非功能需求时,可以对照一个检查清单——性能、安全、可用性、可维护性、可扩展性、兼容性。每项至少写一条,这样基本不会漏。
3.2 业务规则梳理:藏在流程里的「潜规则」
业务规则,是需求文档里最容易「打架」的地方。为什么?因为业务规则往往是「例外情况」。正常流程大家都懂,但「如果用户余额不足怎么办?」「如果商品库存为0怎么办?」——这些才是真正的坑。
我曾经在一个电商项目中,因为没写清楚「优惠券和满减能否叠加使用」,导致开发做了两版逻辑,最后上线前才发现冲突。嗯,那次教训挺深刻的。
梳理业务规则,我推荐用决策表或规则矩阵。把条件列出来,把结果列出来,一目了然。
举个例子,一个简单的「订单取消规则」:
| 条件 | 规则1 | 规则2 | 规则3 |
|---|---|---|---|
| 订单状态 = 待支付 | 是 | 否 | 否 |
| 订单状态 = 已发货 | 否 | 是 | 否 |
| 距离下单时间 < 30分钟 | — | — | 是 |
| 结果:允许取消 | 是 | 否 | 是(需审核) |
你看,三行规则就把所有情况覆盖了。开发看到这个,直接写if-else就行,不会产生歧义。
注意: 业务规则一定要和业务方逐条确认。别自己脑补。我曾经见过一个团队,把「会员折扣」规则写错了,结果上线后所有订单都打了8折,公司亏了一周才发现。
3.3 数据流图绘制:让数据「流动」起来
数据流图(DFD),说白了就是画清楚「数据从哪里来,到哪里去,经过谁处理」。很多分析师觉得这玩意儿过时了,但我认为它依然是沟通利器。为什么?因为它不涉及具体技术,业务人员也能看懂。
画DFD,我习惯分两层:
- 上下文图(顶层):只画一个系统框,外面是外部实体(用户、第三方系统),箭头表示数据流向。这张图用来和客户确认「系统边界」。
- 0层图:把系统框拆成几个主要功能模块,画出模块间的数据流动。这张图给开发看,让他们理解模块依赖。
举个例子,一个「在线书店」的上下文图:
+----------------+ +------------------+ +----------------+
| 顾客(外部) | ----> | 在线书店系统 | ----> | 支付网关 |
| (提交订单) | | (处理订单) | | (扣款) |
+----------------+ +------------------+ +----------------+
^ |
| v
| +----------------+
+-----------------| 库存系统 |
(查询库存) | (更新库存) |
+----------------+
画图时,记住四个要素:外部实体、处理过程、数据存储、数据流。箭头方向别画反了,数据流是「数据在移动」,不是「控制流」。
我的经验: 画DFD时,尽量用工具(如Draw.io、Visio),别手画。手画改起来太痛苦了。而且,每张图一定要配上文字说明,解释每个数据流的含义。光看图,别人可能猜错。
3.4 状态机建模:把「状态变化」管起来
状态机,是处理「有状态」业务的神器。比如订单、工单、审批流程——这些对象都有明确的生命周期。状态机建模,就是画出状态、事件、转移这三者的关系。
我见过最惨的案例:一个工单系统,没有状态机,开发用一堆if-else硬写。结果后来加了「重新打开」功能,所有if-else都要改,改完又引入一堆bug。嗯,这就是没建模的代价。
状态机通常用状态转移图或状态表来表示。我推荐两者都用:图给业务看,表给开发看。
一个「订单」的简化状态机:
[待支付] --(支付成功)--> [已支付] --(发货)--> [已发货] --(确认收货)--> [已完成]
| |
+--(取消)--> [已取消] +--(退款)--> [退款中] --(退款完成)--> [已退款]
对应的状态表:
| 当前状态 | 事件 | 下一状态 | 前置条件 |
|---|---|---|---|
| 待支付 | 支付成功 | 已支付 | 支付金额 = 订单金额 |
| 待支付 | 取消 | 已取消 | 无 |
| 已支付 | 发货 | 已发货 | 库存充足 |
| 已支付 | 退款 | 退款中 | 未发货 |
| 已发货 | 确认收货 | 已完成 | 无 |
| 退款中 | 退款完成 | 已退款 | 退款处理成功 |
避坑指南: 我曾经漏掉了一个「超时未支付自动取消」的状态转移。结果上线后,大量待支付订单堆积,数据库都快炸了。所以,状态机一定要覆盖所有「时间触发」的事件,比如超时、定时任务。
好了,这一章的内容就这些。总结一下:功能需求和非功能需求要分开写,业务规则用决策表梳理,数据流图画清楚数据走向,状态机把生命周期管住。这四样东西写好了,你的需求文档就有了「骨架」。下一章,咱们聊聊如何把这些内容组织成一份完整的文档结构。