1.2 用户故事与用例

一句话

用户故事用一句话锁住 “谁、要什么、为什么”,细节交给对话;用例用一张流程表锁住 “谁、按什么步骤、出什么岔子”,异常交给分支。

一张表看清两者的分工

维度 用户故事(User Story) 用例(Use Case)
本质 一个用户价值的最小切片 一个参与者达成目标的完整场景集
载体 卡片 + 对话 + 验收标准 参与者 / 前置 / 主流程 / 备选流 / 异常流 / 后置
粒度 1–3 天能做完 一个完整业务目标,可拆成多个故事
详细程度 故意写得少,细节在对话里 写得全,分支必须穷举
变更成本 低,换一张卡片即可 高,改流程要同步所有分支与下游
最适合 需求还在变、两周一个迭代、To C 产品 交互复杂、多角色、合同验收、合规审计
典型失效 只有标题没有验收标准 → 无法判定"做完" 写成 40 页流程图 → 没人读,很快腐化

用户故事:三段式,第三段最容易被砍

作为 <角色>,我想要 <能力>,以便 <价值>。
As a <role>, I want <goal>, so that <benefit>.
  • 角色不能写 “用户”。写 “首次注册未绑卡的买家”——不同角色对同一功能的期望不同。
  • 能力写目标,不写控件。“导出订单” 是能力,“一个导出按钮” 是方案。
  • 价值是最常被省略的一段,也是最该保留的一段:写不出 “以便”,这需求就该砍。
❌ 坏故事 问题
作为用户,我想要一个导出按钮 方案冒充需求,没说要导什么、为什么导
作为用户,我想要系统支持分库分表 技术方案冒充用户价值,用户不关心分片
作为管理员,我想要系统更好用 不可测,无法判定完成
作为用户,我想要下单 太大,是史诗不是故事

3C:卡片只是索引,不是需求

C 含义 落地动作
Card 一张卡片写一句话 够短才能贴在墙上、排进迭代
Conversation 开发、产品、业务当面聊 需求的主体是对话,不是卡片
Confirmation 把聊出来的结论固化成验收标准 没有 AC 的故事不算完成定义

INVEST:判断一个故事是否合格

原则 含义 违反的信号
Independent 故事之间尽量不依赖 排期时必须"等 A 做完才能做 B"
Negotiable 是可协商的占位符,不是合同 把故事当规格书逐字验收
Valuable 对用户或业务有价值 写不出"以便"
Estimable 团队能估出大小 聊了三小时还估不出来 → 需求没想清
Small 一个迭代内能完成 一个故事跨三个迭代
Testable 有客观的通过标准 AC 里出现"友好""快速""合理"

纵向切片,不要横向切片

切法 一个迭代交付什么 结果
纵向(推荐) 从页面 → 接口 → 存储的一条完整链路 第 1 周就能演示,能收真实反馈
横向 先建完所有表结构,再做所有接口,最后做页面 前 3 个迭代没有任何可演示的东西

🔑 横向切片把 “能演示” 推迟到最后一周,等于把风险也推迟到最后一周。

验收标准:Given / When / Then

功能:订单超时自动取消

  场景:未支付订单在 30 分钟后自动取消
    假设 用户已下单,订单状态为"待支付",库存已扣减 1 件
    并且 距下单时间已过 30 分钟
    当 取消任务扫描到该订单
    那么 订单状态变为"已取消"
    并且 库存回滚 1 件
    并且 用户在 1 分钟内收到取消通知

  场景:已支付订单不被取消
    假设 订单在 29 分钟时完成支付
    当 取消任务扫描到该订单
    那么 订单状态保持"已支付"
    并且 库存不回滚

三条纪律:

  • 一个场景只验证一件事,别在一个场景里塞五个断言。
  • 每条 AC 都能直接翻成一个自动化测试——翻不出来的 AC,是形容词。
  • 必须写反例场景 (“已支付不被取消”)。只写正例的 AC,等于没定义边界。

层级:史诗 → 故事 → 任务

层级 时间尺度 一个迭代里的数量 例子
史诗 Epic 周–月 0–1 个在拆 订单履约体系
故事 Story 1–3 天 5–10 个 未支付订单 30 分钟自动取消
任务 Task 小时 每个故事 2–5 个 写定时任务、加状态机、接入通知

史诗直接进迭代,最常见的结局是 “迭代结束,交付了 0 个完整功能”。

用例:主流程只是及格线

用例模板

字段 内容 例子(提交订单)
用例名 动词 + 宾语 提交订单
参与者 主参与者 / 辅助参与者 买家(主)、支付网关、库存服务(辅)
前置条件 开始前必须为真 已登录、购物车非空、收货地址已填
触发 什么动作启动 点击"提交订单"
主流程 编号步骤,成功路径 1 校验参数 2 校验库存 3 锁定库存 4 生成订单 5 跳转支付
备选流 其他成功路径 3a 库存不足 → 提示缺货并回购物车;4a 用户有未支付订单 → 合并或提示先支付
异常流 失败路径 3b 锁库存超时 → 重试 2 次后失败,提示稍后再试;5a 支付网关不可用 → 订单置待支付,30 分钟后自动释放
后置条件 结束后必须为真 订单已创建且状态为待支付;库存已锁定并记录锁定单号

