优点和好处
- Being very short. They represent small chunks of business value that can be implemented in a period of days to weeks.
- Allowing developer and client to discuss requirements throughout the project lifetime
- Needing very little maintenance
- Only being considered at the time of use
- Maintaining a close customer contact
- Allow projects to be broken into small increments
- Suited to projects where the requirements are volatile or poorly understood. Iterations of discovery drive the refinement process.
- May be easier to estimate development effort
User Story模板
User Story可以遵循以下模板:As a <User Type> I want to <achieve goal> So that I can <get some value>
翻译成中文就是:作为一个<某种类型的用户>,我要<达成某些目的>,我这么做的原因是<开发的价值>。
User Story应遵循INVEST规则
- Independent 独立性,避免与其他Story的依赖性。
- Negotiable 可谈判性,Scrum中的story不是瀑布开始某事中的Contract, Stories不必太过详细,开发人员可以给出适当的建议。
- Valueable 有价值性, Story需要体现出对于用户的价值
- Estimable 可估计性,Story应可以估计出Task的开发时间。
- Sized Right 合理的尺寸, Stories应该尽量小,并且使得团队尽量在1个sprint(2 weeks)中完成。
- Testable 可测试性, User Story应该是可以测试的,最好有界面可以测试和自动化测试。每个任务都应有Junit Test.
一些经验:
- 永远不要在User Story中使用And和Or,因为这是些分支词就表示分支任务,把它们拆成两个Story.
- 数据整理:通常情况下1个sprint(2周一次迭代)可以做4~5个Story,极端大的Story不可大于1个sprint。
- 数据整理:通常情况下1个sprint(2周一次迭代)可以做50个左右的Task。
- User Story用于描述用户故事,不要包括任何的技术,框架等内容。Task可以包括框架,技术等内容。
-
敏捷需求分析
在很多人的印象中,敏捷软件开发是种类似黑客行为的过程,是程序员最爱的勾当。不写文档,不作需求分析,没有项目经理,做什么东西完全是程序员自己的行为。所以他们认为这样的过程无法满足真正大型项目和复杂项目的需要,因此在经过考虑后,放弃了敏捷方法。
真的是这样吗?敏捷过程到底是如何做需求分析?用户故事和用例有什么区别?敏捷过程如何去管理需求的?这些是一些想要实践敏捷的人一直在困惑的事情。
我们常常看到书中讲,程序员拿到一个用户故事后,怎么计划,怎么分解,怎么写单元测试,怎么小步前进,怎么持续集成。这是典型的程序员视角。事实上,敏捷方法分为三部分,敏捷项目管理,敏捷需求分析,敏捷软件开发。上述书中提到的完全是敏捷开发中的实践,很多人了解到的敏捷,只是敏捷的三分之一。
在敏捷的团队中,作一个敏捷程序员确实是非常舒服的事情。从程序员的角度来看,只需要选择一张他感兴趣的故事卡片,了解清楚该卡片的需求,开始从功能测试写代码,等通过了所有测试就完工。基本上不需要考虑太多的事情,非常轻松愉快。但程序员向谁去问清楚需求?故事卡片是怎样写出来的呢?让我们来关注开发前发生的事情。
了解敏捷过程的人都知道,Kent Beck在XP过程中提到了现场客户,如果一个敏捷团队能够有现场客户,这当然是最棒的事情。但多数情况下,客户都是很忙碌的,很难全力投入到软件开发过程中。这时候,我们就需要商务分析师这个角色,来充当客户的角色。
我在ThoughtWorks的团队中担任的就是商务分析师这个角色。商务分析师最重要的职责就是与客户交谈,了解和分析需求,将其制作成用户故事并将需求转述给程序员。同时,商务分析师也要代替客户负责功能验收测试。
敏捷思想的核心是人与交流。需求问题实际上是一个交流问题。商务分析师要和客户交流,搞清楚客户到底需要什么,到底为什么需要这些东西。商业价值是商务分析师关注的最终目标。有了目标的指向,就可以不迷失方向。和客户进行交流,最终目的就是挖掘出客户的商业目标。可能大家会经常有这样的经验,客户说,我要这个功能,我想要怎么怎么样。这时候要特别注意,他说的这些东西并不是真正的需求。商务分析师需要详细的问客户为什么,挖掘出他真正的目标。
在这个目标下,商务分析师开始进行需求的分析:我们到底是否真的需要这个需求?有没有更好的解决方案?有没有简单并且低廉的方式?换一种形式是不是也能达到这样的需求?这个需求有多少地方涉及到以前的软件变更?
搞清楚这些事情后,就可以写出用户故事。用户故事的书写遵循一定的原则,一般包括三部分:"作为(系统的一个涉众),我想要(做一件事),从而(达到一个商业价值)"。在书写的时候格式比较随意,可以在故事卡背面写上注释或疑问,甚至画上界面原形图。
举一个最常见的用户故事例子,"作为一个普通用户,我希望能够用用户名和密码登录,以便我能享受到个性化的服务"。其中,用户是系统涉众,登录是他想要做的事情,而他的目标是获得个性化的服务。
从这个例子我们可以想象到,这个页面可能存在两个文本框,用于输入用户名和密码,有一个按钮来登录,并且不登录就不能看到个人资料,另外,如果用户输入错误需要提示"登录失败请重试"。这就是可见性,也可以称为可测试性。我们可以根据这样的可见性写出功能测试,从而驱动这个用户故事的开发,这被称为 Acceptance Driven Development。
用户故事的作用有两个,一个是作为进度跟踪的依据,一个是作为与人交谈的备忘录。用户故事卡片并不是很精确的需求,因此不需要把事情描述的非常清楚。将需求的详细分析推迟到实现前夕来完成,这是敏捷需求分析的精华所在。任何提前做好的东西都会导致浪费,敏捷过程提倡足够就好,避免浪费。
不少人对用户故事和用例的区别感到疑惑。用户故事的作用是备忘功能,而不是文档。而用例需要详细的描述其操作步骤,以及每个异常路径,因而起到了文档的作用。用户故事是可见的商业价值,而不是功能描述。每个用户故事的粒度和工作量都相差不多,这和用例有很大的区别。用户故事是小粒度的,可测试的,可见的,并且是有价值的。[注:此处存有争议,请读者辨证阅读,勿断章取义]
ThoughtWorks有个项目组作的是一个网游物品交易平台。该平台是典型的互联网项目,在开工的时候客户对功能需求还不明确,但需要快速推出抢占市场,正是最适合敏捷过程的项目。
在项目伊始,商务分析师和客户做了深入的谈话,了解他的商业构想,他的盈利模式,搞清楚宏观的结构,然后思考并整理获得的结果,花1-2天时间将客户需求大略整理为几十个用户故事。这些用户故事并不完善,不足以做好整个系统。但对于我们开始项目的前一阵,已经足够了。我们可以从这里开始项目。
敏捷方法希望快速交付可用的软件。实现软件的快速交付是通过迭代来完成。在迭代开始前,由一组有经验的开发人员大致评估一下用户故事,标记出不同的难度和风险,并提出问题供商务分析师来获得更详细的信息,商务分析师会和相关涉众去讨论。然后商务分析师将推荐优先级最高的一组用户故事给客户来挑选,客户可以选择这些用户故事,或者指出从他的视角看到的优先级更高的用户故事。这些将成为下一个迭代的内容。
客户看到每个迭代交付的可运行的软件后或者得到用户反馈后,常常会有新的想法冒出来。有些想法是好的,有些想法就属于看到别家网站有这个功能,不假思索的提出的功能。这些不同的需求都需要经过认真的分析,找出哪些是值得我们立即考虑的,哪些是不用急迫的去实现的。
有一次和客户谈话时,他说到希望增加拍卖功能。那么,我们为什么需要拍卖呢?客户说希望让用户拍卖物品以获得最高价格。经过考虑,我们发现,网游物品的实时性和唯一性决定了系统不适合使用拍卖机制。拍卖的时效性无法满足实时交易的要求,因此,用户最终放弃了这个特性。
另一次,客服人员提出增加一个查询用户交易的功能,而此时我们有其他更加重要的功能需要先去考虑,查询用户交易功能可以由技术人员临时通过数据库直接代为查询,因为项目运营初期交易不是很多,暂时还不需要专门的后台功能来支持客服的工作。所以把这个需求卡片一直贴在墙壁上,始终没有排到最高的优先级。
客户一开始也不是很能够接受敏捷需求中强调商业价值和优先级的做法。但经过几个月的磨合,客户也逐渐适应了许多敏捷思想,甚至我在和客户讨论时,偶然提起了后期的某种可能的情况,他们还能够帮我纠正应当考虑目前的情况,为近期的情况作计划。
用户故事的跟踪和管理是由项目经理来进行。每个迭代跟踪卡片的进展,是否已经开始实现?是否已经完成代码开发?是否已经开始功能测试?不同的卡片在迭代前都会评估为不同的大小。我们一般分为大中小三级。等实践过几个迭代后,团队的开发速度基本保持恒定,我们就可以很容易的知道每个迭代能做多少个用户故事,这样就可以安排下一迭代的开发。
每个迭代内分析好恰好足够下一个迭代开发的需求,就是商务分析师每个迭代的主要工作内容。商务分析师的需求分析工作在上一个迭代完成,包括需求的了解,分析,评估和排列优先级。
在每个迭代开始的时候,由商务分析师主持召开迭代计划会议,在会议上向所有的程序员解释这个迭代要完成的用户故事,然后由程序员自由提问,知道他们能够获得足够开始实现该功能的信息。
在程序员完成一个用户故事后,商务分析师还要来代表客户做功能验收测试,查看是否完成了预计的功能,是否有程序员还没有想到的异常情况。如果存在问题需要退回给程序员继续完成。这在一定程度上保证了系统完成的需求不偏离客户的要求。当然,更多的测试还需要QA来完成。
我们的实践充分表明了,敏捷过程并不是没有需求分析,而是把需求分析过程分散到整个开发的过程中,让开发和需求分析并行进行。这就是ThoughtWorks敏捷方法实施成功的秘诀之一。而商务分析师在这个过程中,起到了纽带和桥梁的作用,是一个团队不可缺少的角色。
User Story 在敏捷开发过程中的应用
1 从这里开始
第一部分我们将快速浏览什么是user stories以及如何使用,然后将阐述如何编写User Stories;如何通过系统用户模型来定义Stories;当客户自己本身无法前来的时候,如何同那些能够充当客户角色的人一起工作;如何来编写测试用 例,来证明你的Stories已经被成功编写的细节,最后将阐述几条编写好的Story的指导建议。
当你学完这部分之后,你就可以定义、编写、测试你的Stories,同时你应该准备去看如何通过User Stories去进行评估和计划,也就是第二部分的内容。
1.1 概述
软件需求是一个沟通的问题,想得到(或者使用,或者出售)新软件的人,必须和软件的生产者进行沟通。项目的成功与否,依赖于从不同的人那里得到的信息:一方面是客户、用户、分析人员、领域专家以及其他从业务或者组织角度来看待软件的人;另一方面则是技术团队。
如果任何一方控制了沟通,那么项目注定会失败。如果业务一方控制,则会要求功能和日期,而不太担心开发人员是否能全部完成或者开发人员是否明白他们的真正要求;如果开发人员控制了沟通,技术术语会代替业务语言,开发人员也失去了通过倾听来了解客户真正需求的机会。
我 们需要一种方法让大家一起合作,以至于沟通不会被单方控制,并且资源分配中的感情因素和原则问题就变成了双方共同的问题。.当资源分配完全倾向一方的时 候,项目就会失败。如果开发人员全权负责(无论怎样都必须在7月份之前全部做完),他们可能会因为一些附加的功能而牺牲质量,或者只实现部分功能,或者独 自制定本该客户或用户参与制定的大量的决定。当客户和用户方全权负责,项目前期就会出现一个漫长的讨论过程,在这个过程中越来越多的功能被从项目中删除, 当软件被交付的时候,甚至实现的功能比删掉的功能少。
我们已经知道了我们不能够完美 的预言一个软件开发项目。当用户看到软件的初版时,他们会产生一些新的想法,改变一些他们原有的想法,由于软件的不可把握性,开发人员进行时间估算变得非 常困难。由于种种原因,我们无法罗列一个完整的PERT图表来显示我们在项目里所必须完成的全部工作。
那么,怎么办?
我们经常通过手头已经掌握的资料来做决定,会好过在项目初期就做出所有的决定。我们把做决定分散到整个项目过程中。为了做到这一点,我们要确认已经有一个尽早尽多获得相关的资料的程序。User Stories 由此而生。
1.1.1 User Story 是什么?
User story是对软件的用户或买主有价值的功能点的描述。User stories 由以下三点组成:
· 用来制定计划和作为提醒的一段书面描述
· 用来充实story的细节的谈话
· 测试用例,用来表达和记录细节并且能够在story实现的时候对进行验证
因 为User Story的描述是通过传统的手写记录在卡片上,所以Ron Jeffies给这三个方面起了很好的名字,Card(卡片),Conversation(会话),和Confirmation(确认)。卡片是 story最可见的表现形式,但是他不是最重要的。Rachel Davies 已经说过,卡片“重现客户需求场景好于记录它们”。思考User Stories的完美方法是:card 包含story的正文,通过会话得出细节,并记录在测试用例中。
User story 的例子,请参见Story Card 1.1
Story Card 1.1 是一个写在卡片上的初期的User Story
(用户可以在网站上发布简历)
为了保持一致,贯穿剩下的这本书的例子大多都是为BigMoneyJobs 网站而设计的。其他的例子故事可能包括:
· A user can search for jobs(用户可以查找职位)
· A company can post new job openings(公司可以发布新的职位)
· A user can limit who can see her resume(用户可以限制那些人可以查看他的简历)
因为user stories 描述了对客户来说有价值的功能点,所以对这个系统来说下边的例子就不是好的user stories。
· The software will be written in C++.(软件应该用C++来编写)
· The program will connect to the databasethrough a connection pool(软件应该通过连接池来连接到数据库).
第一个例子对BigMoneyJobs来说不是个好的user story是因为用户根本就不关心使用哪种编程语言。但是,如果这是一个应用程序接口,用户(他本身就是个程序员)写下“The software will be written in C++(软件应该用C++来编写)”就会很好。
第二个story在这种情况下也不是个好的user story ,因为系统的使用者并不关心应用程序如何连接到数据库的技术细节。
也许,你已经读了这些stories 并且很惊讶地说,“等等,使用一个连接池是我这个系统的一个需求” 如果这样的话,请一定要清楚,编写stories的关键点在于让客户认可他们的价值,我们将在第二部分“编写story”里看到一些关于编写Story方面的例子。
1.1.2 细节在哪呢?
说 “A user can search for jobs(用户可以查找职位)”是一件事情,而能否只靠这个作为指导就开始编码和测试却是另外一件事情。因为,细节在哪里呢?类似于下边的这些问题怎么办呢?
· What values can users search on? State?City? Job title? Keywords?(用户查询的条件是什么?州?城市?职位?关键字?)
· Does the user have to be a member of thesite?(用户必须是网站的注册用户吗?)
· Can search parameters be saved?(可以保存查询条件么?)
· What information is displayed for matchingjobs?(查询页面上应该显示哪些信息呢?)
· 许多类似的细节可以当作另外的stories来描述。实际上,多做几个stories 比做一个很大的stories要好。例如整个的BigMoneyJobs 网站可以用这两个stories来描述:
· A user can search for a job(用户可以找工作)
· A company can post job openings(公司可以发布职位空缺(好机会))
很明显,这两个stories太大了,大到没有太大用处.,在第二章“编写故事”中,完整的阐述了故事大小的问题。从一、两个开发人员花费半天或者两个星期来编写和测试一个story开始,是一个不错的起点。 公平一些来讲(Liberally interpreted),上边的两个stories简单的概括了BigMoneyJobs网站的大部分功能,,每一个大概要花费程序员多于一周的时间。
当一个故事太大的时候,他通常会被作为一个Epic(译者注:此词本意为史诗级的,我没有找到合适的汉语词汇表达,就是大的故事集的意思)提出.Epics可以被分割成两个或更多个小故事。例如,这个Epic“A user can search for a job(用户可以找工作)”就可以被分割成这些Stories。
· A user can search for jobs by attributeslike location, salary range, job title, company name, and the date the job wasposted.(用户可以通过地区, 薪水, 职位, 单位名称, 和职位发布日期 来搜索)
· A user can view information about each jobthat is matched by a search.(用户可以查看搜索出来的每个职位的详细信息)
· A user can view detailed information abouta company that has posted a job.(用户可以查看发布职位空缺信息公司的详细信息)
· 但是,当我们的story能够涵盖所有的细节时,我们就不再去分割story了。例如,故事“A user can view information about each job that is matched by a search”是非常适度和实用的。我们不需要再去把它进一步的像这样去拆分:
· A user can view a job descrīption.(用户可以查看职位描述)
· A user can view a job's salary range.(用户可以查看职位薪水)
· A user can view the location of a job.(用户可以查看工作地点)
总的来说,user story 不需要用专业的需求文档格式夸张的描述成下面这个样子。
4.6)
A user can view information about each job that is matched by a search.
4.6.1)
A user can view the job descrīption.
4.6.2)
A user can view a job's salary range.
4.6.3)
A user can view the location of a job.
比 坐在这里把这些细节写成stories更好的方法就是开发团队和客户来一起讨论这些细节。就是说,当这些细节比较重要的时候,就把他拿出来讨论。讨论后, 在卡片上添加一些注释是没有错的,就像Story Card 1.2.一样。可是,重点是会话,而不是story card上的笔迹。不管是开发人员还是客户都能够在3个月后还指着卡片说“看,我那时候是这么说的”。Stories并不承担法律责任。我们将看到,协议 通过可以证明某个story被正确实现的测试用例来记录。
Story Card 1.2. A story card with a note.
1.1.3 故事应该有多长呢?
当我上中学文化课时候,每当我们被指定去写一篇论文,我总是问“论文必须写多长呢?”老师是不喜欢这个问题的,但是我仍然认为这个问题是必要的,因为它告诉我老师期望的是什么。这个问题同样也是了解项目用户需求很重要的一点。这些要求最好以可测试的形势被捕获。
如果你使用的是纸质的笔记卡片,你可以把卡片翻过来,把需求写到背面。这些记录下来的要求提醒怎样测试这个story,就像Story Card 1.3所显示的那样。如果你使用的是电子系统,它应该有一个地方可以让你加进一些可测试性的提醒。
Story Card 1.3. The back of a story card holds reminders about how to testthe story.
测试描述是简短和不完备的,测试用例可以随时添加或者删除。目的是涵盖Story的附加信息,以便开发人员知道Story什么时候就算完成了。就像老师的要求对我来说很有用,我可以知道什么时候我写的关于Moby Dick的东西算完成了。它对于开发人员来了解什么时候完成了客户需求一样有用。
1.1.4 客户团队
对于一个理想的项目来说,我们会有一个专门的系统最终用户,他为开发人员区分工作的优先级,并回答他们的问题,编写所有的Stories。这个是太理想的 情况,所以,我们创建一个客户团队,这个团队里包括那些可以保证软件达到最终用户需求的那些人。这就意味着这个客户团队包括测试人员、管理人员、用户和交 互设计人员。
软件开发是一个从捕获客户需求到编码实现的过程。在我们传统的印象中,需求是厚厚的软件 规格说明书,实现则是无穷无尽的bug产生器。需求是在实现之前写好的,客户签字确认的。实现是程序员拿着需求不断猜测这该怎么做,那该怎么做的重新发现 的过程。在需求与实现之间横亘着一个巨大的鸿沟,做需求的人和写代码的人总是互相推诿责任,到最后客户总是得不到自己想要的功能。
敏捷软件开发方法有一整套实践,来促进客户与开发团队之间的交流与反馈。而User Story则是这些实践中比较具有启发意义的一个主要实践,我认为它是承上启下的重要一环。因为在其上,它是具体用户角色完成具体目标的过程组成部分。而 在其下,它是编写验收标准(Acceptance Criteria)的具体上下文。它就像一条锁链一样,在需求与实现之间架起了一座危桥。
之所以称之为危桥,是因为一旦人们把User Story当做软件规格说明书一类的文档来看待的话,User Story很快就不能反映客户的需求,同时也无法指导实现的开发。我们必须要把它当做危桥一样来对待,经常去重新评估实现难度,根据给客户带来的价值排优 先级。当发现它所覆盖的内容不再准确或者过时了的时候,对于危桥我们就不用犹豫,该炸掉重来就炸掉重来。
不严格地说,敏捷开发从需求到实现的单向流程(反馈的路径未包括其中)大概是这样的:
这个过程没有暗示任何瀑布式的开发风格,其实这个过程是反复的,不断有反馈回顾。画出这么一个流程性的图只是为了表明User Story是如何承上启下的。
要知道它是如何承上启下,还是要知道它自身是什么样的。明确的答案是:User Story应该Small(小规模),Testable(可测试),Valuable(有价值)。
Valuable是说User Story能够给利益相关人员提供明确的商业价值。往往表现为满足了用户某方面的预期。
Testable是说User Story可以给验收标准提供明确的上下文。也就是说这个User Story能够对程序的外部行为产生影响,比如界面,日志文件等用户看得见摸得着的东西。
Small是说User Story应该足够小,在商业过程中也就一步或者相关联的几步。小的目的是更好地符合迭代式开发的风格,能够在一个迭代内完成。
这三个特性直接支撑了敏捷开发的一些核心价值:给客户提供价值(对应valuable),保证质量(对应testable)和快速响应变化(small)。
User Story与传统的Use Case有一些不同。某些Use Case的书籍中提倡写出不同层次的Use Case,有High Level的,有Medium Level的,也有Low Level的。从某种程度上来说,High Level相当于Goal,Medium Level相当于User Story,而Low Level相当于Acceptance Criteria。但是由于Use Case的写法缺乏统一的习惯和明确的指导。初学者在写Use Case的时候往往缺乏明确的目标,无法有效地把需求与实现贯穿起来。
因此,若把需求到实现看做从天空到湖底的话,User Story就恰好浮在水面上。可以说User Story是文档能够达到的最细节的层次,若在往下就陷入了实现的细节之中,与具体实现方式相关而且经常变动,维护起来非常困难。更重要的是,写出那样的 细节文档又不能执行,无法给客户带来价值,只是对代码的无味重复。
这里只是概览了User Story在整个开发过程中的位置和作用,以及其自身的的一些属性和它能提供的价值。具体使用User Story去实践敏捷开发可以参阅我同事李默所写的敏捷需求分析一文。他在文中以一个业务分析师的角度讲述了如何把User Story用在敏捷需求分析的过程中去。