用户故事模板:把价值和验收写在一起

0阅读12分钟

用户故事要连接价值和实现

上周我在评审一个 Sprint 的用户故事,产品同学写的描述是:「作为用户,我希望能够导出报表」。开发问了一句「导出成什么格式」,产品说「Excel 就行」;测试又问「数据量多大呢」,产品说「应该不大」。两周后验收的时候,运营跳出来说:「我要的是带图表的 PDF,Excel 没法直接发给客户」。

这种场景我见过很多次。问题不在谁漏说了什么,而在于我们写用户故事时,习惯性地把「价值」和「验收」分成两件不同的事。价值写在故事里,验收留在脑子里。等到开发、测试、产品各自理解出现偏差,返工就变成了常态。

用户故事不只是三句话

用户故事最早由 Kent Beck 在极限编程(XP)中提出,后来由 Ron Jeffries 总结为 3C 模型:

  • Card(卡片):对需求的简短描述,通常用「作为…我希望…从而…」的句式
  • Conversation(对话):围绕这个需求,团队、产品、用户之间的讨论
  • Confirmation(确认):判断这个需求是否完成的验收标准

Agile Alliance 在 INVEST 原则中也把「Testable(可测试)」作为用户故事的六项标准之一——一个写不出验收标准的故事,要么拆得不够细,要么价值还没想清楚。

Mike Cohn 在 Mountain Goat Software 的指南里反复强调:「每个用户故事都是一段对话的占位符」,但对话的结果必须落到具体的验收标准上,否则团队永远无法对齐「什么时候算做完了」。

我在实际项目中发现,多数团队在 Card 和 Conversation 上都做得不错,但在 Confirmation 这一环要么省略,要么写得过于模糊。没有验收标准的故事,就像一份没有签字条件的合同——大家都知道有这回事,但对具体内容的理解可能完全不同。

一个实用的用户故事模板

经过多次迭代,我整理出一个模板结构,覆盖从需求到验收的完整链路:

  • 角色:作为 [某类用户],明确是谁需要这个能力
  • 目标:我希望 [完成某件事],说清楚要做什么
  • 价值:从而 [获得某个结果],解释为什么要做
  • 业务规则:列出限制条件、特殊情况、边界处理
  • 验收标准:用 Given-When-Then 格式,描述可观察的行为
  • 非目标:本故事不覆盖什么,避免范围蔓延
  • 补充说明:技术约束、依赖关系、设计稿链接等

每个字段都不是摆设。角色帮开发理解上下文,价值帮团队在资源紧张时判断优先级,业务规则和验收标准则把模糊的期望变成可验证的条件。

模板结构对比

维度只有「角色-目标-价值」加上业务规则加上验收标准完整模板
开发理解需求知道要做什么知道边界在哪知道怎么实现才算对完整闭环
测试写用例靠猜有方向有明确依据直接映射
产品验收凭感觉有参照有清单可量化
返工概率最低
适合场景探索期原型内部工具面向用户的功能生产级交付

案例一:购物车「保存商品」功能

场景:电商网站用户希望在浏览时保存感兴趣的商品,方便后续购买。

原始需求:「作为用户,我希望保存商品到购物车。」

翻车现场

开发完成后发现:

  • 库存不足时,保存的商品无法加入购物车,但用户不知道
  • 商品价格发生变化,购物车还是显示旧价格
  • 用户在手机端保存,电脑端看不到
  • 用户注销账号后,购物车数据还在

这些问题并非无法预见。如果写故事时把异常情况和业务规则列出来,开发自然会提前考虑。

修复后的故事

角色: 已登录的购物用户
目标: 将商品保存到购物车,方便后续下单
价值: 减少重复搜索商品的时间,提升下单转化率
 
业务规则:
  - 库存为 0 时,商品仍可保存,但标记为「缺货」
  - 保存后价格变动,显示「下单时以实际价格为准」提示
  - 购物车数据跨设备同步,基于用户账号
  - 账号注销后 30 天清除购物车数据
 