为什么价值在备选流和异常流

主流程谁都会写——它就是把 happy path 抄一遍。真正决定系统质量的是分支有没有归宿:

分支 没人写下来会发生什么
库存扣了、订单没生成 少卖货,对账时才发现,且没有补偿入口
订单生成了、支付回调重复到达 重复发货,直接资损
用户连点两次提交 两个订单、两次锁库存
支付成功但回调超时 用户已付款,系统显示待支付,客服工单爆炸

🔑 **用例的价值不在主流程,在备选流和异常流。**线上事故有八成发生在没人写下来的分支里。

用例图只画关系,不画流程

  • 用例图表达:谁 (参与者) 能触发哪些用例,以及用例之间的 include / extend。
  • 流程表达:用活动图或时序图,别在用例图里画 if-else 菱形——那会让图既不能看也不能改。
  • 判断:一张图上有超过 12 个用例,说明你在画系统功能清单,不是在画用例。

怎么选:决策表

你的情况 选什么
两周一个迭代、需求边做边变、To C 产品 故事 + AC
复杂审批流、多角色、跨多个外部系统 用例(主 + 备选 + 异常)
招投标、合同验收、合规审计 用例(可签署的完整规约)
内部工具、需求明确、一次性交付 用例
探索型需求,连用户要什么都说不清 故事,先做最小纵向切片验证
大型系统,既要全景又要迭代 叠用:用例定边界,故事定节奏

最后一行最常见:用例负责 “所有分支都要有归宿”,故事负责 “这次交付哪一段价值”。先用用例把提交订单的 8 条分支列全,再把主流程切成 6 个故事按迭代交付。

反模式

反模式 后果
故事只有标题,没有 AC 无法判定"做完",验收变成扯皮
故事写成"我要一个下拉框 / 我要一个按钮" 方案冒充需求,设计空间被锁死
史诗直接进迭代 迭代结束交付 0 个完整功能
AC 里写"友好""快速""合理" 不可测,等于没写
只写正例场景 边界条件靠开发临场发挥,线上暴露
用例里写实现步骤("先调 A 接口再写 B 表") 需求绑死架构,换实现就要改需求
用例写到 40 页 没人读,以代码为准,文档必然腐化
用例图当流程图用 图既不能评审也不能维护

三条铁律

🔑 写不出 “以便” 的故事,先砍需求,别急着开发。

🔑 写不全 “异常流” 的用例,别上线。

🔑 故事是对话的索引,不是需求的全部;用例是分支的清单,不是实现的设计。

自检

Q1 “作为用户,我想要订单导出按钮。” 缺了哪两段信息?补齐后分别是什么?

▸ 答案:缺角色精确化与价值段。补成:“作为需要月末对账的财务专员,我想要把当月订单按支付时间导出成 Excel,以便直接导入财务系统做对账,不用人工抄 3000 行”。补齐后,“导出” 的字段范围、时间维度、格式要求全都跟着价值自然浮现。

Q2 只写主流程的用例,会漏掉哪类问题?举一个具体场景。

▸ 答案:漏掉并发与失败恢复。例如 “提交订单” 只写主流程,就漏了 “用户连点两次提交”——结果生成两个订单、锁两次库存,用户被扣两次钱。这类分支必须在异常流里显式写成 “同一用户 5 秒内的重复提交按幂等处理,返回首个订单号”。

Q3 一个迭代 2 周,团队有 6 个故事,其中 4 个是横向切片 (先建表、先写接口)。第 10 天你能演示什么?

▸ 答案:几乎什么都演示不了——表结构、接口、页面各自完成 60%,但没有一条链路能跑通。纵向切片能在第 3 天就演示一条完整链路,把 “接口字段对不对、业务流程顺不顺” 的风险提前暴露。

Q4 什么情况下必须用用例,而不是只用故事?

▸ 答案:三种情况——① 分支多且后果重 (支付、资金、库存、审批),漏一条分支就是资损或合规问题;② 外部参与方多,需要把系统间的交互契约固定下来;③ 要签字验收 (合同、招投标、审计),需要一份可追溯的完整规约。故事是给团队自己排期用的,用例是给 “要负责的人” 查的。

Q5 为什么说 “用例图不是流程图”?画错了会怎样?

▸ 答案:用例图只表达参与者与用例的关联 (谁能做什么),不表达步骤顺序与条件分支。把 if-else 画进用例图,图会迅速膨胀到无法评审;而且流程一改,图就过期。流程该用活动图/时序图,用例图只维护 “谁-做什么” 这层稳定关系。