跳到内容

第 6 卷 / 第 3 章 / 第 1 课

3.1 从问题陈述到可验证需求 ​

需求工作要让团队对问题、边界、优先级和验收方式形成可验证的共同理解。文档的长度并不能替它完成这件事。一个需求如果不能说明谁需要它、为什么需要、怎样判断完成,就还不足以指导实现。

先区分问题、需求与方案 ​

三句话看起来相近,所处层次却不同:

text
问题:报名高峰时,管理员要手工合并多个表格,容易重复录入。
需求:管理员能在报名截止后得到一份去重且可追溯的参赛名单。
方案:使用 Redis Set 保存报名者 ID。

前两句描述业务处境与期望能力,第三句已经选择技术。过早把方案写成需求,会让团队跳过替代方案,也很难判断方案是否真的解决了问题。

一页问题陈述 ​

在拆用户故事前,先写一页短说明:

项目要回答的问题
目标哪个结果需要改变?
利益相关者谁使用、运营、购买、审计或承受风险?
当前流程现在怎样完成,痛点在哪里?
系统边界本系统负责什么,不负责什么?
约束法规、期限、预算、既有系统和技术边界是什么?
成功信号上线后怎样知道问题得到改善?
未知项哪些假设仍需访谈、原型或实验验证?

“用户”只是利益相关者的一类。运维人员关心恢复和诊断,安全人员关心权限边界,财务人员关心结算可核对性;这些关注点都会形成需求。

用户故事是讨论入口,不是完整规格 ​

常见格式是:

text
作为 <角色>,我想要 <能力>,以便 <价值>。

例如:

text
作为参赛者,我想取消尚未截止的报名,以便在无法参赛时释放名额。

这张卡片只提供讨论索引。真正需要确认的内容包括:截止时间按哪个时区计算、取消后是否允许重新报名、费用怎样退回、管理员代取消是否留下审计记录。

技术工作也有价值,但不要勉强伪装成“作为系统,我想要……”。可以把数据库迁移、可观测性改造等作为工程任务,并链接到它支持的风险、质量属性或用户故事。

用示例消除歧义 ​

下面是可保存为 cancellation.feature 的 Gherkin 规格,使用英文关键字和中文步骤。它还需要 step definitions 与被测实现才能执行;单有场景文本不代表验收通过。Given–When–Then 用来描述可观察行为:

gherkin
Feature: 报名取消
  Scenario: 截止前取消已确认的报名
    Given 参赛者 A 有一条状态为 CONFIRMED 的报名
      And 赛事报名截止时间为 2026-08-10T18:00:00+08:00
      And 当前时间为 2026-08-10T17:59:00+08:00
    When 参赛者 A 取消报名
    Then 报名状态变为 CANCELLED
      And 赛事可用名额增加 1
      And 系统记录操作者、操作时间与原报名编号

还需要反例和边界:

  • 截止时刻本身是否允许取消;
  • 已取消的请求重试时返回成功还是冲突;
  • 退款失败时,报名状态与退款状态怎样组合;
  • 两个取消请求并发到达时,名额只能释放一次。

这些问题可以先形成一组待确认的选择,再补成场景:

条件示例约定
首次取消恰好发生在截止时刻拒绝;不释放名额
已成功取消后以同一幂等键重试返回原结果;名额总共只增加 1
两次取消并发至多一次完成状态转换和名额释放
取消成功但退款暂时失败报名保持 CANCELLED;退款进入可重试状态

首次操作的时间以服务端作出业务判定的时钟为准;测试注入固定时钟,不依赖墙上时间刚好走到某一秒。是否允许退款失败后保留取消结果,仍需业务方确认,不能由测试作者默默决定。

验收示例应描述外部可观察结果。若它断言某个私有方法调用了三次,测试已经越过需求边界进入实现细节。

功能需求之外:质量属性 ​

“系统要快、稳定、安全”无法验收。质量属性需要放进具体场景。SEI 常用六个要素描述质量属性场景:刺激源、刺激、环境、受影响对象、响应和响应度量。

下面是一个待利益相关者确认的示例,数字不是通用标准:

要素示例
刺激源已登录观众
刺激请求当前积分榜
环境决赛直播期间,3,000 个并发会话
对象排名查询接口及其依赖
响应返回不超过 5 秒前的排名快照
度量5 分钟窗口内 p95 延迟低于 300 ms,成功率不低于 99.9%

3000 个会话没有说明每秒请求数。还可约定持续 5 分钟、每秒发起 1500 次查询,并固定数据规模、请求分布和超时;这组假设共发起 450000 次请求。延迟从客户端发起到接收完整响应计时,超时和拒绝也计入请求总体及失败数;新鲜度超过 5 秒的响应不能只因 HTTP 成功就算合格。不要只拿缓存命中的成功样本作图。

度量必须说明统计窗口和负载条件。只有“平均延迟 100 ms”会掩盖尾延迟,也没有说明在什么流量下成立。

常见质量属性还包括可用性、可修改性、安全性、可测试性、可观测性和成本。它们经常互相牵制:更强一致性可能增加延迟,更细审计会增加存储与隐私治理成本。需求阶段要暴露权衡,不是许诺所有指标同时最大化。

约束、偏好与假设不要混写 ​

text
约束:支付数据必须留在指定区域。
偏好:团队熟悉 PostgreSQL,希望优先复用。
假设:首年峰值写入不超过每秒 200 次。

约束通常不能绕开;偏好可以在收益足够时改变;假设需要验证并设置复审触发条件。把三者都写成“必须”,会制造没有依据的架构限制。

建立领域词汇表 ​

如果“比赛”“场次”“报名”“参赛资格”在产品、代码和数据库中各有不同含义,图画得再精美也无法消除误解。词汇表至少记录:

text
Tournament(赛事):一次有报名窗口和赛程的竞赛活动。
Match(对局):赛事内两名参赛者的一次对战。
Registration(报名):参赛者申请参加某赛事的记录。
Eligibility(参赛资格):允许报名必须满足的规则集合。

词汇不是一次性文档。需求、API、事件和监控指标应尽量使用同一语言;含义变化时记录变更影响。

从需求到可追踪交付 ​

一个轻量追踪链可以是:

text
业务目标
  -> 用户故事 / 质量属性场景
    -> 验收示例
      -> 架构决策与接口契约
        -> 实现、测试和运行指标

追踪的目的不是给每一行代码编号,而是在需求变化或生产指标失守时,能找到受影响的决策与验证手段。

进入架构设计前的最小产物 ​

  • 一页问题陈述与明确的系统边界;
  • 利益相关者及其关键关注点;
  • 排过优先级的用户故事和验收示例;
  • 可度量的关键质量属性场景;
  • 约束、偏好、假设及验证计划;
  • 领域词汇表和仍未解决的问题。

这些内容不会消除变化,但会让变化可见。下一节据此选择架构视图,并记录真正影响系统结构的决策。

参考资料 ​

Built with VitePress | Software Systems Atlas