如果只有强有力的的规范而缺乏敏捷,将导致官僚作风,进而停滞不前;缺乏规范的敏捷如同一个新公司在盈利之前的不负责任的狂热。          -Barry Boehm

软件系统在我们的社会中扮演着举足轻重的角色,及时构建出稳定高效、符合用户需求的软件系统一直是软件从业者的追求。当今剧烈的商业竞争形势下,在快速构建、快速响应需求变化方面对软件开发提出了更加迫切的要求。我们知道决定软件产品质量的要素主要是参与项目的开发团队、开发团队所遵循的过程(流程)以及所应用的技术。技术方面我们已经拥有了结构化设计、OO、UML、DBMS、CORBA、DCOM、.NET、J2EE,以及不胜枚举的编程工具、编程语言,可以说在已经明确所构建系统范围的前提下,现有的技术基本可以满足构建的要求,那么如何通过人和过程这两个要素的改进为软件系统的质量提供增益?两个要素孰轻孰重?如何在项目实践中进行平衡?

在早期软件开发中缺乏规范的流程会导致项目和产品的混乱,集中表现为难以集成、交付延期、质量不佳、成本大大超过预算。在一个大型软件项目几近失败的时候,典型的批评的声音如下:“软件工程学科已经有很多年了,但是至今仍未能提供信息时代社会所需的、成熟的软件工程规范”。为了解决软件开发规范化管理的问题,随即出现了若干规范开发的方法。CMM(能力成熟度模型)作为软件过程规范的代表,将软件开发佳实践分类为若干关键过程域,进而形成了过程改进的框架,并且可以作为衡量组织开发能力成熟度的标准。这种规范是基于工程规范和大型软件系统开发而制定的计划驱动方法,强调软件系统开发的可预见性,通过流程标准的可重复性提高开发的效率和质量。

由于CMM是软件开发佳实践的集大成者,几乎囊括了软件过程的方方面面,但是软件项目所采用的过程应该与该特定项目的特性(包括规模、业务领域、变更程度)、开发团队的技能和文化、风险等环境相匹配。非常遗憾的是流程的制定者、质量保证人员乃至项目经理几乎不具备足够的经验和专业能力:根据项目的实际情况裁剪出与之匹配的流程,生怕进行了过度的裁剪导致项目失败;结果是将制定的整套流程不作任何修改(或者仅仅进行了细枝末节的修改)让项目去遵循,甚至任何项目的生命周期模型都简单的选择了瀑布模型或者是V模型。可以想象适用于航空管理系统开发的流程规范被应用于开发周期仅有半年的小型规模系统的情景!另外对CMM的误解:迷信成熟度等级,认为成熟度级别越高意味着更高的软件质量,会将全套的流程、文档看成项目成功的安全保障,却将产品、需求扔在一边,软件开发成了彻头彻尾的官僚主义。其实倒不妨将CMM看成一本字典,根据需要表达的意思来选择你必要的字词进行有机组合,而不是将整个字典统统罗列出来。

大量的计划、文档可以作为规范管理的显著特征之一,也是广大软件开发人员对此持有异议的主要原因之一。以极限编程(Extreme Programming ,XP)为代表的敏捷(Agile)开发方法的吸引人之处在于对繁文缛节的官僚过程的反叛:不再面向文档,而是面向可执行的代码,根本的文档应该是源码。其实文档的多少只是表面现象,真正的差异在于敏捷型方法是“面向人”的而非“面向过程”的,是“适配性”而非“预设性”,也是欢迎过程中的变化。极限编程是一种面临迅速变化的需求进行快速开发的轻量级的开发方式,强调拥抱变化、短迭代周期和短发布周期、简单设计、用户参加开发、持续集成和重构。假设当前的项目特征符合极限编程的要求和约束,实际上应用极限编程的难度偏高,需要紧密的客户关系、精英的团队、对XP各个实践的精通。看看下面这个例子:

极限编程专家Robert C. MARTIN曾经碰到过一个人,此人声称自己的组织正在使用XP。MARTIN问他如何看待结对编程,此人答道:“我们不结对编程。”MARTIN又问他重构进行得怎么样,此人答道:“我们不重构。” MARTIN又问他计划游戏的效果如何,此人答道:“我们没有计划游戏。” MARTIN问道:“那么你们做了什么?”得到的回答是:“我们只是不写任何文档!”

