正如《敏捷宣言》所说:“我们一直在实践中探寻更好的软件开发方法,身体力行的同时也帮助他人”。至少从2005年开始,我们就一直在进行有关用户故事拆分的实践、指导和撰写。Richard的故事拆分流程图已被下载数十万次。在与客户合作的过程中,我们发现这个领域的工作模式非常相似。现在,随着我们共同组建人性化工作公司(Humanizing Work company)
,我们将所有故事拆分的内容整合并更新到这本新的指南中。这里面包括了在过去的十年里我们发现的一些“更好的方法”,这些方法中有一半是在指导客户在各种情况下拆分待办事项时发现的。
本指南内容
- 为什么故事拆分很重要
- 什么样的用户故事才算是恰当的故事?
- 用户故事格式
- 恰当的故事应遵循INVEST原则
- 用户故事是垂直切片
- 故事拆分流程图
- 步骤1:准备好要拆分的故事/特性
- 步骤2:套用拆分模式
- 步骤3:评估拆分效果
- Cynefin和故事拆分
- 练习故事拆分
- 垂直切片和规模化
- 是否应该让100+的人去开发一个产品?
- 规模化垂直切片的基线
- 下一步
为什么故事拆分很重要
从优先级最高的、工作量较小的用户故事开始开发,可以让产品团队持续输出高价值的产物,并获得高质量的反馈。许多团队都在努力将较大的用户故事和特性(feature)
拆分成恰当的小故事,但是他们没有从业务的垂直切片来拆分,而是从整个技术架构的的角度,拆分出了很多看起来更像研发任务(Task)
或架构组件(Component)
的故事,最终导致他们未能体验到小故事应有的价值或反馈。
幸运的是,故事拆分是一种可以在较短的时间内学会的技能。我们已经看到,团队仅需几个小时的练习和一些简单的工具,就可以从挣扎中解脱出来,快速地拆分故事。稍后,我们将介绍如何组织这种练习。
什么样的用户故事才算是恰当的故事?
在讨论拆分用户故事之前,我们需要确保我们对什么样的用户故事才算是恰当的故事、以及可以将哪些内容拆分为故事有一个共同的理解。
首先,让我们看下用户故事的定义:用户故事是从用户的角度描述系统行为的变化。它描述的是用户想通过系统做的事情,或者希望系统为他们做的事情,而这些事情现在的系统里还没有。
顺便说一下,请注意,用户故事位于方案域(solution space)
而不是问题域(problem space)
。它不是一个人想在某个地方完成一个任务的描述(就像JTBD[Job to be Done,待完成的工作]一样),而是一个人想要在你的系统中完成某件事情的描述。JTBD在问题域中可以与客户产生很好的共鸣,而用户故事可以很好地将客户的共鸣转化为对软件系统的一系列改变,同时在整个交付过程中保持客户的视角。
用户故事格式
你可能经常会看到以如下特定格式书写的用户故事:
作为角色
我想要功能或行动
以实现价值或目标
或者有的是这样:
为了价值或目标
作为角色
我想要功能或行动
该模板的优点在于它要求你回答用户故事中的三个问题:
- 它是给谁(WHO)使用的?
- 他们想要做什么(WHAT),或者让系统做什么,而这些功能现在都还没有?
- 他们为什么(WHY)要这样做?
不过,重要的不是模板,而是回答这三个问题。
实际上,我们很少会用完整的模板来写故事。无论是在便签纸的顶部还是在在线项目管理工具的标题字段里,一个写着“WHAT”的简短标题都会是比较好的选择。“WHAT”由标题提供,而“WHO”通常由产品愿景或版本目标提供,它描述了核心目标客户。如果故事是为该目标客户准备的,我们就不重复撰写了,我们只有在为非核心目标客户撰写用户故事时,才把“WHO”加上。最后,我们将确保在在线工具的“详细描述”或类似的字段中,或者在便签纸上用较浅的字体写明“WHY”。
因此,如果我们要做一个公共图书馆的网站,并且图书馆的读者是我们的默认用户,则我们不会这样来书写用户故事:
作为图书馆的读者,
我想按书名搜索一本书,
以便我能在搜索结果中毫无干扰地找到我想要的书。
我们会这样来写:
按书名精确查找
因为我知道我想要的具体书籍,所以我不希望在搜索结果中出现干扰
有时我们会遇到将单独的研发任务或架构组件伪装成用户故事的情况。即使你使用了诸如“作为开发人员,我想要一份数据库关系图,以便我能了解数据库的结构”这样的神奇描述,它仍然只是一个开发任务。
恰当的故事应遵循INVEST原则
几年前,极限编程先驱Bill Wake提出了一个很好的首字母缩略词,用来表示一个恰当的用户故事应具有的6个关键属性:INVEST。让我们来挨个看一下:
- I代表INDEPENDENT(独立的)。这意味着一个恰当的故事能够足够的独立,它可以不用考虑技术依赖就可以排定优先级。有时,这意味着需要暂时提供一些Mock数据或接口,以便可以独立测试故事,让你在项目的早期就能更快地获得价值或降低风险。
- N代表NEGOTIABLE(可协商的)。一个恰当的故事会为做什么、如何做等细节留下协商的空间。当然,随着协商的进行、更多细节的敲定,故事的可协商性就会降低。
- V代表VALUABLE(有价值的)。每个故事都应该为用户增加一些可见的价值增量。现阶段这似乎是不可能的,因为你的Product Backlog里可能有大量的技术组件和基础架构的任务,这些技术任务伪装成了用户故事,但这并不能直接为用户增加价值。随着你故事拆分技能的不断成长,你能更好地找到能直接提供价值的、短小的功能切片。
(故事并不需要单独提供足够的价值来直接发布。你可能需要积累多个故事,才能从有价值转变为可销售。我喜欢最小可销售特性(MMF,Minimum Marketable Features)作为故事的容器。) - E代表ESTIMABLE(可估算的)。一个恰当的故事应该定义到足以让团队能够估算它的工作量,这个工作量一般是相对于一个基准故事所做的相对估算。
- S代表SMALL(短小的)。经验告诉我们,对于一个已排序的Product Backlog,你应该能够将优先级最高的6到10个故事排入下一个Sprint中。这样做既能经常获得反馈和管理风险,同时也不需要管理太多的故事。不过这个故事数量只是一个建议,它会随着Sprint长度、团队规模、团队速率等因素按比例缩放。
- T代表TESTABLE(可测试的)。我们应该有办法知道我们已经完成了某个故事。它不能只是一个模糊的期望,而需要是系统行为的具体变化。
当然,这些属性之间存在着一定的互斥关系。比如说,随着故事的规模变小,使其变得独立且有价值的难度就会变大;随着故事的可协商性变大,其可估算和可测试的难度就会变大。
不过幸运的是,不同的属性在不同的时间起主要作用。例如在进入Sprint计划后,更重要的是故事要短小、可估算和可测试。这时我们仍然需要故事有一定的独立性、可协商性和有价值,但这些属性这时已经变得不那么重要了。而在Product Backlog中的故事,情况恰恰相反。
用户故事是垂直切片
在提到恰当的故事时,你经常会听到垂直切片(vertical slice)
这个词。这是恰当的故事在软件架构方面的要求。
垂直切片是指“一个能给系统行为带来变化的有价值的工作项,它可能要触及多个架构层级(architectural layers)
来实现这个变化”。当你把这个切片(slice)
称为“完成”时,该系统对于用户而言显然更有价值。
水平切片(horizontal slice)
与垂直切片刚好相反,它是指“对一个组件(component)
或架构层级(architectural layer)
进行更改的工作项,它需要结合其他组件或架构层级的改变,才能对用户交付可感知的价值”。
我们来看一个非常简单的系统架构,这里有UI层、业务逻辑层和持久层。你的系统可能比这更复杂,但它可能至少包含这三层。
要想获得INVEST的大部分属性,故事必然会涉及这3个架构层级。如果不进行某些UI的改变、逻辑的改变、持久存储的改变,我们可能就无法交付价值。因此,故事就是系统的一个垂直切片。
有时候,这些垂直切片非常宽。当我们进行故事拆分时,我们将讨论如何在较宽的垂直切片中找到较薄的垂直切片。但是到目前为止,我们只需要知道故事应该在必要时跨越架构层级来提供价值就足够了。
许多刚组建的敏捷团队会尝试按照架构层级来拆分故事:一个故事用来实现UI,另一个故事用于更新数据库等等。虽然这个故事可能也很小,但在独立性和价值交付上是失败的。
当团队以垂直切片的方式拆分时,他们将会得到如下收益:
- 使Backlog的价值明确
- 进行更多关于价值的对话
- 有助于避免意外地建立低价值的变更
- 更快获得价值
- 更早获得更高质量的反馈
- 更容易看到约束和待办,并能做出相应的响应
- 交付价值时变得更加可预测(因为可工作的软件是进度的首要度量标准)
我们还可以继续说下去,但这些应该已经可以给你一些启发了。当我们一起坐下来,写下我们在成功的敏捷团队中看到的各种习惯,以及各个习惯之间的关系时,我们发现垂直切片几乎与所有其他习惯有关,或至少与部分习惯有关。
看看Product Backlog中的故事,有些是你最近完成的,有些是将来要做的。根据INVEST标准评估每一个故事,找出垂直切片和非垂直切片的故事。然后,看看你是否可以改进这些故事。
故事拆分流程图
为了方便我们更好地指导团队,Richard创建了一个故事拆分流程图,该流程图介绍了我们在帮助团队拆分故事时要问的问题。
让我们分别看一下图中的三个步骤:
步骤1:准备好要拆分的故事/特性
首先要确保你要拆分的故事/特性满足INVEST标准(短小的(Small)
除外)。大多数情况下,有价值的(Valuable)
是问题所在。当人们把他们认为是“不可拆分”的故事带给我们时,它们其实是伪装成故事的开发任务或架构组件。如果你不从增加价值的角度入手,就无法将其拆分并获得价值增量。在这种情况下,下一步就是将非故事(non-story)
与其他水平切片结合起来,这样,它们才可以共同代表一个价值增量。
接下来,是不是切片太大了?如果是的话,就可以开始拆分了。
步骤2:套用拆分模式
模式1:按工作流程步骤拆分
这是我的客户在创建一个内容管理系统的故事:
作为内容管理员,我可以将新闻发布到公司网站。
听起来故事并不大——直到我们深入研究了发布新闻的工作流程。结果发现,仅仅是把一个几句话的新闻发布到公司网站上,就需要编辑和法律部门的批准,以及在预发布网站上做发布前的最终审核。像这样的6-10个故事不可能在一次迭代中完成。
在这样的工作流程中,最大的价值往往来自于开头和结尾。中间的步骤会增加增量价值,但并不独立。所以先构建简单的端到端案例,然后再添加中间步骤和特殊案例,效果会很好。
新的故事包括:
…我可以直接将新闻发布到公司网站上。
…我可以在发布新闻前做一下编辑审核。
…我可以在发布新闻前做一下法律审核。
…我可以在预发布网站上查看新闻。
…我可以将一篇新闻报道从预发布网站发布到正式网站。
但有时,整个工作流程都很重要,你不能只从开头和结尾开始。在这些情况下,寻找一个贯穿整个工作流的薄薄的切片。也许它支持最常见的情况;也许你可以硬编码或以其他方式简化工作流中最容易理解的部分,然后你才能探索更复杂的部分。
无论哪种方式,最明显的拆分——从头到尾按功能模块一步一步执行——都是错误的方式。查看我的80/20产品所有权课程的这段摘录,了解更多关于为什么这种拆分是错误的,以及如何使用其他两种方法。
模式2:按不同的业务规则拆分
这个故事中隐藏着一些同样复杂的故事,这些故事使用不同的业务规则来完成同一件事:
作为一个用户,我可以使用灵活的日期规则搜索航班。
深入研究“灵活的日期规则”,会发现有好几种不同的业务规则,每个规则都可以单独成为一个恰当的故事:
“日期X和日期Y之间的N天”。
“12月的某个周末”。
“日期Z的前后N天”。
模式3:按主要工作拆分
有时,一个故事可以拆分为几个部分,其中大部分的精力会去实现第一个部分。例如这个信用卡支付的故事:
作为用户,我可以用VISA、MasterCard、Diners Club或American Express支付机票费用。
这个故事可以再拆分为四个故事,每种信用卡一个故事。但是,在处理第一个故事的时候就要建立起信用卡交易的基础架构;增加更多的信用卡类型时这方面的工作就会相对较小了。我们可以估算第一个故事的规模大于其他三个故事,但是如果产品负责人后来改变了优先级,我们就必须记得要改变我们的估算。相反,我们可以如下述所示,推迟决定哪种卡的类型先被实现:
…我可以使用一种信用卡类型(VISA,MC,DC,AMEX)付款。
…我可以使用所有四种信用卡类型(VISA,MC,DC,AMEX)付款(前提是已经实施了一种信用卡类型)。
这两个新的故事仍然不是独立的,但依赖性会比为每一种信用卡类型编写一个故事要清晰得多。
模式4:按简单/复杂拆分
当你在计划会上讨论一个故事时,故事似乎越来越大("X怎么办?"、"你考虑过Y吗?"),这时候你应该停下来,询问下大家:“最简单的版本是什么?”把这个简单的版本写成用户故事。你可能必须在现场定义一些验收标准以保持简单。然后,把所有的变化和复杂性拆分成其它的故事。比如这个故事:
作为用户,我可以搜索两个目的地之间的航班。
通过像下面的方式拆分变化来保持简单:
...指定最大中转次数。
...包括附近的机场。
...使用灵活的日期筛选规则。
...等等。
模式5:按不同类型的数据拆分
故事中的复杂性可能来自于处理数据的变化。例如,我当前正在开发的系统需要对运输服务提供商所服务的地理区域进行建模。仅仅是处理复杂的服务区域的地理学知识,我们就可能烧掉整个项目的预算。当我讲完这个故事后:
作为用户,我可以根据行程的始发地和目的地来搜索运输服务提供商。
与产品负责人讨论后发现,虽然我们不需要成熟的GIS,但对地理环境进行建模仍然非常复杂。我们停下来反思:“什么是‘足够好’的地理建模方案,以便我们现在就可以构建其他高价值的功能?”我们选择了:
作为用户,我可以按行程的始发地(市)和目的地(市)搜索运输服务提供商。
这在一段时间内是没问题的,直到我们收集了更多的数据,发现有些服务提供商只服务于某些县城甚至乡镇。于是一个新的故事出现了:
作为用户,我可以按行程的始发地(如市、县、乡/镇、街道)和目的地(如市、县、乡/镇、街道)搜索运输服务提供商。
在查看新的服务提供商数据时,我们还发现,有些服务提供商会支持出发地为单一城市,但终点为周边任意多个城市的行程。这就引出了下面这个故事:
服务提供商可以为行程的始发地和目的地提供不同的地理区域。
这三个故事都是从原来的地理故事中拆分出来的。这里的区别是,我们在构建最简单的版本后,及时添加了新的故事。但有些情况下,你在项目前期就能知道数据的变化。典型的例子是系统的本地化:
作为内容管理员,我可以用以下语言创建新闻:
英语
日语
阿拉伯语
等等……
模式6:按不同界面拆分
有时,故事的复杂性在于用户界面而非功能。在这种情况下,故事的拆分要从最简单的UI开始,然后再构建更易用或更华丽的UI。当然,这些并不是独立的——如果你先做第二个故事的话,第二个故事实际上就是初始故事——但它仍然可以是一种有用的故事拆分方式。
作为用户,我可以搜索两个目的地之间的航班。
...使用简单的日期输入。
...带有精美的日历界面。
模式7:延迟性能优化
有时,一个故事的基础功能实现可能并不难,但是需要花很多时间在性能的优化上。如果你可以从较差性能的基础功能中学到很多知识,并且它对用户有一定的价值(比如没有这个功能用户就无法完成故事中的动作),在这种情况下,你可以把故事拆分为“使其能用”和“使其好用”:
作为用户,我可以搜索两个目的地之间的航班。
...(只要功能完成就好,加载时显示一个“搜索中……”的动画。)
...(加载时间限制在5秒以内)。
模式8:按不同的业务规则拆分
用户故事中的“管理”会涵盖故事的多个操作。这就为故事的拆分提供了一种自然的方式。比如说:
作为用户,我可以管理我的帐户。
...我可以注册一个账户。
...我可以编辑我的账户设置。
...我可以注销我的账户。
模式9:拆分出一个探针
一个故事之所以被大家认为工作量很大,可能并不是因为它的业务有多复杂,也有可能是因为开发团队对其技术实现不太了解。在这种情况下,无论你怎么澄清故事的业务部分,都无法将其拆分。先拆分一个有时间盒限制的探针故事,以便解决开发过程中的不确定性,然后我们可以决定是直接实现,还是使用上述的8种模式来拆分它。假如我们不知道下面的故事如何实现:
作为用户,我可以用信用卡付款。
那么,就把它分解成:
调研信用卡付款。
实施信用卡付款。
在“调研”故事中,验收标准应该是你需要回答的问题。调研要点到为止,能回答问题即可,做调研很容易走火入魔。
探针拆分模式放在最后讲解,是因为它应该是你最后的选择。你目前已知的知识可能已经可以用来构建一些功能了,按照你已知的知识直接开始开发吧,随着项目的推进,这些问题很有可能会不攻自破。因此,在求助于探针模式之前,请尽一切努力使用前面八个模式之一。
元模式:找出复杂性并减少变化
在我们指导团队更有效地拆分故事的过程中,我们发现了这些模式共有的元模式:关注复杂性,并通过它减少变化。使用元模式的方法如下:
- 找出核心复杂性。最有可能让你感到惊讶或者出现问题的部分是什么?这个问题的答案往往取决于人们的个人喜好或行为习惯。有时,这是一个需要重新整合或有外部依赖的部分。
- 识别出其中的变化。变化比较多的东西是什么?业务规则、用户类型、接口、数据变化、实体等。
- 把所有的变化减少到一个。在复杂的部分中找到一个单一的、完整的切片。它可能是一个单独的场景,也可能是通过单个业务规则变化出的一系列场景。
大多数故事拆分模式只是确定变化的来源并将其减少到一个的例子。
这种方法对于一个新事物的第一个切片特别好用,因为它直奔核心复杂性,并避免了任何可能会让工作变得更大的内容。
步骤3:评估拆分效果
你可能会发现,有时你可以使用好几种模式来拆分同一个故事。那我们应该选择哪种拆分方式呢?我一般通过以下两个经验法则来判断:
- 选择能让你降低优先级或扔掉一个故事的拆分方式。80/20法则表明,用户故事的大部分价值来自于一小部分功能。当一种拆分方式揭示了低价值的功能,而另一种拆分方式没有揭示,这说明后一个拆分方式在每个小故事里面都隐藏着浪费。选择能让你扔掉低价值功能的拆分方式。
- 选择能让你得到更多同等大小的小故事的拆分方式。把一个8点的故事变成四个2点的故事的拆分方式比产生一个5点和一个3点的拆分方式更有用,因为它能让产品负责人有更多的自由来分别对这些拆分后的故事进行优先级排序。
可能需要多次尝试才能找到最适合你的故事拆分模式——你可能需要不断地试验才能找到正确的模式。
Cynefin和故事拆分
Dave Snowden的Cynefin模型是一种根据问题的复杂程度来思考问题最优策略的有用方法。我们发现Cynefin非常有用,几乎所有的工作坊都使用了它,有的是作为先决条件,有的是作为工作坊本身。如果你还不熟悉这个模型,请查看我们的概述。
Cynefin每个领域的故事拆分看起来都不一样。下面是具体拆分方法:
- 简单(Simple) - 只需构建即可。如果故事太大,找出所有的故事,先做最有价值的即可。
- 繁杂(Complicated) - 找出所有的故事,并首先做最有价值和/或最具风险的故事。
- 复杂(Complex) - 不要试图找出所有的故事。找出一两个能提供一些价值的,并能教给你一些关于问题和解决方案的知识,构建这些故事,然后利用你所学到的知识去寻找其余的故事。
- 混乱(Chaotic) - 先把手头紧急的事情解决吧,现在拆分故事可能并不重要。
- 失序(Disordered) - 拆分之前先弄清楚你在哪个领域,以免采取错误的方法。
最重要的细微差别在复杂域(complex domain)
,从这里开始工作会让你快速了解工作的内容。在这种情况下,试图找到构成原始大故事的所有小故事是没有意义的。找到一两个可以立即开始学习的故事会更有效率。
有些人不喜欢这种方法,他希望把所有的故事都列举出来,并确定大小,以便能够把故事记录到Backlog并估算时间。但如果你真的是处于复杂域(complex domain)
,这样做只会给你带来可预测性的错觉——实际的故事很可能会随着工作的推进而发生变化。最好对复杂工作中固有的不确定性保持透明。
练习故事拆分
就像我们之前说过的那样,在较薄的垂直切片中工作是敏捷软件开发的关键习惯。很多人都在努力寻找垂直切片,但其实这是一项非常容易习得的技能。团队只需2.5-3个小时的练习,就可以从苦苦挣扎到快速地识别出其领域中的特性和大故事的切片。当然,练习的质量很重要。下面是我推荐的做法:
在1-2周的时间内安排两到三次1小时的练习课程。邀请整个团队或至少能很好地结合业务和技术观点的组合。
为了准备第一次练习,看看你最近几个月的Backlog。选择几个你曾难以拆分但现在已经成功实现的故事或特性。
用Cynefin的术语来说,这些已完成的特性现在是有序的(繁杂的或简单的),因为出现了足够的秩序来实现它们。未来的工作很可能是复杂和无序的。但现在这并不重要。在第一个练习环节中,你的目标是识别出在你的领域中使特性变大的原因。追溯已完成的工作是练习有效性的关键。
在第一个练习环节中,拿着你选择的一个特性或故事,对照故事拆分流程图中的问题一起过一遍。假设这个特性尚未实现,也可以检测下你自己现在对它有多了解。
如果你使用其中一种模式找到了一个好的拆分方式,请不要停下来。继续浏览其他模式,并尝试找到另一种可能的拆分方式。
如果一次拆分不能产生足够小的故事,请尝试对拆分后的故事继续拆分。
大约50分钟后停下来。对于你准备的特性或故事,使用流程图上的每种拆分模式后,请检查下各模式下拆分后的小故事。
如果你在这个环节没有找到合适的拆分方式,花点时间让大家一起来头脑风暴一下。当这些拆分模式应用到你的特性或故事时,大家是否已经达成了共识。
如果在第一次练习结束时,拆分已完成的特性似乎很容易,那么你就可以尝试对后续的工作进行拆分了。如果不是,需要再重复下第一次的练习。在下次练习之前,找几个合适的特性,重复上述过程。
这样做的难点在于,它是一个“练习”。很多人只愿意通过正式培训或在工作中边干边学来提升能力,他们往往不愿意花时间用来做一些练习,尤其是练习拆分已经完成的特性,因为这个活动不会有新的工作产出——比如说,它不会完善即将要做的Backlog。但这方面的练习可以快速提升团队故事拆分的能力。千万不要跳过它。
经过2到3个这样的练习,你应该达到这样的程度,即对于工作中的每个特性,每个人都能快速找出适当的拆分模式,并迅速拆分出适合迭代的故事。
垂直切片和规模化
当你有100+人在同一个产品上工作时,可以使用垂直切片吗?
当你有多个敏捷团队开发同一个产品时,可以采用这两种组织方式:特性团队(feature team)
或组件团队(component team)
。
特性团队的组织方式是,每个团队都有足够多的跨功能成员,以便可以在部分或全部产品上提供完整的价值切片(即“垂直切片”)。根据产品的规模,特性团队可能会专注于产品的某些部分,有效地创建子产品,或者他们可能会完成整个产品中最重要的部分。
组件团队的组织方式是,每个团队专注于一个特定的组件、架构层次或技术方向。要想交付一个完整的价值片段,需要协调多个团队的工作。
让我们看一个大型商业软件的具体例子:淘宝。(注:我不知道淘宝的实际组织方式或技术是什么样的,但是这并不重要,我只是需要一个大家都熟悉的软件产品来进行推理)。
淘宝有一个APP。它通过某种通讯协议与某种语言编写的后端进行通讯。后端有一些流程处理的程序,比如搜索商品、生成订单、支付订单以及跟踪物流信息等。
如果采用组件团队结构,你会有APP团队,例如,他们可以对APP界面进行修改,但他们很可能依赖于后端团队对其系统部分进行相应的修改。各个团队之间的协调将集中在确保他们的工作同步推进,以最终能够提供价值。
在特性团队的结构下,你可能会有一个团队或一组团队负责商品的搜索模块,另一个负责订单模块,第三个负责支付模块等。这些团队中的每一个都拥有APP和后端技能。在这种情况下,各团队之间的协调将集中于确保整个产品的设计和架构一致。
相同的产品,团队以两种不同的组织方式,将得到两套不同的结果和协调方案。
所以,有关“垂直切片是否与规模相关”这个问题,答案取决于你的组织方式。组件团队是不以垂直切片的方式工作的。但组件团队可以围绕更大的垂直切片(如MMF)协调工作,但在具体的工作项层面,组件团队无法完成垂直切片所需的全部功能。构建组件团队无法独立交付价值,但这种组织方式可以针对其他方面进行优化(通常是更容易进行架构调整或更高的研发人员利用率)。
特性团队与组建团队的收益刚好相反。他们旨在独立提供垂直切片,以便更快速的交付价值、获取反馈,代价是需要明确地协调架构一致性。
特性团队与组件团队是2种主要的组织方法。当然,有些组织可能有细微的差别或混合,并且会随着时间的推移而变化。我以前写过这方面的文章,特别是在改造一个拥有大型遗留产品的组织的情况下。
是否应该让100+的人去开发一个产品?
现在,我们心中还有一个更重要的问题,那就是:不管我们是否可以在大型产品/项目中使用垂直切片(正如我们所展示的那样,如果我们以特性团队来组织,我们是可以的),这么多人一拥而上,是否真的有效?
为单个产品/项目添加人员或团队,都会带来一些生产力和协调的开销:项目如果只有一个人,那么这个人的生产力几乎是100%;再增加一个人的话,我们不会得到2倍的生产力,可能只会得到1.8倍的生产力(平均每个人提供90%的生产力),因为这两个人需要花时间用来进行工作的协调(每个人消耗10%的生产力用于协调);增加到3个人的时候,生产力会得到再次提升,这次有可能会提高到2.4倍(平均每个人提供80%的生产力),相应的,协调的开销也会随着上升(每个人消耗20%的生产力用于协调)。而且,这种协调的开销会随着人与人之间联系的数量呈指数增长。
通过组建小规模团队,使每个人只需要与少数人协调工作细节,并尝试在团队之间进行分工,尽量减少依赖性,从而能在一定程度上减少协调的开销。但工作越复杂,依赖关系就越难以预测,团队之间需要协调的可能性就越大。
因此,在某些时候,在项目/产品中再增加一个人或一个团队,不仅不能提升生产力,还会给整个系统带来协调开销的增加,最终导致整体生产力的下降。
团队规模的临界点到底落在哪里,在很大程度上取决于项目/产品的具体情况。但抛物线的形状至少应该让我们对大型团队产生怀疑,并慎重考虑人员或团队的增加。
对于复杂的工作来说尤其如此,因为很可能需要我们在一个项目/产品上工作一段时间后才能了解真正的问题和解决方案。而在软件开发过程中,复杂性似乎与价值高度相关。越是高价值的特性,项目/产品前期越可能发现不了。如果是一个新项目/产品,我们在工作中很有可能会学到一些新知识,从而改善我们交付的价值。
规模化垂直切片的基线
是的,你可以在每个细节层面和各种规模的工作上进行垂直切片,这样做很有价值。但在大规模的交付中,你需要特殊定的方式进行组织:以特性团队的方式,或者以某种强调功能交付的混合方式。而且,当你使用它时,需要考虑一下,你的需求是否真的需要如此大的规模。
下一步
我很乐意帮助你更好地掌握故事拆分和产品负责人的其他关键技能。如果你在拆分的过程中有任何问题,请留言告诉我。