最近又一个项目用瀑布方式做砸了(由于本文会多次提到本项目,我们就叫她项目X吧)。项目X刚开始的时候,我们部门的敏捷转型还没有起步,所有项目依然用瀑布方式。这个项目我一开始就想采用敏捷,毕竟这才是我拿手的,和客户那边也沟通过,他们也不反对尝试。而且项目的自主开发部分是用Java写的,有一定的JUnit测试覆盖和持续集成(CI)基础。但是由于我一直没有想好这个项目可以如何拆分进而迭代,所以项目的敏捷转型一直被搁置,其实际开发过程依然是瀑布方式,也遭遇了所有瀑布方式会遇到的问题。
(传统需求难以描述用户的真实想法,传统瀑布开发没有快速反馈机制)
瀑布不行,向敏捷转型已经是共识,但是具体怎么做呢?通过对项目X的复盘以及对其他项目的思考,以下是我的一些心得。
把项目拆分成用户故事才是硬本领
我也算是个“老敏捷”,但像前面说的,在面对一个具体项目,不会把项目拆分成用户故事,就无法敏捷起来!真正的敏捷开发必须是基于用户故事的开发过程。
所谓用户故事就是含有一定业务价值的端到端交付。瀑布开发是把项目按照不同生命周期阶段横向拆分的过程。而敏捷开发是把项目或产品或业务目标竖向拆分成若干可体验、可交付的用户故事的过程。一个用户故事,应该是用一两个月甚至几个星期或更短时间就能做出来的东西,我们可以通过它更早地获取用户反馈,从而确定产品的正确性。这也符合敏捷倡导的“小步推进,频繁验证”的原则,是降低项目风险最有效的方法。
(瀑布和敏捷的不同拆分过程)
只有基于用户故事开发才能快速交付和持续交付
正如前面所说,我们用一两个月甚至几个星期把第一个用户故事做出来并给用户体验和反馈,而不是大半年甚至一两年后在项目后期才把产品给用户体验,我们更早、更快地交付并获取反馈,而不断重复这样的过程,就是持续交付的过程。在整个过程中,我们都在交付业务价值,而不是战战兢兢地拿着一堆半成品面对那个死亡日期的逼近。
项目X最终呈现给用户的是不同类型的基金报表,其实每一类报表就是一个用户故事。如果我们一开始就以最重要的一类报表,作为首个用户故事进行开发,只需要两、三个月的时间,我们就可以把这个用户故事完成并交付给客户进行测试和反馈,有任何的反馈我们都可以及时进行修正。得到客户认可后,我们就可以如法完成其他报表。更重要的是,从第一个用户故事,也就是最早可测试产品获得的用户反馈将确保其他用户故事的开发也在正确的方向上。而在瀑布方式下,两个月后我们才刚刚收到需求文档,什么开发都没有开始。
(尽早定义和交付最早可测试产品可及时获取用户反馈,确保产品正确)
因此,定义好用户故事是实施敏捷的基础,没有这个基础,其他敏捷实践的实施其实只是局部改善,依然是战术上的改良,而不是战略上的改变,长远来看,收效有限并容易倒退。敏捷开发是一个有机体系,各种具体的方法论和实践需要打组合拳才能发挥出其应有的效力,基于用户故事开发是一切的基础:
- 如果不是基于用户故事开发,简单地把项目的长周期拆分成短周期并不是真正的迭代,因为每个周期都没有可体验、可交付的东西,依然像瀑布一样在不断堆积半成品,这也不是真的Scrum;
- 如果不是基于用户故事开发,测试驱动开发(TDD)和行为驱动开发(BDD)很难开展,因为缺乏具体用户场景的描述,很难写出具体、简明的测试用例,因而很难累积足够的自动化测试提高系统的可改性,内部质量、重构、持续优化便无从谈起;
- 如果不是基于用户故事开发,持续集成(CI)也意义不大,因为提交的代码并没有构成可交付的产品,其实并没有真的在集成。
既然用户故事是敏捷开发的重中之重,那么如何定义好用户故事呢?诚然,这是敏捷转型的难点。业界有关具体定义用户故事的说法并不多,这也是为什么用户故事一直被忽视,因为还没有标准答案,大家无从下手。《用户故事地图》是为数不多的较具体地阐述用户故事定义方法的书籍。所谓用户故事地图就是从左至右按时间顺序罗列用户行为(也就是流程的每一步),在每个用户行为下从上至下罗列相应的细节,包括所需要的开发点,构成一个二维的“地图”。基于这个地图,还可以对每个开发点的业务价值进行审视,找出最小可用产品(MVP)并制定发布计划。但是直接从整个项目或产品入手编制用户故事地图其实非常困难。
(《用户故事地图》是为数不多的较具体地阐述用户故事定义方法的书籍)
具体用户场景+用户故事地图则是我认为比较可行的方法
所谓具体用户场景,就是设想一个用户在使用某个功能的具体过程。比如我们使用共享单车,具体的场景是用户找到一辆单车、用手机扫码和开锁、骑行、到达目标地、锁车、支付费用。这个场景的每一步,按照时间顺序从左到右罗列出来,然后再分解每一步所需要的系统或模块,在每个系统或模块下从上到下罗列所需要的细节,包括所需要开发点,便形成一个用户故事地图。如果这个场景依赖于其他场景,比如注册,那么就设想注册的场景及其用户故事地图。如果注册就是所有其他场景的前置条件,就优先开发它。
(场景+地图是一对好基友)
再举一个传统金融项目的例子。比如银行开户,其中一个典型场景就是具体某类客户通过某个渠道开某类账户的过程。在这个例子里,可以想象它会有很多个不同的场景,而每个场景都是一个交付。有了一个具体场景,我们就可以分析要实现这个场景,背后需要哪些系统来支撑,每个系统需要开发什么,形成一个用户故事地图。
当然,以开户为例,开发首选场景的过程会相对较长,因为软件从无到有有打地基的过程,业务实现也需要各个系统的统筹配合,但它并没有看起来那么困难和漫长,因为:
- 由于一个具体场景相对于整个项目要简单得多,相比传统方式下各个系统各顾各围绕所有功能进行开发,开发内容相对简单很多,集成的难度也相对低;
- 首选场景的开发其实为其他开户场景打下了大量基础,其他场景的开发会相对快和容易很多,交付会加速;
- 可以采用微服务架构、云服务、容器和像Spring Boot这样的快速开发框架在技术上大大缩短了从搭地基到业务逻辑开发的前置时间。
项目X中,开发第一个用户故事确实会是开发周期最长的一个用户故事,但是由于它为其他用户故事打下了大量基础,它们的开发会大量重用第一个用户故事的代码,开发与交付会大大加快。
基于场景更易理解和测试
因为场景具体和相对简单明了,不像传统需求的功能描述那么抽象和割裂,它更容易解释、理解和测试,也是测试驱动开发(TDD)和行为驱动开发(BDD)的基础。
基于场景考虑用户体验
设想场景也是考虑用户体验的过程,前面提到的更早和频繁获取的用户反馈也包含用户体验。
用户体验并不是互联网产品的专有名词,在传统的业务开发中,用户体验同等重要,只是它一直在瀑布开发中被忽视。
在项目X后期,离原定交付日期只有一个月了,客户提出在测试过程中发现,由于一个请求需要在不同系统中处理,很难追踪,建议增加一个统一的请求ID作为识别。这时我们有两个选项:
- 我们的目标是按照计划把原定的所有报表按时交付,因此这是新的需求或需求变更,不应该在这个时候考虑;
- 我们的目标是实现业务价值,客户在测试中发现的这个问题在上线后必然会被无限放大,不解决这个问题,用户体验和可用性极差,我们应该优先解决这个问题。由于时间有限,我们要和客户沟通能否先集中精力测试某类报表,确保操作的用户体验和可用性,把一个月后的发布目标改为先上线这类报表,实现部分业务价值,其余报表在这次发布后再测试和上线。
前者是瀑布的思维,后者是敏捷的思维。而按照瀑布思维交付,就像我们新装修完一间会议室,电视机、视频会议主机、电话都有,每个设备单独都能通电开启,但是电视机不能连接视频会议主机进行视频会议,也不能连接电脑进行演示,电话也没有设置好不能进行通话,也就是所有设备对用户来说其实都是不可用的。这样的交付有何意义?这几个需求哪怕只有一个能被满足,都比现在这种情况要好。
其实每个项目的需求或产品的设计,都是由一个个具体的场景构成的
如果我们和客户能从一开始就以场景作为切入点,我们的眼里就不再是一个个孤立的功能,而是一个个有具体业务价值、可交付的用户故事,开发的过程便是这一个个业务价值的持续交付过程,这也是一个产品长期演进的过程,项目只是产品演进的一个个小插曲,软件开发中最不可控的因素——时间对于客户来说也变得不那么敏感。在此基础上,再结合其他敏捷方法论和实践,锦上添花。
总 结
传统瀑布开发是半成品堆积而且缺乏快速反馈的过程,传统需求只考虑功能而不考虑场景和用户体验。敏捷开发是基于用户故事的业务价值的持续交付过程。把项目拆分成用户故事是实施敏捷的基础。具体用户场景+用户故事地图是定义好用户故事的一个具体方法。
【IDCF共创读书会】第2期汇报在【冬哥有话说】免费直播,关注公众号回复“共读”获取地址
- 12月9日(周四)晚8点,共读《持续交付2.0》