用户故事编写
概览
编写良好的用户故事以用户为中心的方式传达需求,促进讨论,并为开发人员和测试人员提供清晰的验收标准。
何时使用
- 将需求分解为开发任务
- 产品待办事项创建和细化
- 敏捷冲刺计划
- 与开发团队沟通功能
- 定义验收标准
- 创建测试用例
说明
1. 用户故事格式
# 用户故事模板
**标题:** [功能名称]
**作为** [用户角色/人物]
**我想要** [行动/能力]
**以便于** [业务价值/好处]
---
## 用户背景
- 用户角色:[谁执行此操作?]
- 用户目标:[他们试图完成什么?]
- 使用案例:[他们何时执行此操作?]
---
## 验收标准
假设 [前提条件]
当 [行动]
那么 [预期结果]
示例:
假设用户已登录并查看他们的购物车
当他们将产品添加到购物车时
那么购物车数量增加,并且出现成功消息
---
## 完成定义
- [ ] 代码编写并同行评审
- [ ] 单元测试编写(>80%覆盖率)
- [ ] 集成测试通过
- [ ] 验收标准验证
- [ ] 文档更新
- [ ] 无控制台错误或警告
- [ ] 性能可接受
- [ ] 满足可访问性要求
- [ ] 安全审查完成
- [ ] 产品负责人批准
---
## 附加细节
**故事点数:** 5(工作量估计)
**优先级:** 高
**史诗:** [父级功能]
**冲刺:** 冲刺23
**指派人:** [开发人员]
**依赖项:** [此故事依赖的其他故事]
---
## 笔记
- 任何额外的上下文或考虑因素
- 需要考虑的边缘情况
- 性能限制
- 可访问性要求
- 安全考虑
2. 故事细化过程
# 故事细化和质量门
class UserStoryRefinement:
QUALITY_GATES = {
'独立': '故事可以独立实现',
'可协商': '细节可以讨论和细化',
'有价值': '提供清晰的业务价值',
'可估计': '团队可以估计工作量',
'小': '可以在一个冲刺中完成',
'可测试': '清晰的验收标准'
}
def evaluate_story(self, story):
"""使用INVEST标准评估故事质量"""
assessment = {}
for criterion, description in self.QUALITY_GATES.items():
assessment[criterion] = self.check_criterion(story, criterion)
return {
'story_id': story.id,
'assessment': assessment,
'ready_for_development': all(assessment.values()),
'issues': self.identify_issues(story),
'recommendations': self.provide_recommendations(story)
}
def check_criterion(self, story, criterion):
"""根据特定INVEST标准进行评估"""
checks = {
'独立': lambda s: len(s.dependencies) == 0,
'可协商': lambda s: len(s.acceptance_criteria) > 0,
'有价值': lambda s: len(s.business_value) > 0,
'可估计': lambda s: s.story_points is not None,
'小': lambda s: s.story_points <= 8,
'可测试': lambda s: len(s.acceptance_criteria) > 0 and all(
ac.get('test_case') for ac in s.acceptance_criteria
)
}
return checks[criterion](story)
def refine_story(self, story):
"""指导细化讨论"""
return {
'story_id': story.id,
'refinement_agenda': [
{
'topic': '澄清范围',
'questions': [
'用户到底需要什么?',
'不包括什么?',
'有没有边缘情况?'
]
},
{
'topic': '定义验收标准',
'questions': [
'我们怎么知道完成了?',
'成功标准是什么?',
'什么应该优雅地失败?'
]
},
{
'topic': '技术方法',
'questions': [
'我们将如何实现这一点?',
'有没有依赖项?',
'风险是什么?'
]
},
{
'topic': '估计',
'questions': [
'工作量多少?',
'有没有未知数?',
'需要缓冲吗?'
]
}
],
'outputs': [
'细化后的故事描述',
'详细的验收标准',
'确定的技术方法',
'故事点数估计',
'列出依赖项',
'团队对范围达成一致'
]
}
3. 验收标准示例
故事:作为客户,我希望保存支付方式,以便我可以更快地结账
验收标准:
场景 1:添加新的支付方式
假设我已登录
并且我在支付设置页面
当我点击“添加支付方式”
并且我输入有效的支付详情
并且我点击“保存”
那么支付方式被保存
并且我看到成功消息
并且新方法出现在我的保存列表中
场景 2:编辑现有的支付方式
假设我有保存的支付方式
当我点击方法上的“编辑”
并且我更改有效期
并且我点击“保存”
那么更改被保存
并且其他字段保持不变
场景 3:删除支付方式
假设我有多个保存的支付方式
当我点击方法上的“删除”
并且我确认删除
那么该方法被移除
并且如果需要,我的默认方法被更新
场景 4:错误处理
假设我输入无效的支付信息
当我点击“保存”
那么我看到错误消息
并且该方法不被保存
并且我返回表单进行更正
场景 5:安全
假设支付表单显示
当我查看页面源代码
那么我不能看到完整的支付号码(PCI合规)
并且信用卡数据被加密
并且连接是HTTPS
---
非功能性需求:
- 性能:表单保存必须在<2秒内完成
- 可用性:表单必须在<3步内完成
- 可靠性:支付服务99.9%的正常运行时间
- 可访问性:WCAG 2.1 AA合规
- 安全性:PCI DSS 1级合规
4. 故事拆分
// 将大型故事拆分成较小的部分
class StorySpitting {
SPLITTING_STRATEGIES = [
'按工作流程步骤',
'按用户角色',
'按CRUD操作',
'按业务规则',
'按技术层',
'按风险/复杂性',
'按优先级'
];
splitLargeStory(largeStory) {
return {
original_story: largeStory.title,
original_points: largeStory.story_points,
strategy: '按工作流程步骤拆分',
split_stories: [
{
id: 'US-201',
title: '添加支付方式 - 表单UI',
points: 3,
description: '构建带有验证的支付表单UI',
depends_on: 'None',
priority: 'First'
},
{
id: 'US-202',
title: '添加支付方式 - 后端API',
points: 5,
description: '创建保存支付方式的API端点',
depends_on: 'US-201',
priority: 'Second'
},
{
id: 'US-203',
title: '添加支付方式 - 集成',
points: 3,
description: '将表单连接到API,处理响应',
depends_on: 'US-202',
priority: 'Third'
},
{
id: 'US-204',
title: '添加支付方式 - 安全加固',
points: 2,
description: 'PCI合规,加密,数据保护',
depends_on: 'US-202',
priority: 'Critical'
}
],
total_split_points: 13,
complexity_reduction: '从13点的单个故事到5点最大',
benefits: [
'更快的反馈周期',
'可能并行开发',
'更容易测试',
'每个故事更清晰的范围'
]
};
}
}
5. 故事估计
故事点数框架:
1点:微不足道
- 更新标签文本
- 添加CSS类
- 简单的配置更改
- 时间:<2小时
2点:非常小
- 向表单添加简单字段
- 更新错误消息
- 简单的验证
- 时间:2-4小时
3点:小
- 创建单个页面/组件
- 添加基本API端点
- 简单的集成
- 时间:4-8小时
5点:中等
- 创建具有多个交互的功能
- 构建具有多个端点的API
- 复杂的业务逻辑
- 时间:1-2天
8点:大
- 跨多个页面的功能
- 复杂的集成
- 多个技术挑战
- 时间:2-3天
13点:非常大(太大了 - 拆分它!)
- 应该拆分成更小的故事
- 或提升为史诗
- 时间:>3天
---
估计技巧:
- 使用相对大小(与已知故事比较)
- 考虑未知数和风险
- 包括非编码时间(测试,文档)
- 考虑团队技能水平
- 对假设保持透明
- 学习后重新估计
最佳实践
✅ 做
- 从用户的角度编写
- 专注于价值,而不是实现
- 创建足够小的一个冲刺中完成的故事
- 定义清晰的验收标准
- 使用一致的格式和术语
- 让产品负责人批准故事
- 包括边缘情况和错误场景
- 链接到业务需求/目标
- 根据学习更新故事
- 创建可测试的故事
❌ 不做
- 编写技术任务为中心的故事
- 创建过于详细的规范
- 编写需要多个冲刺的故事
- 忘记非功能性需求
- 跳过验收标准
- 无必要地创建依赖故事
- 编写模糊的验收标准
- 忽略边缘情况
- 创建太大的故事
- 没有讨论就更改冲刺中的故事
用户故事提示
- 保持故事专注于用户价值
- 当>5点时使用故事拆分
- 始终包括验收标准
- 在冲刺前与团队审查故事
- 根据团队学习更新完成定义