验收标准:
  - Given 用户已登录, When 点击「加入购物车」, Then 商品出现在购物车列表中
  - Given 商品库存为 0, When 用户保存商品, Then 显示「缺货」标记且不阻塞保存
  - Given 保存后商品价格变动, When 用户进入购物车, Then 展示新价格并附变动提示
  - Given 用户在手机端保存商品, When 在电脑端登录同一账号, Then 购物车包含该商品
 
非目标:
  - 不涉及购物车结算流程
  - 不涉及优惠券和满减逻辑

案例二:SaaS 平台的密码重置

场景:用户忘记密码时需要通过邮箱重置。

原始需求:「作为用户,我希望能重置密码。」

翻车现场

功能确实实现了——用户能收到重置邮件,也能设置新密码。但上线后投诉不断:

  • 锁定状态的账号仍能发起重置,用户以为修好了,实际登录不了
  • 有人一分钟内点了 5 次「发送重置邮件」,邮箱被塞满
  • 用户在两个标签页同时点重置链接,先设的密码被后设的覆盖
  • 重置邮件里写了「点击链接修改密码」,但没有说明链接多久失效

修复后的故事

角色: 已注册但忘记密码的用户
目标: 通过邮箱验证身份并重置密码
价值: 恢复账号访问,不需要联系客服
 
业务规则:
  - 账号处于锁定时,不允许发起重置
  - 重置链接 24 小时内有效,且一次性使用
  - 同一邮箱 24 小时内最多发送 3 次重置邮件
  - 重置成功后,所有已登录会话失效
 
验收标准:
  - Given 用户账号正常, When 输入邮箱请求重置, Then 收到含重置链接的邮件
  - Given 账号已被锁定, When 请求重置密码, Then 提示「账号已锁定,请联系管理员」
  - Given 24 小时内已发送 3 次邮件, When 再次请求, Then 提示「请稍后再试」
  - Given 用户点击重置链接, When 设置新密码并保存, Then 旧密码失效且所有会话登出
  - Given 重置链接已超过 24 小时, When 用户点击, Then 提示「链接已过期,请重新申请」
 
非目标:
  - 不涉及双因素认证(2FA)的设置和验证
  - 不涉及管理员强制重置密码的流程

案例三:API 分页接口

场景:后端需要提供一个分页查询接口,前端用它展示列表。

原始需求:「作为前端开发,我希望接口支持分页,并返回总数。」

翻车现场

后端返回了 pagetotal,但没有说明:

  • page 从 0 开始还是从 1 开始
  • page_size 的默认值和最大值
  • 请求超出最大页码时返回什么
  • 总数 total 是精确值还是估算值
  • 数据为空时返回空数组还是 null

前端按 page=0 写了一版,后端默认 page=1,联调时花了一天对齐。后来又发现 total 在大数据量时是估算值,产品不接受,又返工了 3 天。

修复后的故事

角色: 前端开发者
目标: 调用分页接口获取列表数据
价值: 实现列表展示和翻页功能,用户体验流畅
 
业务规则:
  - page 从 1 开始,默认值为 1
  - page_size 默认 20,最大 100
  - page 超出范围时返回空数组和实际总数
  - total 为精确计数(非估算)
  - 数据为空时返回空数组,不返回 null
  - 支持按 created_at 排序,默认降序
 
验收标准:
  - Given 数据库有 150 条记录, When 请求 page=1&page_size=50, Then 返回 50 条且 total=150
  - Given 数据库有 150 条记录, When 请求 page=4&page_size=50, Then 返回空数组且 total=150
  - Given 未传 page_size, When 发起请求, Then 按 page_size=20 返回数据
  - Given 请求 page_size=200, When 发起请求, Then 返回错误码并提示「page_size 不能超过 100」
  - Given 数据库无匹配数据, When 发起请求, Then 返回空数组而非 null
 
非目标:
  - 不涉及游标分页(cursor-based pagination)
  - 不涉及全文搜索和高亮

从故事到验收:完整工作流

用户故事从提出到验收,需要经过多个环节的流转。下面是一个典型的流程:

流程图画布 · 115%
Mermaid 流程图加载中...

用户故事 vs 任务 vs 技术 Spike

很多团队分不清用户故事和技术任务的边界。用户故事应该从用户视角描述价值,技术任务是实现过程中的具体步骤,Spike 则是用来调研不确定方案的技术探索。

