文|武毳
互联网时代,硬件、应用软件更新速度赶不上人们需求的增长。软件的数量急剧膨胀,软件需求日趋复杂,维护的难度越来越大,开发成本令人吃惊地高,而失败的软件开发项目却屡见不鲜。“软件危机”就这样开始了。
软件危机一方面是由软件生产本身存在着复杂性,另一方面却是与软件开发所使用的方法和技术有关。软件工程学正是为克服软件危机而形成的新的学科,但可惜的是时至今日人们并没有完全克服软件危机。
软件开发中当连续地犯错误时,我们会对错误进行诊断,并在过程中增加更多的约束和人为制品来防止以后重犯这样的错误。经过多次这样的增加之后,我们就会不堪巨大、笨重的过程的重负,极大地削弱我们完成工作的能力。一个大而笨重的过程会产生它本来企图去解决的问题。降低了团队的开发效率,使得进度延期,预算超支。它降低了团队的相应能力,使得团队经常创建错误的产品。遗憾的是,许多团队认为,这种结果是因为他们没有采用更多的过程方法引起的。因此,在这种失控的过程膨胀中,过程会变得越来越庞大。
2001年初,由于看到许多公司的软件团队陷入了不断增长的过程的泥潭,一批业界专家聚集在一起概括出了一些可以使软件开发团队具有快速工作、响应变化能力的价值观(value)原则。他们称自己为敏捷(Agile)联盟。在随后的几个月中,他们创建出了一份价值观声明。也就是敏捷联盟宣言(The Manifesto of the Agile Alliance)。
(1)个体和交互胜过过程和工具。
人是获得成功的最为重要的因素。如果团队中没有优秀的成员,那么就是使用好的过程也不能挽救失败的项目。但是,不好的过程却可以使最优秀的团队成员失去效用。如果不能作为一个团队进行工作,那么即使拥有一批优秀的成员项目也会失败。
一个由平均水平程序员组成的团队,如果具有良好的沟通能力,将要比那些虽然拥有一批高水平的程序员,但是成员之间却不能交流的团队更有可能获得成功。
团队的构建要比环境的构建重要得多。应该首先致力于构建团队,然后在让团队基于需要来配置环境。
根据调查总结:一般团队都具备创业型团队的特点:一个优秀的lead,带多名水平一般的员工;这样的团队存在两个问题:1)优秀员工的引入,受lead的水平限制;2)员工各自为政的开发模式,分享不够。
团队中的优秀人才并不是越多越好,优秀人才太多反而有更大的弊端。一是人力成本太高,他们可能消耗掉产品创造的大部分效益,那么就不划算了。二是团队分裂的风险太高,因为团队的空间有限,无法同时满足很多优秀人才事业发展的欲望;所以,团队的优秀人才恰好够用就行。
软件开发团队的lead应当具有四项素质,按级别从低到高排列;不错的技术才能(一段)较强的管理才能(二段)丰富的产品开发经验(三段)敏锐的商业头脑(四段)。目前大多数IT企业在物色团队的领导时,主要考察候选人的管理能力和技术能力。对于搞技术出身的人,如果他能当上小头目,一般地讲他的技术才能不会太差。然而即使技术水平是团队里最强的,如果他不具备带领团队所有成员正确干活的能力(即管理能力),那么他也就不不适合当lead。
(2)可以工作的软件胜过面面俱到的文档。
没有文档的软件是一种灾难。代码不是传达系统原理和结构的理想媒介。然而,过多的文档比过少的文档更糟。编制众多的文档需要花费大量的时间,要使这些文档和代码保持同步,那么就要花费更多的时间。如果文档和代码之间失去同步,文档就会变成庞大的、复杂的谎言,会造成重大的误导。
(3)客户合作胜过合同谈判。
成功的项目需要有序、频繁的反馈。不是依赖于合同或者关于工作的陈述,而是让软件的客户和开发团队密切地在一起工作,并经常地提供反馈。项目成功的关键在于和客户之间真诚的协作。
(4)响应变化胜过遵循计划。
响应变化的能力常常决定着一个软件项目的成败。当我们构建计划时,应该确保计划是灵活的并且易于适应商务和技术方面的变化。
图1
较好的做计划的策略是:为下两周做详细的计划,为下三个月做粗略的计划,再以后就做极为粗糙的计划。计划中这种逐渐降低的细致度,意味着我们仅仅对于迫切的任务才花费时间进行详细的计划。一旦制定了这个详细的计划,就很难进行改变,因为团队会根据这个计划启动工作并有了相应的投入。然而,由于计划仅仅支配了几周的时间,计划的其余部分仍然保持着灵活性。
综观上述四个过程,敏捷开发强调以人为中心,而不是以过程为中心,强调尽可能的沟通(与客户,与团队成员),尽可能地以最简单的设计解决问题(从而能够拥抱变化)。
敏捷开发不同于以往的瀑布式开发,非常适合需求变动的情况,敏捷开发的工作量是随着需求的变化而不断发生变化的,所以整个过程中浪费很少(如图1所示)。
与传统的软件开发方法惧怕需求变化相反,敏捷团队依靠变化来获取活力。团队几乎不进行预先设计,因此,不需要一个成熟的初始设计。他们更愿意保持系统设计尽可能的干净、简单,并使用许多单元测试和验收测试作为支援。这保持了设计的灵活性、易于理解性。团队利用这种灵活性,持续地改进设计,以便于每次迭代结束所生系统都具有最适合于迭代中需求的设计。
上面的描述非常美好,读者不禁会问:敏捷开发人员如何知道要做什么的呢?
答案是:
(1)他们遵循敏捷实践去发现问题;
(2)他们应用设计原则去诊断问题;
(3)他们应用适当的设计模式去解决问题。
软件开发的这三个方面的相互作用就是设计。
到目前为止,已经有许多的敏捷开发方法可供选择,包括Scrum 、Crystal 、FDD(Feature Driven Development)、ADP(Adaptive Software Development)、XP(eXtreme Programming)等。Scrum是最常用的方法之一。Scrum本意是橄榄球运动中的争球。在一般人的印象中,橄榄球运动是非常野蛮的,球员目的非常明确——破门得分。你可以抱着球跑,可以传给队友……各种方式都可以,目的就是要快速得分。敏捷开发就需要这种精神。下面我们来看一下Scrum大概的流程(如图2所示)。
1、在一个Scrum项目中,产品负责人(Product Owner)建立待开发的产品条目(Product Backlog),并确定其优先级。开发中需求的改变也要写进去,对于调研、查阅资料、配置环境等也应考虑进去,因为这些也很占用时间,敏捷开发中不提倡冲刺,不提倡加班,讲究发挥团队最大价值;
2、根据所列P r o d u c t Backlog情况,确定产品一个迭代(Sprint)所要完成的东西,每一个Sprint大概是2-6周的时间;
3、Sprint开始前,需要开一个迭代计划会议(Sprint Planning Meeting)会议。会上,产品负责人(Product Owner)讲解本次开发要开发的条目(Story),将确定的Story放入Sprint Backlog中来;
4、Sprint开发过程中,团队每天都要开一个站立会议(Daily Stand-up Meeting),以便团队之间了解彼此的开发进度;
5、Sprint结束之后,需要开评审会(Review Meeting),Scrum团队会在评审会议上把这个迭代的开发成功展示给大家;
6、之后还要开一个反思会(Retrospective Meeting),Scrum团队会回顾过去这个Sprint,从中总结经验教训。
传统的项目负责人也罢,敏捷的项目负责人也罢,都会制定计划,而且会为之投入相当的时间。但是他们对待计划的态度截然不同。在敏捷开发中,我们采用“调整性行为”来说明应该采纳的一些正确做法(其中之一便有可能是纠正计划本身)。
1、知晓变化(即不确定因素)可能随时发生,面对突发的变化,要进行相应的调整,而不能继续按原计划执行。
实际工作中我们会遇到:客户提出新的要求,开发团队的经验不能马上告诉:这个技术需求能不能实现或需要多长时间实现。一般需要三天时间进行预研,这样才能知道是否能做,需要多少时间完成。然后修改部分计划。
2、必要时,对项目的过程和实施办法做出随机调整。
(1)调节项目中的已知和未知。
哈佛商学院教授罗布·奥斯丁(Rob Austin)和同事李德文(Lee Devin)共同执笔发表了《艺术性管理》(Artful Making)一书。书中提到一个价值1.25亿美元的IT项目最终失败的案例。失败的原因正是由于合作企业一味坚持原计划,亦步亦趋死板执行,拒绝用调整来应对突发的变化而造成的。书中写道:“‘为工作制定计划,然后按照计划做事’成了让他们盲从的真言,直接导致团队采取了毁灭性的做法,带来惨重的代价。…… 在商界,人人都以为这种问题很少发生,可实际上却非常普遍。”
现实中每一个项目都有其已知的条件和未知的因素,有其确定的一面以及不确定的一面,因此每一个项目都必须在计划和随机调整之间取得平衡。这种平衡是必须的,因为项目可以是生产性的,也可以是开发性的,还可以是介于两者之间的。生产性的项目不确定性很低,而开发性的项目却是高度不确定的。开发性项目强调预见性,项目执行的过程,就是朝着预见的方向探索前进的过程,而不是制定出严密周详的计划,然后严格实施的过程。也就是说,计划或调整,不能说孰对孰错,管理者应根据项目自身的具体情况、具体条件,作出最恰当的选择。
实际中经常遇到类似这样的情况:
Product owner(需求方,可以是产品经理,可以是甲方,可以是单位的主管)不可能一次想清楚所有需求时,产品上线前的灰度发布会有些修改,上线后还要根据用户的反馈,可能还会进行不止一次的修改。(例如,如何鼓励用户进行评价。开始是要求用户必须评价,后来用户评价的频度降低了,而且大多是“哈哈哈哈哈”等无效评价;又选择做趣味性界面,增加了动画,但时间长了,也就降低了趣味性。有效评价还会再次降低,再次面临新的修改。)
(2) 驾驭风险,抓住机遇
人们不想采取敏捷的做法时,往往会找各种借口、理由,甚至抱怨:“这样做太费时间了”,或者“这样做成本太高”等等。所以无论是短期试点,更新数据,随时整合,自动检测,还是其他的各种变通性做法,总是会遇到这样的托辞。
多数情况下,虽不尽然,找种种借口拒绝调整,往往会直接导致效率低下,因为它让企业失去了精简流程、提高随机应对的机会。培养团队的敏捷性,必须进行小型的试点;而小型试点的目的就是找到方法,让重复的工作环节能够低成本地快速完成。而快速且低成本的工作习惯,又能促使团队面对变化,另辟蹊径。快速低成本的解决办法,还能够鼓励团队勇于创新,从而锻炼团队的创新精神。而这种创新又会影响到企业的其他部门,产生涟漪效应。这样一来,降低成本应对变化,就会促使企业重新思考它的商业模式。
(3) 采取可靠的而不是可重复的步骤
必须指出“可重复的”并不意味着敏捷。虽然实施可重复的步骤,已经成为许多企业的管理目标,但在产品开发的过程中,追求可重复的目标却不仅是错误的,而且会极大的遏制产品的开发。可重复意味着用同样的方式,做同样的事情,产出同样的结果。而可靠性却指的是无论遇到什么困难障碍都要实现既定的目标——也就意味着不断的做出调整,应对各种变化,实现既定目标。
可重复的步骤,通过制定标准和对流程的不断改进,来减少产品的质量变化。这是一个源于制造业的词。因为在生产制造中,产出什么样的产品,是已经定义好的。那么可重复性就意味在生产过程中,只要连续输入,就可以产出预期的结果。可以重复意味着从输入到产出的转换过程是可以复制的,而无需任何变化。它还意味着生产的过程不会有任何新情况发生,因为所有信息都全部预先知道,来保证最终的精准产出。但是,可重复的步骤在产品开发中毫无用处,因为首先很难精准地判断出最终的结果;其次项目不同,项目的投入也大不相同;第三,开发不同产品,从输入到产出的转换过程本身更是大相径庭。
可靠的步骤过程关注的是产出,而不是投入。哪怕是投入完全不同,通过采取可靠的步骤,项目成员也能够想出各种办法,不断向既定的目标靠拢。也正因为投入的差异,他们决不会把一个项目所采用的步骤或做法,亦或是试点,复制到另一个项目中。
可靠性是受结果驱动的;而可复制性是受输入驱动的。如果把项目的步骤固定下来,那么项目本身就会因为投入和转化的巨大差异,而变得极其危险。即便是那些声称采用了固定步骤且获得成功的企业,他们的成功并非来自于固定的、可重复的过程本身,而是来自于企业员工在实施这些步骤时,进行的敏捷调整。
敏捷开发项目管理(APM)既是可靠的,又是可预测的:这样的项目过程,由于考虑到了各种不确定性因素,因而在规定的时限内开发出的产品,最能满足客户不断变化的各种需求。这一点是其他任何一种管理方式都无法比拟的。而之所以能够这样,不是因为项目经理制定出了极其周详的任务计划,也不是对这个计划实施了精微细致的管理,而是因为敏捷的项目管理者,营造了一个这样的工作环境和氛围:人人追求卓越,并愿意为实现目标而努力。
敏捷管理虽然是可靠的,但也并非是无往而不胜的,因为它并不能消除所有的不确定性,也无法避免全部的意外。但是,这样的管理方式能够设法转化意外和不确定性,使项目最终走向成功。
总结来说:敏捷设计是一个过程,不是一个事件。它是一个持续的应用原则、模式以及实践来改进软件的结构和可读性的过程。它致力于保持系统设计在任何时间都尽可能得简单、干净以及富有表现力。
软件大师、C++之父Bjarne Stroustrup曾经说过:设计和编程都是人的活动。忘记了这一点,将会失去一切。敏捷软件开发方法正是认识到软件开发的这一本质特征而提出的革新性开发方法。虽然完全做到很困难,但坚持使用敏捷开发方法一定会给我们带来巨大的好处。