【不要错过文末彩蛋】
用户故事拆分是敏捷实施的入门实践——没有用户故事拆分,就没有真正意义上的迭代,也就没法做到敏捷所倡导的快速反馈、快速学习和快速价值交付。
INVEST 原则常常被看做是用户故事拆分的基本要求[1]。但是,不少敏捷团队在如何获得 INVEST 原则所要求的用户故事方面仍然感到困惑。一些常见的情况是:用户故事拆不开,没法在一个迭代内完成;拆开了的用户故事,支离破碎,很难被管理;用户故事变成了内部的技术需求,不能做到端到端,成了只有研发团队关心的“故事”。等等。
存在一些比较流行的用户故事拆分原则。但是,在过去几年中,我们似乎已忘记了用户故事拆分这个实践。当我们进行需求澄清的时候,通常是一个实例化需求工作坊结束,完全符合 INVEST 原则的用户故事就已经在那儿了。
我们将通过这篇文章来分享我们的一些经验,也希望帮助仍然纠结于怎么写出小的用户故事的敏捷团队,能通过更小的代价和更有序的方法来获得高质量的用户故事。
用户故事和反模式
用户故事是一个来自于极限编程(XP, Extreme Programming)的实践。今天,用户故事的应用范围早已超越了 XP——无论是 Scrum,还是看板,用户故事都作为需求的基本形态被广泛运用。在 Scrum 中,用户故事扮演了 Product Backlog Item (PBI) 的角色,而看板中的流动的价值单元(Value Unit),也往往是由用户故事来扮演。
说到用户故事,浮现到脑海里的第一个印象是什么呢张像这样的索引卡片/p>
事实上,协商的困难,大多数时候真的不是市场方不通情理,而实在是交付团队所能提供的交付灵活性太少了。
在上面的图中,如果把实线框中包括的总面积看作是迭代所交付的价值的话,那么未拆分的需求显然降低了价值交付能力。延迟了价值交付,同时也降低了端到端的反馈和学习能力。这是我们不想看到的。
“拆分”的困难
存在一些比较流行的用户故事拆分模式。例如[3]:
-
业务规则:首先实现业务规则的一个子集。
-
数据:首先完成和一部分数据的相关的功能。
-
界面接口:首先完成一部分界面或接口,然后支持其他类型的界面或接口。
-
简单/复杂:首先完成核心、基本的业务价值,然后完成其它的。
-
操作:区分配置和查询等等。
-
工作流的步骤:首先完成工作流步骤中的一部分,然后完成其他部分。
-
非功能需求:区隔非功能需求的实现。
没错,这些规则都对,都是我们可以考虑的维度。但是,在实际中执行的又是如何呢—实际情况是:只要看一下这些模式中提及的术语,就能体会到其中的困难。“业务规则”、“数据”、“界面和接口”、“简单和复杂”、“操作”,等等。
本质上说,人类的大脑并不那么善于掌控复杂性,而这些堆积起来的术语,往往只有经验非常丰富的团队才能理解的很透彻。但是还不仅如此,真正困难的还不是掌握这些拆分规则。概念是有些复杂,但是熟能生巧,勤学苦练,总归能学会了吧。应用这些模式的最重要的困难是:你怎么才能发现存在哪些“业务规则”、“数据”、“界面和接口”等等,然后把它们用于拆分/p>
大多数失败的拆分,不是由于拆分故事的技巧不足造成的,而是对信息量不足,也就是对需求本身的探索不够所导致的。没有清晰定义的业务规则,没有清楚的数据描述,…
沟通和探索才是本质
现在让我们回到 Ron Jeffries 的 3C 原则。对于用户故事来说,除了 Card, 还有更重要的 Conversation 和 Confirmation 。如果用户故事的“撰写”、“拆分”都是由团队中的个人完成的,那么无论是不是采取了故事卡片的形式,无论是否进行了拆分,它其实和传统的需求分析方法没有什么区别。真正有别于传统需求方法的,是我们可以通过一组有序的工作步骤、通过协作,从看似模糊、混乱的业务需求中梳理出清晰的脉络,并以此指导后续的开发活动,当然也包括了用户故事的拆分。
这里我们援引 Mike Cohn 在《用户故事和敏捷方法》[4]中对 3C 的概括:
-
一份书面描述,用于做计划和提示。
-
关于故事的对话,具体化故事细节。
-
测试,用于表达和编档故事细节,并且用于确定故事何时完成。
Ron Jeffries 说到了用户故事应该 Conversation,应该 Confirmation,但是并没有就 conversation 和 confirmation 的具体方法给出建议。当然 Ron Jeffries 关于 3C 的文章发表于 2001 年,那时也还没有太多成熟的实践来支撑 3C 的目标。
实例化需求给出了一个需求澄清活动的更好方式。在过去的很多项目中,我们通过实例化需求来实现Conversation 和 Confirmation,达到了很好的效果。
实例化需求的核心是需求
“实例化需求”不是接收测试驱动开发(ATDD),用 Cucumber 或 RobotFramework 写测试吗能有同学会产生这样的疑问。
确实,有不少公司和团队都声称他们在采用“实例化需求”的实践,但是具体的做法却可能大相径庭。单单“实例化需求”这个术语,也存在3个不同的近似词语:“实例化需求(Specification By Example, SBE)”、“接收测试驱动开发(Acceptance Test Driven Development, ATDD)”、“行为驱动开发(Behavior Driven Development)”。Gojko Adzic在他的书籍《实例化需求:团队如何交付正确的软件》中给出了关于这3个概念的辨析,在此不在赘述。但毫无疑问的是:
在我们的实践中,实例化需求的核心关注是”需求“,而不是“测试”或者“开发”。只是说,如果没有开发和测试的参与,需求没法达到所需的质量。通过需求、测试、开发的对话,通过使用实例进行澄清,才能获得高质量的需求。这恰恰是和用户故事的3C匹配的。
产生哪些输出/h3>
Gojko Adzic 给出了关于实例化需求的9个过程模式:从目标获取范围、协作产生需求说明、举例说明、提炼需求说明、在不修改需求说明的情况下实现自动化验证、频繁验证、以及演化出一个活文档系统。这 9 个过程模式涉及了如下的输出(制品):目标和范围、需求说明、例子、自动化测试及活文档系统。
只是泛泛的提及上面的制品,仍然不足以看出为什么实例化需求能有效支持用户故事的澄清和分解。在实践中,我们所产生的“需求说明”的更具体体现形式是:
-
工作流
-
领域模型
-
业务规则
后面让我们通过举例来对三者进行详细阐述。
1. 工作流
工作流也称为业务流程或业务场景,是用户通过一系列步骤,达成系统业务目标的一种实现方式。在实例化需求工作坊中,参与人员在白板上使用顺序图、活动图、带有泳道的活动图等方式,共同绘制出工作流。当然,如果工作流足够明显,也可以直接采用业务用例的形式,列出标题,理清它们之间的先后关系即可。
整个过程中,尽量使用白板而不要使用计算机。这其实是一个技巧。当把工作流在白板上建模出来时,可以把参与讨论的人的关注点收敛到一起,从而共同进行讨论和发现问题。也正是如此,我们强烈建议“不使用软件工具进行建模”。它不容易创造沟通的焦点,或者说,使用计算机建模会创造出一个不正确的焦点——正在操作计算机的同事。 在整个过程中,描述是次要的,核心是对话和验证。一个讨论的场景如下图:
或者就是简单地采用列表的形式,列出几个相关的用户场景:
-
新开通一个子代理商。
-
为子代理商充值。
-
为子代理商修改密码。
-
修改子代理商的基本信息。
-
查询子代理商列表。
-
…
绘制工作流的目的不是为了描述,而是为了信息发现和挑战(challenge, 这里是褒义),即既有的工作流是否合理,是否存在遗漏,是否需要进一步讨论其中的业务数据和业务规则,等等。
在上面的工作流中,我们可以看到的挑战包括:
-
子代理商的初始化密码怎么设定/p>
子代理商首次登录时是否要被提示修改密码/p>
子代理商可以自己添加用户吗/p>
子代理商的基本信息包括哪些些信息需要校验/p>
是否需要在创建时就为子代理商进行充值/p>
创建的子代理商可以进一步创建子代理商吗/p>
-
…
回答上述挑战的过程,事实上是一个需求澄清的过程,它也会对应的更新工作流、领域模型和业务规则。在进行挑战和回答挑战的过程中,也一般都会包含了对每个业务流程或规则背后的业务价值的讨论,以及紧急程度的讨论。例如:
-
密码的一般性规则(例如必须包含特殊字符)是否要适用于初始密码会不会对线下过程带来困扰/p>
我们为什么要把联系人和管理员区分开/p>
在我们的当前阶段,能否延迟支持代理商的多管理员功能/p>
-
…
在上述案例中,一个可能的讨论结果是:代理商的多管理员功能虽然是需要的,但是在当前阶段可以暂缓实现,等等。
下面是一个带有稍微有些复杂的使用带有泳道的活动图描述工作流的例子:
有了上述的模型,当我们在讨论中说到代理商基本信息的时候,所有人就都知道哪些是基本信息。说到子代理商的时候,所有人都知道子代理商其实也是一个代理商。这其实就是领域驱动设计(Domain Driven Design, DDD)中所讲述的“统一语言”的应用。
同时,领域模型带来的统一语言,使得业务规则讨论变得更加精确,也更加高效。
例如:
如果子代理商权限为”无“,则代理商不能创建子代理商。
代理商可以查询子代理商的基本信息。
像上面的这种模型如何获得管存在各种各样的方法,例如关注需求描述中的名词等等,但是可以肯定的一点是,模型是通过讨论获得的。它是持续演进的结果。这个过程常常是这样一个模式:1)发现既有词汇不足以表述需求,或者发现参与人员在过程中产生了困惑; 2) 试图提出一些关于新的词汇的假设,对既有模型进行修正和补充 3)辩驳这些假设;4)修正,推翻,达成一致。 词汇存在歧义是一个常见的问题,这类问题如果不通过讨论,很难快速取得一致。上述模型的达成过程事实上首先是在白板上完成的:
关于举例,我们不准备过多赘述。只提及一点:具体的东西永远比抽象的东西更容易激起讨论,更容易发现原本未注意到的重要因素。
回到“用户故事”
在上述的实例化需求工作坊中,用户故事扮演了什么角色们并没有去“拆分”用户故事。我们在“讨论”用户故事。讨论使得用户故事的工作流、业务规则都已经足够详尽。事实上,现在不是用户故事拆不开的问题,而是要多细节,就有多细节,也许我们发现,为了方便管理,有些场景下还可能需要做一些小的归并。无论如何,迭代项怎么划分的自主权已经完全把握在工程人员手中。
例如,我们可以选择首先实现一个工作流的主干部分,可以选择首先实现工作流的一个业务步骤,可以选择首先实现几条业务规则,推迟后续几条业务规则,等等。
值得说明,并不是需求的所有情况都讨论完毕,才能开始迭代,需求只要有了一个完整的例子就能开始迭代。尚未讨论完全的情况可以视作模糊的东西在迭代中做探索。即便是简单的例子,在程序开始开发后也能发现问题。通过完成一些例子反而能够更好辅助后面未讨论完全的场景明晰起来。在项目开始阶段实例化需求工作坊会比较密集,但是这样的讨论每个迭代都应该持续发生,用户故事卡片,是一种占位符(Card),能够持续推动活动进行。
结论和建议
我们建议放弃“用户故事拆分”这个术语。“拆分”这个词语带来了一种暗示,似乎需求本来是一大块完整的东西,只是为了适应基于迭代的敏捷开发,才需要人为的把它切开。不是的。这不是事实。
真实的情况是:需求原本就是由一大堆彼此缠绕的细节构成,它们需要被辨识,而不是需要被拆分。无论它们是否已经被辨识到,这些细节都隐藏在哪里,甚至比你原本想象的要更细微,更复杂。我们需要一种有效的认知手段,把它们从需求的重重迷雾中发掘出来,识别、澄清、归类这些细节,然后按照价值大小、成本高低、依赖关系等因素为它们分配优先级,成为可以在开发迭代中持续流动的价值单元。
-
[1] Bill Wake. INVEST in Good Stories, and SMART Tasks. http://xp123.com/articles/invest-in-good-stories-and-smart-tasks/
-
2 Ron Jeffries. http://ronjeffries.com/xprog/articles/expcardconversationconfirmation/
-
[3] http://agileforall.com/wp-content/uploads/2012/01/Story-Splitting-Flowchart.pdf
-
[4] Mike Cohn. 用户故事和敏捷方法
-
[5] Gojko Adzio. 实例化需求: 团队如何交付正确的软件
-
吴穹, 资深创新管理顾问,精益看板专家。
-
张刚, 资深架构师、敏捷顾问,专注于领域驱动设计、微服务、实例化需求等在企业的落地实施。
-
雷晓宝,工程实践顾问,专注企业软件设计、测试自动化,开发生产力等领域。
彩蛋
重磅 Chat 分享:
《高效学习,快速变现:不走弯路的五大学习策略》
分享人:
一名会在 B 站直播写代码,会玩杂耍球、弹 Ukulele、极限健身、跑步、写段子、画画、翻译、写作、演讲、培训的程序员。喜欢用编程实现自己的想法,在 Android 市场上赚过钱,有多次创业经历。擅长学习,习惯养成,时间管理。身体力行地影响他人做出积极的改变!目前就职于 ThoughtWorks,致力于传播快乐高效的编程理念。业余创立软件匠艺 区 CodingStyle.cn,组织超过30场技术活动。Chat简介:
说到学习呀,真是头大哟:碎片化,没有较长的连续时间来学习难专注,捧起书,手机却在召唤:来呀,快活呀~ 反正有,大把时光~做不到,看了很多书,生活中却做不到然并卵,学了方法和工具,找不到使用场景效率低,学习速度跟不上知识产生的速度记不牢,学习速度赶不上遗忘速度在这个知识泛滥、跨界竞争的年代,学习能力才是核心竞争力。你想想,过去一周,有没有哪一件工作是不需要学习就能完成的管如此重要,大部分人却没研究过学习这件事,以为上下班路上打开「得到」听本书,就是碎片时间终身学习者了。我是程序员,咨询师,培训师,这几个角色都要求我必须学得又快又好。本场 Chat 将分析学习的「趋势,原则,策略」,帮你站在更高的视角看待学习,从「内容,动机,交互,收益,资源」五方面制定策略,解决学习痛点,助你成为高效学习者!

声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!