维度用户故事技术任务技术 Spike
视角用户 / 业务方开发者开发者
目的交付用户价值完成实现步骤降低技术不确定性
估算者团队共同执行开发者执行开发者
完成标准验收标准 + 用户确认代码合并 + 测试通过输出调研报告
举例作为用户,我能导出报表实现导出接口的分页逻辑调研导出方案的可行性和性能

用户故事可以拆出技术任务,但技术任务不应该反过来被当成用户故事。如果你发现一个故事写成了「作为开发者,我希望重构数据库」,那它更适合作为技术任务或技术 Spike 来管理。

编写验收标准的常见错误

验收标准写得好不好,直接决定了开发能不能一次做对。以下是我在实际项目中见过的问题:

常见错误为什么有问题正确做法示例
写了实现细节限制了开发方案选择描述可观察行为坏:「调用 /api/publish 接口」;好:「点击发布后,文章状态变为已发布」
只覆盖正常路径异常场景漏测补充异常和边界情况补充:「当网络断开时,提示用户重试」
验收条目过多暗示故事太大拆分为多个故事超过 5 条考虑拆分
使用被动语态不清晰谁做了什么用主动语态坏:「数据会被保存」;好:「系统将数据保存到数据库」
模糊的量化词无法测试用具体数值坏:「响应要快」;好:「P95 响应时间低于 200ms」
缺少前置条件测试无法复现Given 写明上下文「Given 用户已登录且购物车有 3 件商品」
把业务规则混入验收边界不清晰业务规则和验收标准分开写规则:「密码至少 8 位」;验收:具体的测试场景

好 / 坏写法对比

对比一:验收标准是否描述行为

# ❌ 坏:写成了实现细节
验收标准:
  - 调用 POST /api/cart/items 接口添加商品
 
# ✅ 好:描述用户可观察的行为
验收标准:
  - Given 用户在商品详情页, When 点击「加入购物车」, Then 购物车数量 +1 且弹出「已添加」提示

实现细节应该交给开发决定。验收标准只关心「用户能感知到什么变化」。

对比二:是否考虑边界情况

# ❌ 坏:只覆盖正常路径
验收标准:
  - Given 用户已登录, When 提交订单, Then 订单创建成功
 
# ✅ 好:覆盖正常和异常路径
验收标准:
  - Given 库存充足, When 提交订单, Then 订单创建成功,库存扣减
  - Given 库存不足, When 提交订单, Then 提示「库存不足」,不创建订单
  - Given 用户有未支付订单, When 提交新订单, Then 提示「请先完成未支付订单」

每个关键操作都应该问一句:「如果前置条件不满足,会怎样?」把答案写进验收标准。

对比三:是否有具体数值

# ❌ 坏:模糊描述,无法测试
验收标准:
  - 页面加载要快
  - 支持大量数据导出
 
# ✅ 好:有具体数值,可直接验证
验收标准:
  - Given 网络条件正常, When 访问列表页, Then 首屏加载时间低于 1.5 秒
  - Given 数据量为 10000 条, When 触发导出, Then 在 30 秒内完成且不超时

所有性能要求、数量限制、时间约束,都应该有具体数值。模糊的描述最终会变成争论的源头。

对比四:是否从用户视角书写

# ❌ 坏:从系统视角描述
验收标准:
  - 数据库记录状态更新为 published
  - 缓存失效并重新加载
 
# ✅ 好:从用户视角描述
验收标准:
  - Given 编辑点击「发布」按钮, When 操作成功, Then 文章在列表页显示「已发布」状态
  - Given 文章已发布, When 用户访问文章页, Then 看到最新内容而非缓存版本

用户不关心数据库和缓存,他们关心的是界面上看到什么、能做什么。验收标准应该用用户能理解的语言来写。

对比五:业务规则和验收标准是否分离

# ❌ 坏:规则混在验收里
验收标准:
  - 密码长度至少 8 位
  - 必须包含大小写字母和数字
  - 不能和最近 3 次密码相同
  - 用户设置新密码时成功保存
 
# ✅ 好:规则和验收分开
业务规则:
  - 密码长度 8-32 位
  - 必须包含大写字母、小写字母和数字
  - 不能和最近 3 次密码相同
 
