敏捷软件开发方法受到越来越多的关注。图(一)是来自Google 趋势的数据,它反映了近年来Scrum(敏捷开发方法的典型代表)和 CMMI(传统开发方法的典型代表)的相对搜索量变化趋势比较。在2004年CMMI的搜索量还是Scrum 的接近3倍,2007年Scrum的搜索量第一次超过CMMI。时至今日,Scrum的搜索量已超过CMMI三倍。
图1 Scrum 和 CMMI相对搜索量的趋势比较
这只能说明一个问题 —— 敏捷很火!问题是,它应该是你的选择吗?先听听别人怎么说,培训机构说:“它是两天的培训”;咨询公司说:“你需要贴身辅导”;工具提供者说:“你out了,该升级啦”; PMI说:“我们也敏捷了,第一期敏捷项目管理认证马上开始”[1];SEI说:“CMMI也敏捷了,我们已经在CMMI 1.3版中为重要的KPA(关键过程域)添加了敏捷的标签”[2];还有人说:“敏捷是神马?”。
敏捷被赋予了太多的含义,甚至承载了利益,有时还让人迷惑。本文并不试图去定义敏捷。但,我们会分别从外部(业务视角)和内部(开发模式及组织视角)观察正在发生的敏捷,并提交观察报告。
从外部(业务视角)看敏捷
离开用户的价值、离开组织的业务目标去谈开发模式的转变只有两种可能——“自以为是”或“别有用心”。我们对敏捷的观察将首先从业务目标出发——从外部看敏捷。
1. 反摩尔定律 ⇒ 速度关乎生死,增量交付价值
IT从业者都知道“摩尔定律”——同样的钱所能买到的产品性能,将每隔18个月翻两倍。Google的前CEO 埃里克? 施密特在一次采访中指出,如果你反过来看摩尔定律,一个 IT 公司如果今天和十八个月前卖掉同样多的、同样的产品,它的收入就要降一半,在IT领域这被称为“反摩尔定律”。反摩尔定律告诉我们,同样的产品所能获得的价值,随时间按一定斜率下降。更有甚者,错过了一个时间窗口,产品可能就不再有任何价值。产品推出的迟早,不仅影响获得回报的时间,还影响到获得价值的多少,甚至是有无。
在竞争激烈和复杂多变的市场环境中,快速把概念转化为产品推向市场的能力事关组织的生死。然而,做到这一点并不容易。增加人手?受资源制约。而且,因沟通复杂度的增加可能反使项目延期,这一点在《人月神话》中早有论述。提高开发效率?那不是一朝一夕的事情,敏捷开发实施也不直接带来开发效率的提高。
敏捷软件开发的应对之道是改变价值的交付模式。如图(二)所示,在以瀑布模型为代表的传统开发模式下,只在项目开发完成时一次性交付全部的价值,在此之前的产出都是半成品。敏捷软件开发倡导迭代和增量的价值交付模式,如图(三)所示,在敏捷软件开发模式下,产品开发进程被划分成固定时长的短迭代周期,每一个迭代产出潜在可交付的产品增量,产品的一部分价值得以实现。
图2 瀑布模型下的价值实现
图3 敏捷模式下的增量价值实现
为了做到价值的增量交付,需求要被拆分成小的端到端可交付单元。同时,小的需求便于沟通,团队、业务人员以及客户,更容易对特定需求进行深入、具体的讨论和澄清。小的需求也便于管理,可以灵活地安排迭代计划,在图(三)的价值实现的阶梯中,越是靠前的迭代,交付的价值越大。优先实现高价值的需求,在迭代开发模式下,是一个很自然的选择,这样组织可以在最短的时间获取尽可能多的价值。
后面我们还会看到,迭代和增量开发模式影响的不仅是价值交付的模式,它还是很多其它敏捷实践(如及时的策略调整,风险消除等)的前提。
我们可以开始交付我们的观察报告了,当然,它也会是增量交付的。
从外部(业务视角)看敏捷 - 敏捷软件开发遵循迭代和增量的开发模式,以尽快实现和交付用户价值 - …… |
2. Netscape之死 ⇒ 增量交付还不足够,可持续才有意义
Netscape(网景)死了, 2007年AOL宣布将停止对Netscape的支持。90年代的互联网用户还会怀念它,它最高时占据了浏览器市场86%的份额。Netscape 的衰落有很多原因,众所周知的是微软利用了它在操作系统市场的优势。回顾这段浏览器大战的历史,特别是最关键的1997年到2001年,会有一些其它的发现。
1997年6月Netscape推出了Netscape4.0,其后差不多三年半的时间里,Netscape没有推出过一个主要版本,而微软先后推出了突破性的IE4.0和IE5.0,取得完胜。图(四)来自“Practices for Scaling Lean & Agile Development”一书,很好地展示了在这段时间浏览器版本的推出和市场份额变化的关系。
图4 浏览其市场份额及其版本
难以置信,在1997 - 2001这三年多的时间里Netscape在做什么?微软在1997年底推出了IE4.0,1999年推出IE5.0,在功能上全面超越了Netscape 4.0,而此时Netscape 4.0却不得不面对越来越多的奇怪的Bug。更严重的是,Netscape的代码是如此之糟糕,以至团队认为,再也无法基于它做重大的修改了。为此,Netscape 做出了一个重大决定 —— 重写代码。2001年初Netscape 终于推出了6.0(从来没有过5.0),但这时Netscape的市场占有率已经降到了5%以下,这场浏览器大战胜负已决。
这是一个悲情的故事,Netscape的工程师们绝望地看着Netscape的市场份额急剧萎缩,却无法在产品上采取任何行动。一定程度上Netscape死于自己糟糕的系统质量 —— 在发展时期所欠下的技术债务。在软件行业,这绝不是个案。Netscape的故事告诉我们,忽视长期质量的价值交付最终将无法持续。敏捷软件开发遵循迭代和增量的开发模式,价值得以更快的实现,但如果忽略了质量,这也会意味着更快的积累问题。以下是在迭代交付过程中忽视质量所引发的一些典型问题。
- 前期迭代留下的烂摊子,始终没能清理,问题越积越多
- 既有功能越来越多,迭代中的测试工作量越来越大
- 既有功能总被新的发布破坏
- 代码越来越复杂,添加一个功能需要的工作量越来越大
- 客户开始抱怨,不再愿意接受增量交付
可持续的价值交付才能给组织带来长期的效益,为实现价值交付的可持续,“内建质量”是敏捷软件开发的必然选择,它体现在两个方面:
- 预防问题的发生
在敏捷软件开发中,检查和测试的目的是防止问题的发生,而不是发现问题。Mary Poppendieck曾经这样形容测试的作用,她说:“测试人员的作用不是挥舞拍子赶走蚊子,而是装上纱窗”,为此要做到更早和更频繁地测试(test early, test often),自动化是必然的选择。及时和有效的自动化测试是系统的安全屏障,从源头上防止缺陷的注入。对于问题的预防还体现在一些其它的敏捷管理和技术实践中,如 “持续集成”和“结对编程”等。
- 不让问题积累
为了不积累问题,每一个迭代的交付都要达到特定的质量标准,质量标准同时包含用户可见的外部质量,和系统的内部质量。外部质量,如是否通过集成测试和性能测试等,直接影响用户的当下体验;内部质量,如不良的代码设计是否被重构,是否包含必要的自动化测试覆盖等,影响系统的可扩展、可维护性以及将来的开发效率。为迭代交付的软件定义明确的质量标准,这在敏捷实践中被称为Definition of Done(DoD)。定义合理的DoD,并确保每个迭代交付的软件都达到DoD的标准,是团队维持迭代交付节奏的前提。
即使在迭代之内,也应尽早暴露系统中的问题。尚未集成和测试的代码隐藏沟通、设计和实现的问题,应该尽量早的进行集成和测试。通过“持续集成”技术实践的实施,做到每天至少一次或多次的代码集成和验证。如果多个团队共享一个代码库,那么持续集成实践就需要拓展到所有这些团队。
好了,第二次交付观察报告。
从外部(业务视角)看敏捷 - 敏捷软件开发遵循迭代和增量的开发模式,以尽快实现和交付用户价值 - 敏捷软件开发在增量交付过程中内建质量,以保证价值交付的可持续性 - …… |
* 一个题外话:后来Firefox基于Netscape 重写的代码起家,势头很不错,说明那次重写技术上是成功的。但又如何,只能印证前面的一点,错过时间窗可能意味着失去全世界。
3. 应时而变 ⇒ 抗拒不可预知的变化,还是打造适应变化的灵活性
在“The Agile Samurai”一书中,作者陈述了软件项目的三个简单事实,并指出接受并正确对待这些事实可以避免软件项目中很多误区。这三个事实是:
- 不可能在项目开始的时候收集到所有的需求
- 不管你收集到什么样的需求,它一定会发生变化
- 要做的功能,一定会超过时间和金钱允许的范围
每一次软件开发都是对未知领域的探索,无法预知一切。问题是,面对不可预知的变化,组织应采取什么样的策略,是“抗拒不可预知的变化”还是“打造适应变化的灵活性”?传统软件工程的思路更接近于前者 —— 在项目开始时去预测用户的需求,然后冻结需求,制定相应的开发计划,再按照计划执行,这一过程被称为“预测性的过程”;敏捷软件开发通过不断的反馈和调整,动态地达成目标,这一过程被称为“自适应过程”。
图5 传统的预测性软件过程和敏捷自适应过程比较
图(五)从概念上比较了传统的预测性过程和敏捷的自适应过程。不管你如何预测和计划,最后的实际目标总会发生变化,执行过程也会出现偏差,面对软件开发这样复杂的活动,预测性过程很难奏效。相对应的,敏捷的自适应过程强调反馈和调整,在开发过程中不断修正方向和行动计划,在复杂的市场环境和技术环境中把握和实现业务目标,打造适应变化的灵活性,与价值的交付速度一样,它们都是应对激励竞争和复杂多变的业务环境的核心竞争力。
敏捷软件开发过程承认软件开发的复杂性,致力于构建更加灵活应变的软件开发过程。在迭代开发模型的基础上,每一个迭代完成时,团队更加深入的理解了产品及其构建技术,用户也更加清楚自己的需求。团队根据这些新获取的知识和获取的用户反馈,调整产品方向、需求定义以及技术路线,这些调整将直接体现在接下来的迭代的开发活动中。通过这一过程,团队能够更准确的把握用户需求,适应技术和市场环境的变化。
观察报告的第三次交付。
从外部(业务视角)看敏捷 - 敏捷软件开发遵循迭代和增量的开发模式,以尽快实现和交付用户价值 - 敏捷软件开发在增量交付过程中内建质量,以保证价值交付的可持续性 - 敏捷软件开发在开发过程中不断反馈和调整,以获得适应市场及技术环境变化的灵活性 - …… |
4. 与熊共舞 ⇒ 面对风险,需要的不仅仅是勇气;积极和系统性的应对风险
“与熊共舞”来自关于项目风险管理的同名著作,“熊”指的是项目中的风险。“风险与收益共存,通过掌控风险获取相对竞争对手的优势”,这是“与熊共舞”背后的含义。拒绝风险,会使组织丧失竞争优势;承担风险,但在操作上忽略它,同样会把项目带向失败。
风险来自复杂系统开发的不确定性,敏捷软件开发接受并应对不确定性,自然也必须面对风险。掌控风险体现在敏捷软件开发的方方面面,可以说在某种程度上敏捷开发过程就是风险掌控的过程。以下是敏捷开发过程中应对各类风险的策略。
- 业务风险
开发错误的产品是最关键的项目风险。通过敏捷软件开发方法,更早和更频繁的交付产品,获取反馈,及时调整产品开发方向,极大地降低了开发错误产品的可能。更紧密地与用户协作,现场客户参与开发过程,定期向用户演示产品等实践都有助于对产品的方向作出及时的修正。
不确定性并不意味着范围的无限蔓延,敏捷软件开发包容不确定性,同时为不确定性的设置边界。例如在典型的敏捷方法Scrum中,通过产品待办事项(Product Backlog)管理需求,产品负责人(Product Owner)对产品待办事项最终负责;根据业务价值设定需求的优先级,并依照优先级的次序实现和交付需求;需求的变更只在迭代之间发生,在一个迭代之内,一般不增加或变更需求;需求的变更,必须以符合业务目标为前提。通过这些边界的设定,团队可以更加有序的掌控不确定性。
- 技术风险
在开发过程中,尽可能早的验证和暴露问题,是应对技术风险的最有效手段。
- 架构的可行性会给项目带来极大风险,在考虑客户价值的同时,尽量在前几个迭代中安排对架构影响比较大的用户需求,以此来尽早地移除架构风险。对一些不确定的技术点,也可以采取类似的策略。
- 很多技术问题往往在集成时才能暴露。持续集成的技术实践,让团队在第一时间集成代码、自动构建和验证软件版本,始终保持一个符合质量标准的可用版本。通过持续集成,使过去在项目后期才能暴露的风险得以尽早的被发现和修正。
- 每个迭代都要交付用户可用的需求,可以尽早的暴露团队在能力方面的不足。
技术上的风险永远存在,它甚至可能会使项目根本不可行。敏捷软件开发容忍失败,但通过不断的反馈,敏捷开发可以做到尽早失败(fail fast),一方面造成的浪费比较有限,另一方还有时间寻找替代方案或实施弥补措施,在这一次的失败中孕育下一次的成功,这也是业务和技术创新的重要源泉。
- 执行风险
对于软件开发这样复杂的活动,估计和计划的偏差在所难免,它会带来项目执行和交付的问题。敏捷软件开发并不否认计划的重要,但在实践上提倡分层次和滚动式的计划。
计划是基于对未来的预测,根据离现在的时间长短,未来的可预测程度是不同的,基于它们的计划也应该有所区别。
图6 可预测性和时间关系
- 近期的将来是可以预测的。
- 稍远的将来可以预测但并不确定
- 远期的将来则很难预测
相应的,敏捷计划也是分层次的, InfoQ的另一篇文章,《敏捷项目的多层面规划》,把敏捷计划的层次分为为:产品愿景、产品路线图、发布计划、迭代计划和每日承诺,并总结了每一个层次的规划包含怎样的详细程度,越是针对近期的计划包含越多的细节,而远期的计划则更是方向性和总体性的。
敏捷开发的计划并不是一次性完成,随着开发进度的推进,团队会逐步细化接下来的工作计划,如在迭代开始前,对任务做具体规划。这种计划方式被称为滚动式的计划,它降低的计划不能适应最新情况的风险,同时减少了不合理计划对执行形成的负面约束。
计划执行的度量和跟踪同样会影响风险的发现和管理,传统上基于任务完成百分比的度量方式,会隐藏计划执行的潜在风险。比如一个项目的进度是100%设计完成,加80%编码完成,与原计划相符。但实际又如何呢?设计可能不合理,代码质量可能未达到要求,到了集成和测试阶段突然出现进度的巨大落后。在敏捷软件开发中把可工作的软件作为进度度量的基本指标,在团队遵循明确的迭代完成标准的前提下,这样的进度度量是更实际和可靠的,进度和交付的潜在风险得以尽早暴露。
另一方面,在迭代交付模式下,如果项目在限期内不能交付所有的用户需求,但至少可以交付已经完成的高优先级需求,而不是“要么全有,要么全无”,降低了风险发生时所造成的影响。
总之:接受和掌控软件开发的不确定性是敏捷开发的重要基础,也是敏捷软件开发应对风险的出发点。风险管理体现在敏捷软件开发的各个环节和方面,敏捷软件开发中的风险管理是积极的和系统性的。承担而不是躲避风险,并由此提升竞争能力,是其积极性的体现;风险应对与开发过程有机集合,而不是仅依靠单独的风险管理实践进行风险管理,是其系统性的体现。
至此,我们可以提交从外部(业务视角)看敏捷的完整的观察报告了。
从外部(业务视角)看敏捷 - 敏捷软件开发遵循迭代和增量的开发模式,以尽快实现和交付用户价值 - 敏捷软件开发在增量交付过程中内建质量,以保证价值交付的可持续性 - 敏捷软件开发在开发过程中不断反馈和调整,以获得适应市场及技术环境变化的灵活性 - 敏捷软件开发系统性的和积极的应对风险,以通过掌控不确定性获取竞争优势 |
对以上四点可以总结为一句话:
可持续的快速交付,和稳健的灵活性。
- 可持续来源于内建质量
- 快速交付来源于迭代和增量的开发模式
- 稳健来源于对风险积极和系统的掌控
- 灵活性来源于不断反馈和调整的开发过程
“可持续的快速交付,稳健的灵活性”,要做到并不容易,它需要开发模式、团队组织和技术的变革,这也是我们在本文的后面的部分要带大家去观察的。
[1] PMI(项目管理协会)旗下的项目管理认证(PMP)在项目管理领域影响巨大,PMP所引用的方法学多为偏重量级的管理方法。2009年初PMI的CEO在他的博客On the Threshold of Agility中表现出对敏捷开发方法和敏捷项目管理极大关注。2011年初PMI宣布将在2011年第4季度推出PMI敏捷认证,详见http://www.pmi.org/Agile.aspx
[2] SEI(软件工程协会)是CMMI的主要开发者,相对敏捷开发方法,CMMI一直被认为是传统软件工程的代表,关于CMMI与敏捷是否冲突在社区中也多有争论。2010年10月发布的CMMI V1.3中增加了敏捷相关的内容,比较突出的是为相关的KPA(关键过程域)增加了使用敏捷方法时的应用指导。