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 画进用例图,图会迅速膨胀到无法评审;而且流程一改,图就过期。流程该用活动图/时序图,用例图只维护 “谁-做什么” 这层稳定关系。