验收标准:
  - Given 用户输入符合规则的密码, When 点击保存, Then 密码更新成功并提示「修改成功」
  - Given 用户输入 6 位密码, When 点击保存, Then 提示「密码长度至少 8 位」
  - Given 用户输入与前 3 次相同的密码, When 点击保存, Then 提示「不能使用最近 3 次用过的密码」

业务规则是「系统的一般性约束」,验收标准是「具体场景下的可验证行为」。分开写,开发和测试各自都能快速找到自己需要的信息。

用 INVEST 原则检验故事质量

写完用户故事后,我会用 INVEST 原则过一遍。这六个维度能帮你快速发现故事的结构性问题:

原则含义检验问题常见问题
Independent独立的这个故事能否独立交付?和其他故事强耦合,需要一起上线
Negotiable可协商的描述是否留有实现空间?写得太像合同,限制了技术方案
Valuable有价值的用户或业务能从中获益吗?纯技术优化,没有可感知的价值
Estimable可估算的团队能估算工作量吗?需求太模糊,没人知道有多大
Small小的能在一个 Sprint 内完成吗?一个故事覆盖了整个模块
Testable可测试的能写出验收标准吗?价值太虚,无法定义「完成」

如果一个故事在多个维度上不合格,最有效的做法通常是拆分。比如「作为用户,我希望管理我的账户」就太大了,可以拆成「修改头像」「更换邮箱」「修改密码」「注销账号」等多个独立故事。

交付前检查清单

每次评审用户故事之前,我会对照以下清单逐项检查。不一定每条都适用,但它能帮你避开大部分常见坑点。

一、故事结构

  • 有明确的角色定义,不是泛泛的「用户」
  • 有清晰的目标描述,说明要做什么
  • 有价值说明,解释为什么要做
  • 有业务规则,列出边界条件和特殊情况
  • 有验收标准,用 Given-When-Then 格式
  • 有非目标,说明本故事不覆盖什么

二、INVEST 检验

  • 故事相对独立,不依赖其他故事才能交付
  • 描述留有协商空间,不限制具体实现方案
  • 对用户或业务有明确价值
  • 团队能估算工作量
  • 足够小,能在一个 Sprint 内完成
  • 可测试,能写出明确的验收标准

三、验收标准质量

  • 覆盖正常路径和至少 2 条异常路径
  • 条目控制在 3-5 条,过多则考虑拆分故事
  • 描述可观察行为,不包含实现细节
  • 使用主动语态,主语明确
  • 有具体数值和明确的状态描述
  • 每条标准可独立测试验证
  • 边界情况已考虑(空值、并发、超时、权限)

四、可交付性

  • 开发人员读完知道怎么实现
  • 测试人员读完能直接写测试用例
  • 产品人员读完知道怎么验收
  • 新加入的团队成员读完能快速理解上下文

模板文件下载

如果你需要在团队内推广这个模板,可以把下面的结构复制到你的项目管理工具中:

# 用户故事模板
 
角色: 作为 [某类用户]
目标: 我希望 [完成某件事]
价值: 从而 [获得某个结果]
 
业务规则:
  - [限制条件 1]
  - [限制条件 2]
  - [边界情况处理]
 
验收标准:
  - Given [前置条件], When [用户动作], Then [预期结果]
  - Given [前置条件], When [用户动作], Then [预期结果]
  - Given [前置条件], When [用户动作], Then [预期结果]
 
非目标:
  - [本故事不覆盖的内容 1]
  - [本故事不覆盖的内容 2]
 
补充说明:
  - [技术约束]
  - [依赖关系]
  - [设计稿链接]

写在最后

用户故事模板不是为了增加文档负担。它的真正价值在于:当你把角色、价值、业务规则和验收标准写在一起时,团队对「做完」这件事就有了共识。

好的用户故事不需要开会反复确认。开发读完知道怎么实现,测试读完能写用例,产品读完知道怎么验收。如果做到了这一点,模板就发挥了作用。

如果你发现团队总是因为「理解不一致」而返工,不妨从一个故事开始,把验收标准补齐,看看效果。

参考资料

评论 0

0 / 1000