「产品开发中如果只有一件最困难的事,那就是精确的决定做什么」,《人月神话》的作者布鲁克斯如是说。「需求」从来都是产品开发的重点和难点,对精益和敏捷产品开发也不例外。
许多精益敏捷实施的失败,在实践层面 [1] 都根源于缺乏有效的需求实践。实例化需求是我所知道的两个投入产出比最高的敏捷和精益需求实践之一 [2] ,它能有效解决精益敏捷实施中的需求的分析、澄清和拆分等问题。
本文的主旨是帮助大家,第一:理解实例化需求,介绍实例化需求的 Why 和 What;第二:实施实例化需求,介绍实例化需求的 Who,When 和 How。如此 4W1H,帮助大家掌握这一高效的精益和敏捷需求实践,并落实验收测试驱动开发(ATDD)方法。
一、理解实例化需求
为了理解实例化需求,我们将从实例化需求的目标(why)和核心概念(what)讲起。
1. Why:实例化需求的目标
实例化需求的目标可以概括为四个字——以终为始(Begin with the End inMind)。「以终为始」是《高效能人士的 7 个习惯》一书中的第二个习惯,指在开始一件事情之前,先明确其目标,再努力实现之。
对应产品开发,它指:开始开发前,充分澄清需求,明确其验收标准,并保证相关人员对需求的一致理解。
「以终为始」的反面是「GIGO」——Garbage In, Garbage Out(输入的是垃圾,输出垃圾)。这恰恰是很多精益敏捷实施的现状,极大影响团队交付的质量、节奏和最终业务成果。
敏捷开发团队中普遍以“用户故事”承载需求。
用户故事有两个核心作用:
- 它是交付的单元。用户故事应该是足够小的、端到端的可交付单元,基于它可以组织和规划迭代或持续交付;
- 它是沟通的载体。与传统的需求表述方式不同,用户故事中并不包含需求的详细信息,它只是对未来进一步沟通的承诺。
极限编程的发明人之一 Ron Jefferise 用 3Cs(Card,Conversation,Confirmation)来形容用户故事。
用户故事卡片(Card)上的内容有限,更多信息依赖于未来的沟通(Conversation),并最终确认(Confirmation)。
问题是如何才能有效沟通?确认什么?怎么确认?这是困扰很多敏捷开发团队的问题。传统的需求分析问题,在精益和敏捷开发中依然存在。
实例化需求既要解决传统上需求分析的问题,又要适应迭代和持续交付的模式,更加高效、有效和持续地沟通需求,做到“以终为始”。
2. What:实例化需求的核心概念
以终为始是目标,那实例化需求具体包含什么内容呢?实例化需求的英文是Specification by Example,简称 SBE,直译过来就是用实例说明。
为什么要用实例来说明需求?让我们从需求沟通中的一个最常见误区——知识的诅咒——说起。
知识的诅咒是指:人们在沟通时会不自觉地假设别人拥有和自己一样的背景知识,造成沟通的困难和误解。在陌生的地方问路,经常体会到「知识的诅咒」。
上图中,当地人告诉你:「噢,那家旅馆啊,前面左拐就到了」。但事实上,你需要走到第三个路口再左拐,然后穿过一个街区,再从巷口进去才是。
并不是当地人不够友善,而是他太熟悉这里了,不自觉地假设别人也有同样的背景知识,这就是典型的“被自己的知识诅咒”,而影响了与他人的沟通。
「知识的诅咒」在需求沟通中时常发生。我们经常会看到这样的场景,需求交付后,才发现场景的遗漏,或规则的错误。
对此,开发人员抱怨:「需求说明中并没有说要考虑余额不足啊」,或者说:「从来没人告诉我还有这种类型的交易啊」。
而业务人员却说:「这不是很明显吗?」。业务人员口中明显的事,对开发和测试人员可不一定。
为避免需求沟通过程中的「知识诅咒」,“实例化需求”方法从场景出发,以用户的操作实例来澄清需求。
相比一般的规格说明,实例更加场景化,能够激发参与和深度讨论;同时,实例是具体的,其典型形式是:「在什么情况下,做什么操作,会得到什么结果」。基于具体的实例,更加便于沟通中的双向确认,保证理解的一致和场景覆盖。
上图是对实例化需求的概念说明。
用例子来分析和澄清需求。
这些例子随后会转化为测试用例。
最后再通过测试验证需求。
如此形成闭环,这个三角是实例化需求的核心概念。
二、实施实例化需求
综合以上的内容,可以用一句化来定义实例化需求:
基于用户使用的实例分析和澄清需求,做到“以终为始”,为其后的持续需求交付提供高质量的输入。
概念并不复杂,而让实例化需求真正不同的是其实施过程的有效性。接下来将介绍实例化需求的实施,具体包含:Who:谁参与,When:什么时间做,How:步骤和方法。
1. Who:谁负责,实例化需求活动
管理学大师德鲁克曾说:「每一次信息传递会使信息减半,而噪音加倍」[3],德鲁克称之为信息学第一原理。
综艺节目中的传话游戏,常利用这一现象制造欢乐效果。在产品开发中,需求在逐级传递中同样会不断丢失信息和引入噪音,只不过它一点不欢乐,反而是很多误解和信息遗漏的根源。
在「实例化需求」中,开发、测试和业务人员一起沟通需求,避免信息传递的噪音和损耗。
如上图所示,开发、测试和业务三个角色是实例化需求的参与者,当然条件不具备时,业务可能是业务方的代表,比如业务分析师或系统分析师等。
通常开发、测试和业务会在足够大的白板或墙面前直接分析和沟通需求,上图是实例化需求沟通过程中的典型产出。
2. When:什么时候进行实例化需求
实例化需求是适合精益和敏捷开发的需求分析方法。与精益和敏捷所倡导的持续交付相对应,实例化需求应该持续和小批量的进行。这带来如下的好处:
接近实现阶段,此时团队拥有决策所需的最充分和最新鲜的信息,更能做出正确的决策,等开始实现时信息的保真度也足够。
因为很快就要实现,团队也会更加专注和投入,沟通更加充分。
即时进行,能够体现最新的变化,提高了对外响应的灵活性。
即时小批量的沟通是指导原则,具体到使用 Scrum 或看板方法的团队,则对应不同的活动。
如上图所示,Scurm 团队会在 Sprint 计划会议上澄清和承诺需求,这时进行实例化需求活动是较为合适的。同时,很多团队会引入产品待办事项的梳理(Product BacklogRefinement)机制,在当前 Sprint 的某个时间点梳理下个 Sprint 的内容。这时,在待办事项梳理会议上进行实例化需求活动更适合。
使用看板方法的团队,通常会进行有节奏的就绪队列填充,这也是团队的计划活动。
所谓「就绪」是指:需求已经准备好,可以开始实现了。如上图所示,在就绪队列填充前进行实例化需求活动,可以帮助团队分析、澄清、一致理解需求,并定义验收标准,做到名副其实的「就绪」。
3. How:实例化需求的实施步骤
接下来介绍如何组织实例化需求活动。需求的分析和澄清本质上是在挖掘和梳理需求的信息,并合理澄清和组织它们。下面,我们将从理清需求的信息结构出发,来组织实例化需求的实施步骤。
需求的组织和沟通要符合 MECE 原则
不管问多少麦肯锡校友(麦肯锡的员工和前员工),麦肯锡解决问题的方法中,哪些他们映像最深刻,答案都是 MECE,MECE,MECE。—— 摘自《麦肯锡方》
「MECE,MECE,MECE」重要的事情说三遍,MECE 是麦肯锡方法的最核心原则,它是思考、分析也是沟通和表达问题的逻辑。
MECE 原则指出观点和事实的表达,在各个层次上都要做到:
- 条目之间相互独立(Mutually Exclusive),通俗的讲就是要“分清”各个条目,做到无重叠;
- 这些条目作为一个整体要完全穷举( Collectively Exhaustive),也就是要“分净”,做到无遗漏。这两点合起来就是所谓 ME-CE
MECE 原则最早由芭芭拉.明拓在《金字塔原理》一书中提出的。问题的分析和表达符合 MECE 原则,就会呈现出金字塔结构——每个层次的的抽象级别清晰一致,各个层次向下逐渐明晰。
如上图所示,如果符合 MECE 原则,需求的信息也会呈现金字塔结构。
金字塔的顶端是需求的目标,也就是解决什么用户或业务问题?以及与之相关的上下文。
金字塔的中间层次是操作和操作流程,为了实现上面目标,系统需要支持哪些用户操作?这些操作的流程是什么样的?
金字塔的底层是业务规则,各个操作步骤对应的业务规则是什么样的?
以上三个层次自顶向下,逐渐明晰,形成的金字塔信息结构,确保信息的清晰、完整和一致性。
为了提高沟通的效率和效果,团队还应该在需求的分析和沟通过程中,持续构建和精化领域模型,并把领域模型作为沟通的统一语言。
领域模型是对领域中的概念或现实世界的对象的可视化表示,被被认为是面向对象分析最重要的产出。
领域模型虽不是实例化需求的必选项,但它能让需求的沟通和澄清事半功倍,让团队快速就问题域达成一致理解和高效沟通。
领域模型的构建和精化还为领域驱动设计(Domain Driven Design)和微服务(Micro-Service)的实施提供输入。它是今天的技术环境下,团队应该掌握和娴熟应用的技能。关于领域模型,后面还会更详细介绍。
实例化需求活动的步骤
需求的信息结构为实例化需求的实施步骤提供了指导。上图是我在实施实例需求时常用的组织步骤,它与需求的信息金字塔结构是一致的。下面将逐一介绍这些步骤。
第一步:澄清价值
实例化需求的第一步“澄清价值,它包含两个子步骤
描述背景。也就是需求的业务背景和系统的上下文。这一步形式相对*。上面的示例图中,我使用了面向对象分析中的常用的系统上下文图(SCD,System ContextDiagram),定义了系统的边界、所处的环境以及主要组成部分,你也可以使用更*的线框图来表达系统的上下文。
系统上下文相对稳定,并不需要对每个需求重复这样描述,只要在必要时(比如发生变化时),做出澄清就可以了。
澄清用户问题和业务目标。需求最终要解决用户的问题,从而实现产品的业务目标。因此,在讨论具体的需求前,我们还要澄清用户是谁,要解决他们什么问题。
针对目标和问题的典型挑战性检验是:如果不做这个需求会怎么样?有没有其它替代方法?认真回答上面两个问题,往往能挖掘出需求的本质,确保我们在解决的是真正的用户或业务问题。
第二步:列出操作并明确操作步
明确目标后,接下来就是分析为实现这一目标,产品所要支持的功能。实例化需求的第二步是:列举产品要支持的用户操作,并描述它们的流程。具体分为两个子步骤。
列出用户的操作。产品的功能体现为它所支持的用户操作,列出用户操作,可以涵盖其功能性需求。在上图中,我们通过用例图描述了用户的操作。
用例图定义了为完成特定目标,操作者和系统之间的交互,它包含操作者和操作两个部分。
用例是需求工程中获取和列举功能需求最常用的手段之一。如果不习惯用例的表示法,更简单的方法是直接列出用户和用户的操作。
画出用户操作的流程步骤。这一步的目的是:定义操作的具体交互流程。上图使用了活动图和时序图两种形式,来表达操作步骤。
其中,活动图形式上与流程图类似,只不过它表达的是用户操作流程,而不是技术实现流程;
时序图则在表达系统间的交互方面更胜一筹,例如针对金融类系统的需求,可以用时序图表示系统间的资金往来和记录存取等。
这两种表示法,都表示了操作的步骤,团队应该灵活选取适合的表达方式,当然也可以选取其它表示法如带泳道的活动图、通信图、状态机等。
针对操作和步骤的典型挑战性检验是:这些操作能解决识别出的用户问题并实现业务目标吗?操作步骤合理吗?操作流程可以更简单吗?认真应对这些的挑战,将确保功能和操作的合理性、简单性和完整性。
第三步:列出业务规则
实例化需求的最重要输出是需求验收标准,它们可以表达为一条条的业务规则。上一步,我们已经列出了操作和操作步骤,用它们来组织业务规则非常合适,对于操作中的主要步骤,团队可以列出它们的业务规则。
最常见的业务规则可以表达为三段式的结构,也就是「Given(当),When(如果),Then(那么)」。比如:
- 当用户是 VIP 会员时,如果其购买金额为 100 元,那么运费为 0 元。
- 当用户是 VIP 会员时,如果其购买金额为 99 元,那么运费为 0 元。
- 当用户是普通会员时,如果其购买金额为 100 元,那么运费为 0 元。
- 当用户是 VIP 会员时,如果其购买金额为 99
实例的形式表达场景和业务规则,这是”实例化需求“这个词的来源。之前对用户操作步骤的分析,正好可以用来组织这些实例。上图所示,正是按操作步骤分别列举对应的实例(业务规则)。
这些实例可以用条目化的方式表达。同时,当规则组合较多时,可以将他们抽取为数据表格。上图中关于”共同贷款人审查“这一步骤的规则,就被抽象成了表格。这一方面让规则更清晰和易于理解;另一方面,将来表格在映射为测试用例时,能自然的做到测试流程和测试数据分离,更易于阅读、维护和扩展。
以上列出的都是功能性的需求和规则。在实际过程中可能还会涉及非功能性需求,如可用性、可靠性、性能、安全性等。非功能性需求大部分体现在系统级别,而实例化需求针对的是单个需求。实例化需求过程中,一般只需要列出与特定功能相关的非功能性需求,如针对某一特定操作的特定安全性和性能要求。
针对业务规则的典型挑战性检验是:相关业务规则考虑全面吗?特殊情况,异常或错误处理包含了吗?是否考虑了不同用户、数据和操作类别?认真应对以上的挑战,将确保规则的完整性,以及产品交互细节的合理性。
持续的活动:在进行以上三个步骤的同时,持续构建和精化领域模型
以上介绍了实例化需求的三个主要步骤。与这三个步骤并行,团队还应该在需求分析和澄清过程中,持续梳理和澄清所分析领域的概念,建立统一的认知,形成需求沟通的统一语言。领域模型是承载这一目标的最佳载体。
使用 UML(统一建模语言)表示法,领域模型体现为不包含操作的类图[4],领域模型由三个要素构成:
领域中的实体对象(如: 房产,房主等)和概念(如:交易,按揭方案等)。
对象或概念间的关系。如:房主拥有房产等,”拥有“就是房主与房产之间的关系。
这些对象或概念所包含的属性。如:房产的属性包含房龄、价格、面积等。
领域模型又被称为术语表和概念词典。理论上,纯文本描述也能达到统一概念和认知的作用。
不过我强烈的建议使用 UML 类图来表示,一方面它的表达能力更强,形成的可视化的概念词典更加简洁直观,也方便沟通和演进。
同时,良好的领域模型为 DDD 的实施提供了基础,是分析和设计之间过渡的桥梁,为 DDD 中的子域和微服务中的服务的划分提供了业务依据。
如上图所示,领域模型是对分析领域的描述,属于需求分析中的静态视图;而操作和操作流程属于系统的动态视图。
在需求分析中,静态视图和动态视图相互印证,将极大提高需求分析和澄清的效率,以及其输出的准确性和覆盖。
静态模型和动态模型相互印证,这是需求分析方法的精髓所在,不管是传统的需求分析方法,还是适合精益和敏捷的需求分析方法,都是如此。
三、实例化需求的活动达成的效果
1. 保障需求澄清和沟通的质量
实例化需求活动上,业务、开发和测试人员通过实例澄清小批量的需求,澄清过程通常符合金字塔结构,在目标、操作和业务规则这三个层面,逐渐明晰,解决相应的挑战:
- 目标层面:目标是什么?不做这个需求会怎么样?
- 操作层面:通过哪些操作来实现这些目标?操作步骤合理吗?还可以更简化吗?
- 业务规则层面:和操作相关的业务规则都考虑了吗?特殊情况,异常或错误处理包含了吗?是否涵盖了不同的业务、数据和接口类型?
解决以上问题,保障了需求目标的清晰、交互流程的简单合理、业务规则的完整覆盖,并让业务、开发和测试对需求形成一致理解。
特别是基于共同领域模型的沟通,静态和动态视图相互印证进一步确保了需求的质量。
2. 需求拆分是实例化需求的副产品
作为副产品,实例化需求还起到了需求拆分的作用。在实施精益敏捷产品开发过程中,需求拆分是许多团队面临的难题。
之所以需求拆分困难,是因为它要做到:
- 足够小:这样才能保障迭代或持续交付。
- 端到端,这样才能保证交付有意义的价值。
- 相对独立,这样才便于迭代和交付的灵活安排。
- 拆分完还能看到整体的结构。
采用实例化需求,以上要求往往能顺便达成,需求会被自动的分解成一个个小的独立的操作,从用户角度的分析也保证了这些拆分后的需求是端到端且可交付的。
四、从实例化需求到验收测试驱动开发
实例化需求和验收测试驱动开发是一对近义词。字面上,实例化强调需求澄清活动,而验收测试驱动开发则关注整个过程。
但两者的目标是一致的,都是要做到「以终为始」,实例化需求落实到位,验收测试驱动开发则水到渠成。
上图反映了某个产品团队的验收测试驱动开发过程。正如前面实例化需求的概念三角中所表达的:
- 在就绪队列填充前,团队通过实例化需求活动产生实例。
- 实现过程中,团队将这些实例自动化,功能实现和自动化测试开发同步完成。
- 实现完成后,团队用已经完成的自动化测试来验收这些需求。这个循环就是验收测试驱动开发循环。
上图中,团队选用了 RobotFramework [5]作为验收测试的自动化工具,他们做了接口自动化测试 100%覆盖率,并辅以少量的端到端的界面自动测试。
在开发过程中,自动功能和单元测试的回归是持续进行的,而交付新功能后,团队会用新开发的自动测试进行基本的功能验收,而后再开始快速的手动验证。
本文不会专门讨论验收自动化测试,感兴趣的同学可以在我的公众号(精益产品开发和设计)中回复「自动化测试」,能看到我分享的《做好自动化测试的 15 条原则》,其中的例子大部分都是以实例化需求为基础的。
验收测试驱动开发帮助团队内建质量,它是提升开发过程的重要保障,并从根本上改善团队的有效协作和持续交付能力。
五、总结
以上我们介绍了实例化需求的 4W1H(Why,What,Who,When,How),实例化需求是精益和敏捷开的基础需求实践,它帮助团队分析、澄清、拆分和沟通需求,为开发活动提供高质量的输入。
同时它也将影响整个开发和交付过程,支持精益和敏捷开发的成功实施,改善团队的交付过程,达成高质量和顺畅的价值交付。
注释:
[1]之所以强调实践层面,是为了区别于思想层面,比如对目标和价值观的认同,和组织层面,比如组织结构和考核体系的支持。
[2]另一个是用户故事地图。
[3]参见《下一个社会的管理》。
[4]在设计视图中,类一般包含名称、属性和操作,而领域模型属于分析视图,是对概念和实体的抽象,通常不含操作。
[5]RobotFramework 是对验收测试驱动开发支持比较好的一个开源测试框架,还有更多的框架可供选择,如 Fitnesse,Cucumber 等。
本文作者:何勉
很多人对云效的认知是阿里云的一站式DevOps工具平台,这没错,但我们不仅仅如此。我们深知,DevOps是一组文化、工具和最佳实践的结合,仅有工具是不够的。除了持续打磨云效产品,让优秀的效能提升方法与云效工具更好的结合外,我们仍将持续输出阿里的研发效能和DevOps实践方法,欢迎持续锁定云效。