一、前言
精通Scrum的团队知道,成功的关键在于及时并逐步完善积压的Product Backlog Item(简称PBI)。
在Sprint Backlog里,他们更喜欢包含许多小(功能性)PBI,而不是几个大PBI。较小的PBI,可以改善工作流程、降低 迭代交付失败的风险。
本文将首先阐述为什么拆解需求很重要,以及为什么应该跨越功能边界(垂直拆分),而不是技术边界(水平拆分)来进行拆分, 然后重点介绍Scrum团队进行需求拆解的10种策略。非『道』,唯术尔。
二、背景
前面【TAPD实战故事】研发效能之再靠近一点点一文提到了需求拆解, 此外作为EPC的第一环节,从最开始梳理好需求,拆解需求,需求归一化、可视化,才是推动EP的第一措施。
三、术语对照表
术语 | 对应语 |
---|---|
Backlog | 待办列表,对应需求池 |
Sprint Backlog | 迭代待办列表,对应迭代任务清单 |
Product Backlog | 产品待办列表,对应需求清单 |
Product Backlog Item | 简称PBI,产品待办工作条目,对应需求 |
Sprint | 冲刺,对应迭代 |
Happy Path | 正常流程 |
Unhappt Path | 异常流程 |
鉴于笔者工作环境,下面篇幅,将主要用右侧的术语来描述。
四、为什么和什么时候拆解需求
软件开发本质上就是不可预测的,在需求池里面积压的需求,有些是需要花费比预期更多的精力,有些是需要花费比较较少的精力。 因此,如果一个迭代里只包含几个大需求,那么即使是对单个需求低估预期,也会对整个迭代产生较大的影响。同时,由于较大的需求 往往难以预估和理解,会导致迭代交付失败的风险增大。
经验丰富的Scrum团队,往往会花费时间和经历去将大需求拆解为较小的用户故事。虽然有时候,他们是在新迭代的计划过程中进行 这样的拆解,但是这种需求清单的梳理应该是持续性的,以便使迭代的衔接,尤其是迭代的计划更加顺畅。在迭代开始之后, 团队会花费额外的时间来拆解下一个迭代的需求,甚至下下个迭代的需求。这种拆解的方式是准时制的,所以团队在未来的迭代上 花费的时间将越来越少。
拆解需求的过程,可以增进共识,提高预估的准确性,并有助于团队确认工作的优先级。但是做的好并不容易,需要练习才能即时完成。
五、为什么垂直拆解优于水平拆解
一般而言,拆解需求有两种方式:水平拆解和垂直拆解。
1. 水平拆解
水平拆解,指将需要完成的需求,按照工作类型或者层次或者组件来拆解。因此,UI相关、数据库、一些其他组件、前端、 测试等工作,会在待办列表里拆分为多个子需求。这种方式在Srum里面拆解需求时,运转的并不好,主要是因为:
-
单个子需求不能独立演示。假设有一个网上商城订购流程的需求,如果按照这种水平拆解方式,拆分为UI设计、数据库、 前端和测试工作。尽管每个子需求都很小,但是它们并不能独立运行、提供功能,只有所有的结合在一起,才能产生商业价值。
-
增加瓶颈。水平拆解往往伴随着“独立的思考”,每一个事项的成员都是一个孤岛,每个人都只负责自己独立的那一部分, 成员之间不可互换,很有可能出现瓶颈。中间任何一个模块的延迟、中断都会影响整个的迭代。
-
无法进行优先级划分。水平拆解的单个部分,都无法单独提供业务价值,因此不好确定优先级。此外,每一部分都有可能是技术性的, 很容易在产品和开发之间造成一定的误解
水平拆解乍看能拆解出更多更小的子需求,但是它确实限制了一个团队交付工作、解决瓶颈、确定优先级的能力, 从而增加了迭代交付失败的风险。其实,水平拆解往往用于任务的拆解,由研发同学讲需求进行技术任务的拆分。
2. 垂直拆解
垂直拆解,则是在垂直方向纵深抛开,按照不同用户及场景分组,并分别依据事件流程、需求层次进行梳理, 这样的拆分的较小的子需求可以独立运行、演示。
【示例】需求是“作为客户,我可以为我的订单付款,这样我就可以得到我的产品”,可以拆分为:
- 作为客户,我可以通过微信付款,这样我就可以得到我的产品
- 作为客户,我可以通过银行卡付款,这样我就可以得到我的产品
想象一下,蛋糕有一层奶油、一层水果、一层蛋糕。如果你水平切蛋糕,那么每个人得到的可能会是一片蛋糕、奶油或者水果。 所以更妥善的切法是垂直切,这样每个人都能吃到奶油、水果和蛋糕了。
六、十种策略
下面的十种策略,通常不是单独使用,而是组合其中的几种进行设计和拆分,按照实际情况,进行合理选用才是最佳方式。
1. 策略一:通过业务流程拆解
如果需求涉及到某种工作流程,通常可以将该需求拆解为各个步骤,这也是最常用的拆解问题的方式。
比如,网上商店的订购过程,我们可识别出有如下的步骤
作为一个顾客,我可以为我的购物车付款,以此在家收到产品
- 作为一个顾客,我可以用我的账户登陆,以此不用每次都重复输入个人信息。
- 作为一个顾客,我可以查看并确认我的订单,以此在支付前修改填错信息。
- 作为一个顾客,我可以通过微信支付,以此确认订单。
- 作为一个顾客,我可以通过银行卡支付,以此确认订单。
- 作为一个顾客,我可以收到订单确认邮件,以此获得支付凭据。
按照上述方式进行了拆解之后,我们对需要实现的功能以及需要提供的能力都有了很清晰的理解。而且,对产品经理来说, 也很容易制定优先级。
2. 策略二:通过业务规则拆解
需求往往涉及到多个显式或隐式的业务规则,还是以上面的需求为例,我们可识别出有如下的业务规则:
作为一个顾客,我可以为我的购物车付款,以此在家收到产品
- 作为店主,我可以拒绝10美元以下的订单,因为他们不盈利
- 作为店主,我可以拒绝国外的用户,因为运费太高会导致不盈利
- 作为店主,我可以在保留48小时内被订的产品的库存,以便其他顾客可以看到实际库存
- 作为店主,我可以取消48小时内未付款的订单,以便将商品卖给其他顾客
业务规则通常是隐式的,因为挖掘他们需要一定的能力,采用下面的策略七可能会有帮助。测试用例通常意味着重要的业务规则, 一旦确定了业务规则,能提高我们的理解能力和预估能力。产品经理根据业务规则,决定哪些规则暂时不重要,或者可以简化实施, 比如网站上加一条文本说明“暂不支持外国地区配配送”等。
3. 策略三:按正常/异常(Happy/Unhappy)流程拆解
功能往往涉及到正常流程(Happy Path)和多个异常流程(Unhappy Path)。正常流程描述了一切顺利的行为方式, 如果出现偏差或者异常,则会走到异常流程里。
比如,账户登陆的过程,我们可以考虑正常登陆和登陆失败的场景:
作为一用户,我可以用我的账户登陆,以便我能访问安全的网页。
- 作为一个用户,我可以用我的账户正常登陆(Happy)
- 作为一个用户,当我登录失败的时候,我可以重置我的密码(Unhappy)
- 作为一个用户,当我登陆名不存在时候,我可以注册一个新账户(Unhappy)
- 作为网站所有者,当用户连续三次登陆失败的时候,我可以阻止用户再次登陆(Unhappy)
通过识别各种流程,我们可以更清晰的了解产品所需的功能。产品经理能够给更轻松的决定功能的优先级。也许用户三次 登陆失败并不打紧,因为出现这种场景的用户很少,或者用户可以通过重置密码来解决。
4. 策略四:按输入源或平台拆解
大多数web应用程序必须支持各种输入源或者多平台(PC端、平板、手机、触摸屏等)。
比如,电子敏捷看板的展示,我们可以考虑以下几种输入源:
作为一个团队成员,我可以看到敏捷看板,以便我能知道我们团队的整体情况
- 作为一个团队成员,我可以在PC端查看敏捷看板。以便我知道迭代的进度
- 作为一个团队成员,我可以在手机上查看敏捷看板。以便我知道迭代的进度
- 作为一个团队成员,我可以在平板查看敏捷看板。以便我知道迭代的进度
- 作为一个团队成员,我可以打印出敏捷看板。以便我知道迭代的进度
通过这种方式拆解需求,产品经理可以更轻松的确定哪些输入源或平台更重要。比如目前来看,PC端的版本已经足够了, 移动端的版本可以在之后的迭代实现,或许可以暂时通过简单打印PDF来实现打印输出,而不必花费太多精力开发一版专门适合打印的版本。
5. 策略五:按数据类型或参数拆解
某些需求可以根据他们返回的数据类型或者应该处理的参数进行拆解。
比如,网上商城的搜索功能,可以有很多种搜索商品的方法。
作为一名顾客,我可以搜搜产品,以便我可以查看和订购它们。
- 作为一名顾客,我可以根据商品编号搜索商品,以便快速找到我已经知道的商品
- 作为一名顾客,我可以搜索价格范围之内的商品,从而使搜索结果更加相关
- 作为一名顾客,我可以按颜色搜索商品,从而使搜索结果更加相关
- 作为一名顾客,我可以搜索商品类别中的商品,从而使搜索结果更加相关
通过这种方式拆解需求,我们可以更清楚地了解将使用哪些搜素参数,也便于开发同学的估算和设计。也许由于产品数量少, 分页没有太多意义,但是当产品数量增加的时候,就得考虑分页的问题了,目前第一版本可以简单实现一些搜索功能。
再或者基于返回的数据类型进行拆解涉及管理信息的功能时,某些信息可以以图表或者图形的形式展示,但是也可以 以表格形式的数据类型进行展示,或者也可以将数据导出到excel,然后让用户自己在excel创建自己想要的图标和图形。
6. 策略六:按操作(增删改查)拆解
需求往往涉及到许多默认操作,比如创建、读取、更新或删除(CRUD)。当功能涉及到实体(商品、用户、订单)的管理时, CRUD的操作就比较普遍了。
比如,网上商城的商品管理里,可以识别每个实体的相关操作。
作为店主,我可以在网上商城中管理产品,以便当商品价格和信息发生变化的时候,我可以更新价格和信息。
- 作为店主,我可以添加商品,以便客户可以购买它们。
- 作为店主,我可以更新现有商品,以便价格和信息是最新的。
- 作为店主,我可以删除商品,以便清理没有库存的商品。
- 作为店主,我可以隐藏商品,以便管理暂时无法出售的商品。
通过这种方式拆解需求的时候,有些团队会思考,这样的子需求是否到底带来了业务价值。毕竟只能创建商品不能更新和 删除商品似乎没有什么意义。因此,在商品数量有限的时候,有时候简化版本会先通过直接在数据库进行修改和删除来完成,或者 只是软删除一个商品。不管怎么样,最简单快捷实现的方式,也许才是当下最好的实现方案。
7. 策略七:按测试场景或测试用例拆解
当仅凭功能很难拆解需求的时候,按照测试场景来拆分就很有用了。
比如,一个任务计划系统,可以找到几种潜在场景
作为经理,我可以将任务分配给员工,以便他们可以处理任务。
- 如果一个员工已经分配了一个任务,他不能再接受其他任务
- 如果一个员工请假了,他应该被可视化标记出来
- 如果一个员工请假了,他不能接受任务
- 如果一个员工没有任务,他可以接受任务
测试场景,代表的是从测试维度进行验收,可测试在一定程度上说明了可独立演示,同时包含了一定的功能点。某些场景, 如果不是很常见或者风险不高,产品经理可以决定暂时跳过此功能,专注于提供更多价值的场景。
8. 策略八:按需求涉及的角色拆解
需求通常涉及许多角色或角色组,每个角色执行该功能的一部分。
比如,将新文章发表到新闻官方网站,涉及到不同的角色:
作为新闻机构,我们可以在首页上发布新文章。以便用户经常访问
- 作为用户,我可以阅读一篇新文章,以便网站通知重要的信息给我
- 作为记着,我可以写一篇文章,以便用户进行阅读
- 作为编辑,我可以在文章发表之前,对其进行审阅,以便输入错误
- 作为管理员,我可以把文章从网站上删除,以便处理违规的文章
- 作为用户,我可以查看并确认我的订单,因此我可以在付款之前更改错误信息
按照不同的角色划分,可以理清业务流程。根据每一种角色的用户量多少、权限多少、角色之间的关系,可以确定涉及流程的 优先级。比如,最高优先级并不需要编辑器,因为新闻工作者可以让编辑人员手动检查文章。
9. 策略九:按照紧急程度拆解
通常紧急程度的考虑,是暗藏在所有策略之中的,按照功能的完善程度和优化程度,合理分配当前资源。
比如,搜索酒店的功能,可以有如下的方向:
作为访客,我可以搜索附近的酒店,以便我乐意缩小搜索范围。
- 作为访客,我可以在地址范围内搜索酒店,以便我可以缩小搜索范围
- 作为访客,我可以输入邮政编码以自动填写地址,以便我不用手动输入整个地址
- 作为访客,我可以使用自己的位置(GPS)在附近进行搜索,因此无需手动输入地址
- 作为访客,我可以立即获取附近搜索最多的酒店,而其他酒店正在后台慢慢加载,以便我可以更快的得到结果
说明一点的是,不应该把该策略当做当前编写烂代码、未来优化的借口。团队应该至始至终考虑未来的实现,做出可拓展的设计方案, 编写可维护可拓展的良好代码。此策略与功能优化有关,也许现在实现按地址范围内搜索就足够了,将来实现自动化搜索的复杂功能。
10. 策略十:按浏览器兼容性拆解
作为策略四的变体和细化,在web应用程序上的应用,通过需要在各种平台的浏览器上工作。现代浏览器往往更符合标准, 并且更易于开发,较旧的浏览器往往需要黑客或者自定义才能使所有功能正常运行。
比如,客户购买商品时候,可以通过考虑浏览器的版本,分为如下几个方向:
作为客户,我可以查看商品详细信息,以便我确定是否要购买商品。
- 作为客户,我可以在符合标准的现代浏览器中查看商品详细信息
- 作为客户,我可以在文本浏览器中查看商品详细信息。
尽管最好是提供完全支持所有浏览器版本的功能,但在某些情况下这种拆解是可行的。也许绝大多数的访问者都是使用的现代浏览器, 而无需花费太多精力来支持旧的浏览器(除了警告)。再或者,该应用程序的所有用户都使用IE7在内网上运行。
11. 其他策略
在拆解需求时,还有许多其他有用的策略:
- 根据验收标准进行拆分。看起来这是一个显然易见的方式,但是却是一个最简单、最自然的方式,跟本文中有些策略有相似之处。
- 根据难易实现的和易于实现的进行拆分。同样,这个也是基于实用主义和交付价值来决策的。
- 根据外部依赖进行拆分。有时候有些功能是依赖于外部系统,开始的时候可能需要对外部系统进行mock,等待外部系统完成, 有单独子需求进行联调。
- 根据可用性进行拆分。哈特森认为可用性主要包含有用性和易用性两个层面,有用性主要指产品是否能够完成一系列任务, 易用性指的是产品在完成任务的过程中的效率,操作性和用户对其满意度评价。
- 根据SEO要求进行拆分。SEO(Search Engine Optimization),比如根据Google Analytics分析的数据, 进行优先级的划分。
七、原则
Bill Wake提出了一个好用户故事的验收标准——INVEST模型 , 它由六个单词的首字母组成,分别是:
- Independent:子需求应该是独立的,不会和其他子需求产生耦合
- Negotiable:并不会非常明确的阐述功能,细节应带到开发阶段跟程序员、客户来共同商议
- Valuable:每一个子需求的交付都要能够给用户带来用户价值
- Estimable:不需要能够准确的估计,但需要能辅助客户排定优先级
- Small:要小一点,但不是越小越好,要大小合适,可以更容易的圈定需求范围
- Testable:需要能够进行验收测试,最好能把Test Case提前加进去
也许我们的粒度暂时做不到用户故事的细粒度,但是对于需求的拆分而言,仍然有一定的指导意义。这不仅仅是故事的验收原则, 更是在进行需求拆分的时候所需要考虑的拆分原则。当然,凡事有例外。在需求拆分中,有时会拆出一些实在不能满足INVEST原则的子需求,也不要太纠结,我们追求完美,但也总要接受现实的不完美。这个时候,跟开发团队多交流,开拓思路,协调一个比较好的拆分方式,比自己一个人憋大招要好的多。
八、思考
1. 需求拆分是否有一套完美的方法?
需求拆分是没有银弹的,要根据具体的场景、限制来选择合适的拆分方法。在遇到使用某个拆分方法,不能满足当前业务需求时, 看看是不是可以换个思路,换个方法。往往在拆分的时候,会同时包括上述十种策略的多个进行拆分。
当然,在选择拆分策略时,也有一些技巧,比如:
- 八二法则,也就是20%的功能决定了这个步骤的核心价值,而80%的功能仅仅是锦上添花的。
- 需求归一,选择可以把需求拆的大小差不多的方法,未来在发布计划中更容易做需求置换。
- 团队至上,选择开发团队更容易理解和实现的方式。
此外,在进行需求拆解之前,也可以画流程图协助需求的理解和拆分,比如:
- 业务流程图,一般用泳道图来描述各个角色,在每一个模块关注的功能,从战略层反映了业务流程。
- 操作流程图,一般类似于程序流程图,理清楚各个操作的衔接,便于开发理解。
- 页面流程图,一般用原型图来描述各个页面的跳转,比较直观清晰。
2. 需求粒度要多小?
没有一个明确的规定,标注一个需求到底要多小。这很大程度取决于迭代的长短,程序应用本身的特点和团队的分工情况, 通常需要花费几个迭代时间才能找到比较合适的大小。我的经验是,一个拆解之后需求的时间最好不超过迭代一半的时间(上限)。
2. 拆解需求是否会造成可交付价值降低?
当团队进行需求拆解的时候,担心最多的往往是,这样拆解之后的需求,交付起来没有太多价值。确实,与整个需求相比, 拆解之后的小需求确实降低了大需求整体的价值。但是,拆解的只要目的是降低风险,增加每次迭代结束时候可验收的功能点, 而不是强行绑定所有的需要一起上线。当然,也可以选择使用非常大的需求,一般用在首次迭代中,或者封闭式冲刺中, 完成所有细节才能交付。
八、小结与参考
需求拆解推进过程中,很多团队并不是立即就了解到拆解的收益和如何拆解,遇到阻力也并不罕见。结合一定的度量, 致力于将需求归一化、可视化,并持续不断的形成反馈循环,坚持不懈的协助团队,争取将团队的各个角色的诉求透视出来, 打破阻力,也是一种解决办法。
本文的策略部分主要参考10 Powerful Strategies To Break Down Product Backlog Items in Scrum (with cheatsheet) 一文, 在此基础上,进行了一定程度的意译和加工,转换了部分敏捷术语。
附上原文中附件的截图: