1. 什么是用户故事?
这一部分会说明什么是用户故事,如何使用它们开始,介绍如何编写用户故事,如何利用系统的用户种类来确定故事,如果在难以接触到用户的情况下与充当用户角色的人一起工作,如何编写测试来验证故事已经完成。
最后,给出一些有助于编写良好故事的指导原则。
1.1. 背景
1.1.1. 软件需求是一个沟通的过程
一个项目的成功,依赖于很多不同的信息,这些信息来自各自不同的人员:
- 一方是客户和用户,有时还有分析人员、领域专家和其他从业务或组织视角来审视软件的人
- 另一方是技术团队
一旦任何一方在沟通中把持绝对地位,项目就会遭受损失。
- 如果业务方把持绝对地位,他们就会关注软件功能和交付日期,却很少关注开发人员是否能够同时满足这两个目标,或者开发人员是否确切了解需求。
- 如果是开发人员把持绝对地位,技术术语就会代替业务语言,从而导致开发人员无法倾听业务方的实际需求。
1.1.2. 需求的协同工作方法
我们需要一种需求协同工作的方法,让双方都不占绝对主导地位,共同面对感情用事和办公室政治化的资源分配问题。
如果资源分配问题完全落在一方,项目必定会失败。
- 如果只让开发人员来承担这些问题(他们通常被告知“我不关心你们怎么做,但请你们在6月份之前完成”),他们可能会牺牲质量来换取额外的特性,也可能只部分实现一个特性,或者自行做出一些该在有客户和用户参与的情况下才能做出的决定。
- 如果只是客户和用户承担资源分配的责任,那么我们会通常在项目开始阶段看到一系列漫长的讨论,项目中的特性逐渐减少。之后,在最终发布版本的时候,只剩下很少的功能,甚至少于被减少的功能。
1.1.3. 如何规避风险
软件开发类项目本身是很难预先评估的,中间有很多因素能决定最终项目的结果和质量,这是软件开发本身的特点。那么我们应该如何来做?如何来更好的规避风险?
基本原则:
- 不要在项目开始阶段就做一套完善的、包罗万象的决策
- 把各个决策分散项目过程中
因此,我们需要有一个获取信息的过程,越早越好,越频繁越好。
1.2. 什么是用户故事?
用户故事描述了对用户、系统或软件购买者有价值的功能。
用户故事由以下三个方面组成:
- 一份书面的故事描述,用来做计划和提示
- 有关故事的对话,用于具体化故事细节
- 测试,用来表达和编档故事细节并且可以用于确定故事何时完成
基于Ron Jeffries
提出了3C
原则,对用户故事的最佳诠释应该是这样。
卡片(
Card
)包含了故事的文字说明,然而需求细节要在“对话(Conversation
)”中获得,并在“确认(Confirmation
)”部分得以记录。
例子
我们所有的例子都是来自一个假想的职位发布和搜索的招聘网站。
好的故事雏形例子
- 用户可以在网站上发布简历
- 用户可以搜索职位
- 公司可以发布新职位
- 用户可以限制浏览其简历的人
不好的例子
- 这个软件将用C++语言进行编写
- 程序将通过连接池连接数据库
第一个不好的例子,对于招聘网站来说,它的用户根本不关心系统是用什么语言来写的。
第二个不好的例子也不是一个很好的用户故事,因为用户没有必要关心应用如何连接数据库之类的技术细节。
关键在于故事应该以对用户有价值的方式写下来。
1.3. 细节在哪里?
“用户可以搜索工作”,说起来容易,但仅以这句话为指南着手开发和测试确实另外一回事。
1.3.1. 故事细节
那细节都在哪里?下面这些未解决的问题又该怎么办?
- 用户可以搜索哪些值?省份?城市?职位?关键字?
- 用户必须是网站的会员?
- 搜索参数可以保存吗?
- 要显示哪些与工作匹配的信息?
许多这样的细节可以用另外的用户故事来描述。
事实上,多个小故事远胜于一个庞大的故事。
例如,这个招聘网站大部分的功能可以描述成下面两个故事。
- 用户可以搜索工作
- 公司可以发布工作信息
但是这两个故事太庞大了,派不上用场。
1.3.2. 史诗故事
如果一个故事很大,我们会称之为“史诗故事(
Epic
)”.
史诗故事可以分成多个小故事。
例如,“用户可以搜索工作”可以分为下面几个小故事。
- 用户可以通过地区、薪水范围、职位、公司名和发布日期之类的属性来搜索工作
- 用户可以查看搜索结果中每个工作的信息
- 用户可以查看发布工作的公司的详细信息
然而,我们不需要不断的分解故事,知道有一个故事能够覆盖每一个细节。
例如,“用户可以查看搜索结果中每个工作的信息”,就是一个比较合理且实际的故事。我们不需要在进行下一步的分解成更小的故事。
- 用户可以查看工作范围
- 用户可以查看薪水范围
- 用户可以查看工作地点
与其写下这些故事细节,还不如让开发团队和客户讨论这些细节,即在这些细节变得重要时才讨论。
讨论才是关键,而不是故事卡上的注释。
故事并不具有契约性质,达成的协议将由测试来记录,这些测试将演示故事是否被正确开发。
1.4. 必须多长时间完成?
“必须多长时间完成?”这个问题能够从某种角度来了解项目用户的期望是什么?
用户的期望最好以验收测试的形式记录下来。
如何测试验收故事的提示语句就是用户的期望。
可以记录如何测试用户故事的这样一些提示
- 用空的工作描述来试试
- 用很长的工作描述来试试
- 用缺少薪资来试试
- 用六位数的薪资来试试
- ...
测试描述可以很简短、不完整,可以在任何时候加入或者删除。
写这些测试描述的目的是传递故事的额外信息,以便于开发人员知道故事于什么时候结束。
开发人员如果能够了解客户的期望,他们便能知道什么时候算是完成了客户要求的功能。
1.5. 客户团队
在一个理想的项目中,我们应该会有一个专职的人员为开发人员的工作排列优先级,回答他们所有的问题,在软件完成时使用软件,并且写下所有的故事。这个人在互联网公司一般来说是产品经理。
不过,我们依然要想办法组建一个客户团队,这个团队中应该包括确保软件满足用户需求的所有人。
这意味着这个客户团队应该包括产品经理、测试人员、实际用户和交互设计师。
1.6. 使用故事的过程是怎样的?
对于故事驱动的项目而言,最引人注目的是客户团队在项目整个过程中全称参与,我们不希望(或者不允许)他们在项目进行时离开,不管团队是否在使用XP、Scrum之类的敏捷过程或开发人员自己发展出来的故事驱动的敏捷过程。
客户团队应该在编写用户故事时承担着非常活跃的角色。
编写用户故事的过程最好从考虑系统的用户类别开始。
例如,如果是在构建一个旅行预订网站,你可能会有诸如经常旅行者、假期计划着等用户类别。客户团队应该尽量包括了这些实际的用户类别。
可以参考使用用户角色建模。
1.6.1. 客户团队为什么要编写故事?
有客户团队而不是开发团队来编写用户故事主要基于两个原因。
- 每个故事必须用商业语言来写,而不是技术用语。这样一来,客户端团队可以排列故事的优先级,放入迭代和发布。
- 作为主要的产品构想者,客户团队所处的位置最适合描述产品行为。
1.6.2. 通过故事评估效率
一个项目的用户故事初稿,肯定是在一开始就要写好的,但是用户故事可以项目生命周期的任何时候编写。
在每次迭代结束时,开发人员将负责发布完全可用的应用程序子集。客户团队在迭代周期间高度参与,与开发燃油谈论迭代期间正在开发的故事。
在迭代期间,客户团队也会详细定义测试,并且和开发人员一起编写运行自动化测试。此外,客户团队要保证项目能够达到交付所需产品的目标。
一旦确定了迭代长度,开发人员就会评估每轮迭代中可以做多少事情。我们称之为速率(velociry
)。
团队第一次的速率评估可能是错误的,因为无法事先知道团队的速率。然而,我们可以用初步估计来勾勒出大致的蓝图或者发布计划,用以说明在每轮迭代中会完成哪些工作,需要多少轮迭代周期。
在每轮迭代开始前,客户团队可以在中图修正计划。当迭代结束后,我们可以得知开发团队的实际速率,然后用它来代替估计速率进行估计。这意味着每一堆故事可能需要通过增加或者移除来进行调整。
有些故事可能比预期的简单很多,所以有时开发团队想在迭代中完成另外的故事。但有些故事比预期的难,这是就要把有些工作移到下一轮迭代或者下一个发布计划中去完成。
1.7. 规划发布和迭代
一个发布由一个或多轮迭代组成。
发布规划指的是确定项目实际表和预期功能集合之间达到平衡。
迭代规划涉及选择迭代包含的故事。
客户团队和开发人员在发布和迭代规划中都要参与。
在进行发布规划时,客户团队首先从排列目标优先级开始。在排列优先级是,需要考虑下面几点。
- 大部分用户和客户对特定特性的渴望程度
- 小部分重要客户和用户对特定特性的渴望程度
- 故事之间的关系。例如,“缩小(
zoom out
)”这个故事的优先级可能不高,但是它可能被看做高优先级的,因为它和高优先级的另一个故事“放大(zoom in
)”互补。
在许多故事的优先级上,开发人员可能与客户团队意见相左。他们可能基于技术风险方面的考虑,或者由某个故事是其他故事的互补故事,而建议更改故事的优先级。客户团队应该倾听他们的观点,但是随后排列故事优先级时,应该坚持客户组织利益最大化的原则。
排列故事优先级时不能不考虑它们的成本。故事的成本由开发人员给出的,每个故事用故事点来估计,故事点表明了一个故事相对于其他故事的大小和复杂度。
一个4个点的故事成本是一个估计2个点的故事成本的2倍。
为发布中的所有迭代分配故事后,发布计划便浮出水面了。当开发人员陈述他们所预计的速率,在每一轮迭代中他们认为可以完成多少故事点。然后客户团队把故事分配到迭代中,他们要确保每轮迭代中分配的故事点数不超过开发团队预期的速率。
比如开发团队的预期速率是13,没有迭代可以完成多于13个故事点的故事。这意味着第二轮、第三轮迭代只能计划12个故事点。(很少有非常精确,这点差异不会造成什么影响)
除了在迭代中临时跳过一个大的故事而放入一个较小的故事以外,可以把大故事分成两个小故事。
假设5个故事点的故事I可以作为故事Y(3个点)和故事Z(2个点)。现在故事Y包含故事I的最重要部分,就可以在当前迭代中引入故事Y。
1.8. 什么是验收测试?
验收测试是用来验证实现的用户故事是否符合客户团队的期望。
当一轮迭代开始,开发人员开始编码,同时客户团队开始测试工作。测试工作可以报考从故事中写下测试描述开始,将测试放入到自动化测试工具中的所有工作。客户团队中应该包含一个专业的、熟练的测试人员,由他完成这些任务中偏技术的工作。
测试工作应该尽早的在迭代中编写(如果能大致猜到即将开始的迭代会产出什么,就可以在迭代开始前编写测试)。
早期编写测试是非常有用的,因为这样一来,客户团队的假设和预期就会更早与开放人员沟通。
例如,写下故事“用户可以用信用卡为购物车中的物品付款”,然后可以写下这些简单的测试描述.
- 用Visa信用卡、万事达信用卡来测试(通过)
- 用公交卡测试(失败)
- 用Visa借记卡测试(通过)
- 用有效、无效和反面丢失卡ID号的信用卡测试
- 用过期卡测试
- 用不同购买金额测试(包括超出信用卡额度)
尽早把这些测试交给开发人员,客户团队不仅仅澄清了他们的预期,也同时提醒了开发人员可能会忘记的场景。
1.9. 为什么要变成用户故事?
为什么要编写用户故事,并进行所有这些对话呢?
相比较其他方法,用户故事有比较多的优势,比如:
- 用户故事强调对话交流而不是书面沟通
- 用户故事可以同时被你和开发人员理解
- 用户故事的大小适合做计划
- 用户故事适用于迭代开发
- 用户故事激励推迟考虑细节,直到你非常清楚地了解自己的真正需求
由于用户故事的重点从文档转移到对话,所有重要决策不会写在文档里,因为很可能没有人阅读哪些文档。取而代之的是,在自动化测试中捕获用户故事的重要信息,频繁执行进行验证。
除此之外,我们还要避免在文档中出现下面含义不清的语句:
- 系统必须存储地址和办公电话或移动电话
上面的描述是什么意思呢?它可以理解为系统必须存储:
- (地址和办公电话),或者移动电话
- 地址和(办公电话或移动电话)
再次强调,由于用户故事不会有技术术语(它们是有客户团队编写的),所以开发人员和客户团队双方都能理解。
每个用户故事都代表一个独立的功能,即用户在一个单一环境中可能做的事情。这便使用户故事成为一个非常合适的计划工具。你能够估计在不同的发布中挪动故事顺序(优先级)的价值,这远远比估计去掉一个或多个“系统应该...”的陈述所产生的影响容易。
迭代过程是一个逐步求精的过程。开发团队首先开发系统中一小部分,知道它在某些(或许很多)方面是不完整的或者不完善的。然后在逐步加以相应的改进,直到产品让人满意。
通过每轮迭代中增加的更多细节,软件被逐步改进。用户故事和迭代开发可以紧密结合,因为故事也是可以迭代的。
对于最终需要但当前并不重要的特性,可以写下一个大的故事(史诗故事Epic
)。准备好将大故事加入系统之后,便可以提炼它,抛弃史诗故事继而使用更小的,更具体的故事代替它。
“故事集可以迭代”这一能力,恰恰可以佐证我们可以推迟考虑故事细节。
因为假如你可以今天写下用于占位的史诗故事,就没有必要再进一步写下系统这部分的用户故事,除非马上就要开发那些部分。
推迟细节很重要,因为这样一来,我们在不确定是否真正需要某个特性时,可以不花过多的时间来考虑它。使用故事,我们不必假装可以事先知道并写下所有东西,以客户团队和开发人员的讨论为基础,不断精炼我们的需求。
1.10. 小结
- 故事卡包含对用户或客户有价值的功能和简短描述
- 故事卡是故事可见部分,但客户团队和开发人员关于故事的对话更重要
- 客户团队包括那些确保软件符合潜在用户需求的人,可以包括测试人员、产品经理、实际用户和交互设计师
- 故事卡有客户团队编写,因为他们最了解如何表达需要实现的需求,也因为他们会在后期与开发人员共同确定故事细节并安排故事的优先级顺序
- 按照故事对客户的价值来安排故事的优先级顺序
- 将各个故事放入迭代,进行发布和迭代规则
- 效率是开发人员可以在一轮迭代中完成的工作量
- 如果故事太大以至于无法在一轮迭代中完成,可以考虑把它分成两个或更多的小故事
- 验收测试用于验证实现的故事是否开发成符合客户团队的设想
- 用户故事是很有意义的,因为它们强调口头交流,你和开发人员都可以理解,可用于进行迭代计划,子啊迭代开发过程中能很好的工作,而且它们鼓励推迟细节