我想这位老兄是将极限编程当作了无序的“code-and-fix”,根本不了解各个实践的含义,更谈不上对各个实践的熟练运用,可以想象该项目失败肯定 “会归于极限编程所赐”;甚至有人攻击极限编程的“40小时”工作,认为IT人员不得不加班,因此通过5×8的工作无法完成工作,殊不知极限编程提倡的稳定的工作节奏(Sustainable Pace),是指项目开发需要持续稳定的工作效率,是马拉松式的长跑,而不能通过跑百米的方式奢望一蹴而。其实对于规范和敏捷两个方面都存在了大量一知半解的人,他们根据自己的喜恶来随意扭曲原来的真正涵义、“裁剪”流程或者断章取义的割裂活动实践,并将项目的失利归咎于流程。下面让我们看看两种开发方式真正的区别在哪里(下面仅仅列举了主要区别):

敏捷方式采用较短的迭代和发布周期,根据上一次迭代的完成情况、需求的变化等信息规划未来的进度计划,在制定计划过程中强调协调沟通,开发人员和用户统一确定需要完成任务的优先级;规范方式通常采用瀑布模型,即使采用了增量式、螺旋式的开发生命周期模型,一般的发布周期也较长,通常会在开发过程中不同的阶段修正计划,这种方式在项目规模较小、需求变化较大的情况下,开发过程会显得臃肿而低效:“规范化”的处理需求变更活动会占用大量的时间,令人烦恼的是即使在需求开发阶段投入大量工作,也很难获取终的用户需求(用户在真正触摸到系统并用一用它之前无法提供完整的需求),也无法使需求变更率下降到“理想”的程度;

对于开发成员之间的沟通,敏捷方式将系统的“隐式知识”保存在项目成员的头脑中并保持一致,并不维护大量显式的文档,在项目规模和成员数量不大(100人行吗?50人?20人?——20人到底行不行无法确定,不过10个人肯定行。现在回顾一下你领导和参与的项目行不行吧!)并且具备足够的业务水准的情况下,确实可以节省大量的时间,将主要精力聚焦于需求和尽快可执行交付件;而规模进一步增加、团队中包括一些新手时,“隐式知识”会凸现扩展能力不足、人员无法通过头脑和少量文档同步和维护大量信息的劣势,这时通过文档进行显式的维护信息一致性会更加适合;

敏捷开发的一个基本假设是变更成本/时间曲线可以保持平稳,这样后期的持续设计、重构等活动才会是低成本的,但是其强调的简单设计是否会保证架构具有足够的伸缩性,进而使变更成本/时间曲线可以保持平稳呢?这似乎自相矛盾;不过Martin Fowler、Robert C. MARTIN这种设计模式方面的泰斗认同简单设计是可行的,我等凡人也无话可说啦,不过我想不明白到底什么样的设计才能算作“简单设计”呢?以上是敏捷方式所提倡的“反射(或者响应)式”的设计方法,另一种是预见式的方法:架构师会预计变更并实现通过设计避免这种变更带来的影响。听起来不错,问题是变更是否会象你所期望的那样变更?如果答案是否定的,根据猜想的需求而进行设计的系统架构可能会失效,那么耗费的大量时间是否值得?要知道修改的时候有大量的文档工作等着哪!

敏捷方式将用户作为开发团队的一分子,开发过程中用户和开发人员坐在一起进行无缝的沟通,用户提供了基本需求并指出优先级、随即验证了实现的需求并及时给出反馈,这种方式无疑会使开发效率更高、真实需求的真正实现有了保证,风险是开发团队具有良好的客户关系使得客户坐在你旁边吗?你能找到称职的客户进行合作吗?当用户看到软件修改是如此的“简单”,是否会大大增加他不再认真审视自己的需求、频繁变更的勇气?如果这样,开发人员会陷入没完没了的变更当中!另一种处理需求的方法是与用户签订合同(敏捷方式当然也要签订合同,否则如何付费),要求用户对需求规格进行确认并基线化,需求变更太多要额外付费啦。实际上在这个时候要求用户对自己的需求和变更进行承诺,如果你是用户,你会有勇气承诺吗?