V
VRGL
Unregistered / Unconfirmed
GUEST, unregistred user!
新方法学
英文原文版权由Martin Fowler拥有
Original text is copyrighted by Martin Fowler
Martin Fowler
Chief Scientist, ThoughtWorks
过去几年中兴起的敏捷型(agile)软件开发方法,以矫正官僚繁琐过程,或者许可对过程进行自主调整为特征,在软件业引起了极大的兴趣。在这篇文章里,我将探索敏捷型方法的合理性,着重点并不是放在其“轻重”上,而是于它们的适配性(adaptive)性质和以人优先的理念。我在本文也简要介绍了一些敏捷型方法并给出了进一步的参考材料。另外,我还给出了一些你在决定是否要走这条刚踏出来的敏捷之路时需考虑的因素。
最近一次主要修改: 2001年11月
在SD East 上我作了一次演讲 “让软件恒软〔Keeping Software Soft)” 其材料就是基于这篇文章(你若有充足的时间可浪费的化,不妨一观)。此文的节略版发表于 Software Development Magazine(软件开发杂志) 的2000年12月期。
从无,到繁重, 再到敏捷
预设性与适配性
将设计与建造分离开来
需求的不可预设性
预设性是不可能的吗?
不可预设过程的控制
适配性的客户
让人优先
可兼容性程序插件
程序员是负责任的专业人员
面向人的过程的管理
应用域专家的引领作用
自适配过程
敏捷型方法
XP(Extreme Programming -- 极端编程)
Cockburn的水晶系列方法
开放式源码
Highsmith的适配性软件开发方法〔ASD)
SCRUM
Coad的功用驱动开发方法〔FDD)
动态系统开发方法〔DSDM)
敏捷软件开发宣言
RUP是一种敏捷型方法吗?
其他参考材料
你是否应走向敏捷?
该用哪个适配性过程?
鸣谢
修改记录
从无,到繁重, 再到敏捷
多数软件开发仍然是一个显得混乱的活动,即典型的“边写边改” (code and fix)。设计过程充斥着短期的,即时的决定,而无完整的规划。这种模式对小系统开发其实很管用,但是当系统变得越大越复杂时,要想加入新的功能就越来越困难。同时错误故障越来越多,越来越难于排除。一个典型的标志就是当系统功能完成后有一个很长的测试阶段,有时甚至有遥遥无期之感,从而对项目的完成产生严重的影响。
我们使用这种开发模式已有很长时间了,不过我们实际上也有另外一种选择,那就是“正规方法”(methodology)。这些方法对开发过程有着严格而详尽的规定,以期使软件开发更有可预设性并提高效率,这种思路是借鉴了其他工程领域的实践。
这些正规方法已存在了很长时间了,但是并没有取得令人瞩目的成功,甚至就没怎么引起人们的注意。对这些方法最常听见的批评就是它们的官僚繁琐,要是按照它的要求来,那有做太多的事情需要做,而延缓整个开发进程。所以它们通常被认为是“繁琐滞重型”方法,或 Jim Highsmith 所称的“巨型”(monumental)方法。
作为对这些方法的反叛,在过去几年中出现了一类新方法。尽管它们还没有正式的名称,但是一般被称为“敏捷型”方法。对许多人来说,这类方法的吸引之处在于对繁文缛节的官僚过程的反叛。它们在无过程和过于繁琐的过程中达到了一种平衡,使得能以不多的步骤过程获取较满意的结果。
敏捷型与滞重型方法有一些显著的区别。其中一个显而易见的不同反映在文档上。敏捷型不是很面向文档,对于一项任务,它们通常只要求尽可能少的文档。从许多方面来看,它们更象是“面向源码”(code-oriented)。事实上,它们认为最根本的文档应该是源码。
但是,我并不以为文档方面的特点是敏捷型方法的根本之点。文档减少仅仅是个表象,它其实反映的是更深层的特点:
敏捷型方法是“适配性”而非“预设性”。 重型方法试图对一个软件开发项目在很长的时间跨度内作出详细的计划,然后依计划进行开发。这类方法在计划制定完成后拒绝变化。而敏捷型方法则欢迎变化。其实,它们的目的就是成为适应变化的过程,甚至能允许改变自身来适应变化。
敏捷型方法是“面向人”的(people-oriented) 而非“面向过程”的 (process-oriented)。 它们试图使软件开发工作顺应人的天性而非逆之。它们强调软件开发应当是一项愉快的活动。
在以下各节中,我将详细地探讨这些差别,这样你可以了解适配性和以人为中心的过程是什么,它们的好处与不足,以及你作为软件开发人员或用户时是否应该使用它们。
预设性与适配性
将设计与建造分离开来
传统的软件开发正规方法的基本思路一般是从其他工程领域借鉴而来如土木工程模式对软件工程的影响较大。这类工程实践中,在实际建造之前,通常非常强调设计规划。工程师首先给出一系列的图纸,这些图纸准确地说明了要建造什么以及如何建造(包括部分和整体)。许多工程问题,如怎样处理一座桥梁的负荷,图纸上都有说明。然后,这些图纸分发给另外一组人员,通常是另外一个公司,去建造。这种方式其实已假定了建造过程将按图纸而来。当然,施工中也会碰到一些问题,但这些都是次要的。
图纸其实就是一个详细的建造计划,它说明了一个项目中必须完成的各项任务,以及这些任务之间的依赖关系。这样,管理层能较为合理地制订出生产进度表和项目预算。这种模式实际上也规定了建造者如何做(施工),这也隐含着建造者不须是高智能型的,尽管他们可能都有非常高超的手上功夫。
在此,我们看到的是两类非常不同的活动。设计是难于预设的,并且需要昂贵的有创造你的人员,建造则要易于预设。我们有了设计之后,便可对建造进行计划了。而有了建造计划后,我们进行建造则可以是非常可预设性的了。在土木工程中,建造不论在经费上还是在时间上的花销都要比设计和计划大得多。
所以,多数正规方法的途径是象这样的:我们想要可预定的生产进度计划,以便能使用技能较低的人员。要达到这一点,我们必须得把设计与建造分离开来。因此,在软件开发中,我们得想法作出这样的设计,使得计划一经完成,建造将会是直接而明确的。
那么,计划应该采用什么形式呢?对许多人来说,这是设计“标识符号” (notation),如象UML,需承担的角色了。如果我们能用UML作出所有主要的技术决定,那么就可以用UML来做建造计划,然后把计划交给程序员去编码,即是建造活动。
但这里存在几个问题。你是否能作出这样的设计使得它能够让编码成为一项建造活动?如果能,那么建造是否能在资金和时间上的花销都充分地大于设计而使得这种途径值得一用?
第一个问题是到底有多困难能使一个用类似UML作出的设计达到交给程序员就能直接编码的状态。用象UML那样的语言作出的设计在纸上看起来非常漂亮,而实际编程时可能会发现严重的缺陷。土木工程师使用的模型是基于多年的工程实践,并结晶在工程典章中。更进一步来说,一些设计上的关键部分,如应力作用,都是建立于坚实的数学分析之上。而在软件设计中,我们对UML图纸所能做的只是请专家审阅。这当然是很有帮助的,但是往往一些设计错误只能在编码和测试时才能发现。甚至于熟练的设计者,我自认为我属此列,就常常对在把设计变成软件的过程中出现的错误感到意外。
另一个问题是费用比较。建一座桥梁时,设计费用一般占整个工程的10%,左右,余下的90%左右为施工建造费用。而在软件开发中,编码所占的时间一般要少得多(McConnell 指出在大型项目中,编码和单元测试只占15%,这几乎和桥梁工程中的比例倒过来了。即使把所有测试工作都算作是建造的一部分,设计仍要占到50%)。这就提出了一个重要问题,那就是和其他过程领域的设计相比,软件设计到底是什么性质。
更有甚者,Jack Reeves 认为源码也应是设计文档,而建造应该是编译和链接,因为任何属于建造的工作都应当是自动化的。
这些讨论导致了下面一些结论:
在软件开发中,具体建造费用非常低,几可忽略不计。
软件开发的绝大部分工作是设计,因此需要富有创造性的才智之士。
创造性的过程是不太容易计划的,因此,可预设性不可能成为一个要达到的目标。
我们应该对用传统工程模式来进行软件开发的做法保持足够的警觉,因为它们是不同类型的活动,因此需要不同的过程。
需求的不可预设性
在每个我参加的项目都有这样一种情况,开发人员跑来抱怨说, “这个项目的问题是需求老是在变”。而让我意外的是每个人都对此感到意外。其实在建造商用软件系统中,需求变更是常态,问题是我们如何来处理它。
一种方法是把需求变更看成是因需求工程(requirements engineering)没作好而导致的结果。一般来说,需求工程(或曰进行需求分析)是要在着手建造软件之前,获取一幅已完全理解了的待建系统的画面,然后取得客户认可签发,并且还要建立一套规章来限制需求变更。
该方法的一个问题是要准确获取所有需求是困难的,特别是当开发商不能提供某些需求的费用信息时。例如,你买车时想在你的车上装一个天窗,而推销员却不能告诉你要在车价上只再加10元钱呢,还是10000元。如果不知道这点,你如何能决定你是否愿意在车上加个天窗呢。
作软件开发的费用估算是不容易的,这有多种原因。部分原因是因为软件开发是一种设计活动,因此难于精确计划。部分原因是系统的“基本材料”变化非常之快。部分原因是开发活动极大地依赖于项目参与人员,而个体是难于预测和量化的。
软件的“不可触摸”性也是一个原因。在系统建成之前,有时很难判断一项功能的具体价值。也就是说,只有当你在实实在在地使用系统时,你才能知道哪些功能是有用的,哪些没什么用。
这样的结果颇具讽刺意味,即人们期待需求应该是可变的。毕竟,软件应该是 “软”的。所以,需求不仅是可变的,简直就是应该变的。要让客户把需求固定下来要花很大的力气,特别是当他们“参与”了软件开发并且“知道”软件是多么易于修改。
但是,即使你能把所有的需求都固定下来,并不意味着你的开发就是阳光灿烂了,你可能仍然会在昏暗之中。在当今的经济形势下,决定并推动软件系统功能特性的商业因素飞快地变化着。现在一组很好的功能六个月以后可能就不那么好了。
商业世界并不会因你的系统的需求固定下来了而停止不动,商业世界的许多变化是完全不可预测的。如果有人不承认这一点,要么他在撒谎,要么他已炒股成了百万富翁了。
软件开发的一切都取决于系统需求,如果需求不固定,你就不能制订出一个可预设性的计划。
预设性是不可能的吗?
一般来说,不可能。当然,有一些软件开发项目中,预设性是可能的。象 NASA的航天飞机的软件开发项目,应是这样一个例子。它需要大量的会议,充足的时间,庞大的团队,以及稳定的需求。毕竟,这些是航天飞机的项目。但我并不认为一般的商用软件开发属于这类系统,所以你需要不同的开发过程。
如果你不能遵循一个可预性方法,而你强装能够,那么这是非常危险的。通常,一个正规方法的创造者不是很善于(或乐于)给出其方法的边界条件,换句话说,当这些边界条件不满足时,则该方法就不适用。许多方法学者希望他们的方法能够放之四海而皆准,所以他们既不去了解,也不公布他们方法的边界条件。这导致了人们在错误的情形下来使用一种方法,例如,在不可预设性的环境中使用一种预设性的方法。
使用预设性方法具有强烈的诱惑力,因为预设性毕竟是一个非常需要的特性。可是,当你不能达到预设性时而你相信你能够,这将会导致这样一种局面:你可以很早就制订出计划,但不能适当地处理计划崩溃的情形。你看见现实与计划慢慢的偏离,而你可以在很长的时间里,装着认为计划仍是有效可行的。但是当偏离积累到足够的时候,你的计划就崩溃了,这通常是很痛苦的。
所以说,在不可预设性的环境中是不能使用预设性方法的。认识到这点是一个很大的冲击。它意味着我们用的许多控制项目的模式,许多处理客户关系的模式,都不会再是正确的了。预设性的确有非常多的好处,我们很难就放弃预设性而失去这些益处。象很多问题一样,最困难的一点是认识到这些问题的存在。
可是,放弃预见性并不意味着回到不可控制的一片混乱之中。你所需要的是另一类过程,它们可以让你对不可预设性进行控制,这就是“适配性” 的作用了。
不可预设过程的控制
那么,我们如何对付一个不可预测的世界呢?最重要,也是最困难的是要随时知道我们在开发中的情形处境,这需要一个诚实的反馈机制来不断准确地告诉我们。
这种机制的关键之点是“迭代式”(iterative)开发方法。这并不是一个新思路,迭代式开发方法已存在很久了,只是名称不同,如“递增式”(Incremental),“渐进式”(Evolutionary),“阶段式”(Staged),“螺旋式”(Spiral)等等。迭代式开发的要点是经常不断地出最终系统的工作版本,这些版本逐部地实现系统所需的功能。它们虽然功能不全,但已实现的功能必须忠实于最终系统的要求,它们必须是经过全面整合和测试的产品。
这样做的理由是:没有什么比一个整合了的、测试过的系统更能作为一个项目扎扎实实的成果。文档可以隐藏所有的缺陷,未经测试的程序可能隐藏许多缺陷。但当用户实实在在地坐在系统前来使用它时,所有的问题都会暴露出来。这些问题可能是源码缺陷错误(bug),也有可能是对需求理解有误。
虽然迭代式开发也可用于可预性环境,但它基本上还是用作“适配性” (adaptive)过程,因为适配性过程能及时地对付需求变更。需求变更使得长期计划是不稳定的,一个稳定的计划只能是短期的,这通常是一个“迭代周期”(iteration)。迭代式开发能让每个迭代周期为下面的开发计划提供一个坚实的基础。
迭代式开发的一个重要问题是一个迭代阶段需要多长。不同的人有不同的答案, XP(极端编程)建议一到两周,SCRUM建议一个月,Crystal(水晶系列)更长一些。不过,一般的趋势是让每一个周期尽可能地短。这样你就能得到频繁的反馈,能不断地知道你所处的状况。
适配性的客户
这类适配性过程需要与客户建立一种新型的关系,特别是当开发是由一家签约公司来进行的时候。因为当雇佣一家签约公司来进行开发时,多数客户愿意订一个固定价格的合同。他们告诉开发方他们所需要的功能,招标,签约,然后剩下的便是开发方去建造系统了。
固定价格合同需要稳定的需求,即一个可预设性过程。适配性过程和不稳定的需求意味着你不能做这种固定价格的合同。把一个固定价格模式弄到适配性过程将导致一个痛苦的结局。最糟糕的是客户将与软件开发者受到同样的伤害,毕竟客户不会想要一个不需要软件。即使他们未付开发方一分钱,他们仍然失去许多。
因此,在可预设性过程不能用的情况下,签订固定价格合同对双方来说都有危险。这意味着客户须换一种工作方式。
在适配性过程中,客户实际上能够对软件开发过程进行很深入细微的控制。在每一个迭代阶段中,他们都能检查开发进度,也能变更软件开发方向。这导致了与软件开发者更密切的关系,或曰真正的伙伴关系。但并不是每一个客户,也并不是每一个开发商都准备接受这种程度的介入,不过如要让适配性过程能很好工作,这种合作程度是基本的要求。
适配性过程对客户最关键的益处是软件开发中的“回应性”很好。一个可用的,尽管是很小的系统能够尽早投入使用。根据实际使用情况,以及变更了的需求,客户可及时改变一些系统功能。
让人优先
实施一个适配性过程并不容易,特别是它要求一组高效的开发人员。高效既体现在高素质的个体,也体现在有能让团队协调一致的工作方式。这里有一个有趣的和谐:并非只是适配性过程需要很强的团队,多数优秀的开发人员也愿意采用适配性过程。
可兼容性程序插件
传统正规方法的目标之一是发展出这样一种过程,使得一个项目的参与人员成为可替代的部件。这样的一种过程将人看成是一种资源,他们具有不同的角色,如分析员,程序员,测试员及管理人员。个体是不重要的,只有角色才是重要的。这样一来,在你计划一个项目时,你并不在乎你能得到哪个分析员,哪些测试员,你只需关心你可得到多少,知道资源数量会如何影响你的计划。但这有一个关键问题:参与软件开发的人员是可替代的部件吗?轻灵型方法的一个重要特征就是拒绝这种观点。
也许最明确地反对这种观点的当数Alistair Cockburn. 在他的论文 “人是非线性,一阶的部件”中,他指出可预设性软件开发过程要求 “部件”的行为也是可预性的。
但是,人并非可预性的部件。更进一步,他对软件项目的研究导致了如下结论:人是软件开发中最重要的因素。
在本文的标题里,我将人称为“部件”。其实(传统)过程/方法就是这样看待人的。这种观点的错误在于“人”是非常可变的和非线性的,不同的个体具备特有的成功或失败模式。那些因素是一阶的,不可忽略的。一种过程或方法的设计者如不能充分考虑到这些因素,那麽其后果就是项目的无计划轨迹。就象我们经常看到的那样。
-- Alistair Cockburn
Cockburn是最鲜明地主张在软件开发中应以人为中心,其实这种概念在许多软件行业的有识人士中已是共识。问题在于所使用的方法是与这种理念背道而驰的,这造成了一个很强的正反馈机制。如果你期望你的开发人员是可互替的编程插件,则你不会去试着把他们看成是不同的个体。这会降低士气(和生产率),并使优秀的人才跳到一个能发挥其个性特长的地方,最后你倒是得到你所需要的:可互替的编程插件。
决定使人优先是件大事,它需要很大的决心来推行。把人作为资源的思想在工商界是根深蒂固的,其根源可追溯到 泰勒的“科学管理”方法。当管理一个工厂时,这种泰勒主义途径是有效的。但是对有着高度创造性和专业性的工作,我相信软件开发当属此类,泰勒主义并不适用(事实上现代制造业也在脱离泰勒主义模式)。
程序员是负责任的专业人员
泰勒主义的一个关键的理念是认为干活的人并非是那些知道怎样才能把这件活干的好的人。在工厂中可能是这样,原因是许多工厂里的普通工人并非是最具聪明才智和最富创造力的人员。另一个原因也许是由于管理层和工人的的工资悬殊太大而导致的关系紧张。
历史证明这种情形在软件开发中是不存在的。不断有优秀人才被吸引到软件行业中,吸引他们的既有耀眼的光芒也有丰厚的回报(正是这两样诱使我离开电子工程)。其他一些福利如对公司的股份持有使得程序员的利益与公司紧联在一起。
〔可能还有一个“产生”(generational)效应。一些所见所闻让我想到是否在过去十来年中有很多的优秀人才转入软件行业。如果是这样,这可能是当今年轻人崇尚IT业的原因,就象其他时尚一样,其后总有一些实在的理由。)
如果你想聘到并留住优秀人才,你得认识到他们是有能力的专业人员。因此,他们最有资格决定如何干好他们的技术工作。泰勒主义里让计划部门来决定如何干好一件工作的作法只有当计划者比实际操作者更能知道怎样作时才有效。如果你拥有优秀的、自觉自励的员工,那么这点并不成立。
面向人的过程的管理
敏捷型过程中“以人为本”的理念可以有不同的表现,这会导致不同的效果,而并非所有结果都是完全一致的。
实施敏捷型过程的一个关键之处是让大家接受一个过程而非强加一个过程。通常软件开发的的过程是由管理人员决定的,因此这样的过程经常受到抵制,特别是如果管理人员已脱离实际的开发活动很长时间了。而接受一个过程需要一种“自愿致力”,这样大家就能以积极的态度参与进来。
这样导致了一个有趣的结果,即只有开发人员他们自己才能选择并遵循一个适配性过程。这一点在XP中特别明显,因为这需要很强的自律性来运行这个过程。作为一个互补,Crystal(水晶系列)过程则只要求最少的自律。
另一点是开发人员必须有权作技术方面的所有决定。XP非常强调这一点。在前期计划中,它就说明只有开发人员才能估算干一件工作所需的时间。
对许多管理人员来说,这样形式的技术领导是一个极大的转变。这种途径要求分担责任,即开发人员和管理人员在一个软件项目的领导方面有同等的地位。注意我说的同等。管理人员仍然扮演着他们的角色,但需认识并尊重开发人员的专业知识。
之所以强调开发人员的作用,一个重要的原因是IT行业的技术变化速度非常之快。今天的新技术可能几年后就过时了。这种情况完全不同于其他行业。即使管理层里的以前干技术的人都要认识到进入管理层意味着他们的技术技能会很快消失。因此必须信任和依靠当前的开发人员。
应用域专家的引领作用(The Role of Business Leadership)
技术人员并不能包打天下,他们需要应用系统的需求分析,即他们需要与应用领域专家非常紧密的联系,这是适配性过程一个重要的方面。这种联系的紧密度远远超过了一般项目中应用领域分析人员的介入程度。如果开发人员和应用领域专家只有偶尔的沟通,那么敏捷型过程是不可能存在的。此外,这种沟通不是由管理层来处理的,而是每个开发人员需要做的事。因为开发人员在他们的行业里是有能力的专业人员,因此他们能够与其他行业的专业人员同等地在一起工作。
这是由适配性过程的特点来决定的。因为在整个开发过程中,事情变化很快,你需要经常不断的联系沟通以使每个人都能及时知道这些变化。
对开发人员来说,没有什么比看见自己的辛勤工作白白浪费更让人痛苦的了。因此,开发人员能随时获取准确的高质量的应用系统的(需求)知识就显得很重要了。
自适配过程
到目前为止,我谈到的适配性是指在一个开发项目中如何频繁地修改软件以适应不断的需求变更。但是,还有另一种适配性,即是过程本身随着时间推移变化。一个项目在开始时用一个适配性过程,不会到一年之后还在用这个过程。随着时间的推移,开发组会发现他们的工作有些什么变化,然后改变过程以适应之。
自适配的第一步是经常对过程进行总结检讨。一般来说,在每一次迭代结束后,你可以问自己如下问题〔Norm Kerth):
有哪些做的好的部分
有哪些教训
有哪些可以改进的部分
有哪些没搞清楚的部分
这些问题会帮助你考虑在下一次迭代中如何对过程进行修正。在样,如果开始时使用的过程有问题的话,随着项目的进行,该过程会得以逐步的完善,以使其能更好地适合开发组。
如果一个项目采用了自适配方法,则可以进一步在一个组织内引入这种方法。如果要深化自适配过程,我建议开发人员专门用一段时间做一次更为正式的回顾总结,象Norm Kerth所建议的那样,这些活动包括离开工作地点,到另外一个地方开2-3天的总结会。这不仅是给开发组提供一次学习机会,同时也给整个组织一次学习机会。
自适配性导致的结果是你绝不能期待着只用一个过程。相反,每个项目组不仅能选择他们自己的过程,并且还能随着项目的进行而调整所用的过程。公开发表的过程和其他项目的经验都可以拿来作为参考和样本。但是开发人员需根据手中项目的具体情况而对其加以调整,这也是开发人员的专业职责。
这种自适配性在ASD和Crystal(水晶系列)中都鲜明地提及。XP的严格规则似乎不允许这样,但这只是表面现象,因为XP是鼓励调整过程的。这一点上XP和其他方法的主要区别之处在于,XP的倡导者建议在采用XP时,先根据书本循规蹈矩不走样地做几个迭代之后,再考虑调整。另外,回顾总结这点在XP中没有被强调,也不是这个过程的组成部分,尽管XP建议经常性的回顾应作为XP的实践准则之一。
敏捷型方法
好几个方法都可以归入敏捷型旗下,它们有许多的共同特征,但也有一些重要的不同之处。在此简短的综述中,我不可能列出这些过程所有的特点,但至少我可以告诉你可以到什么地方去查找更详细的材料。对大多数这些方法我都没有深入的实际经验。我有很多工作是基于XP的,也对RUP有些经验。但是对其他方法来说,我的知识主要是来自书本(当然这是很不够的)。
XP(Extreme Programming -- 极端编程)
在所有的敏捷型方法中,XP是最为引人瞩目的。部分原因是因为XP的领军人物们的卓越能力,特别是Kent Beck,他能够把人们吸引到这种方法来,并一直处于领先地位。但是XP热也带来了一个问题,就是它把其他一些方法和它们非常有价值的思想给挤了出去。
XP根源于Smalltalk圈子,特别是Kent Beck和Ward Cunningham在80年代末的密切合作。90年代初,他们在一系列项目上的实践深化扩展了他们关于软件开发应是适配性的、应以人为中心思想。
从非正式的、探索性的实践到形成系统化的正规方法的关键一步是在1996年春。Kent被邀对Chrysler的一个工资管理项目(C3)的开发进度进行审核。该项目由一个签约公司用Smalltalk开发,正处于困境之中。由于源码质量低劣,Kent建议推倒重来。该项目然后在他的领导下从头开始并成了早期 XP的旗舰和培训基地。
C3的第一期系统在1997年初投入运行。项目继续进行了一段时间后,遇到了麻烦,导致了在1999年开发计划被撤销。在我写此文时,该系统还在用来给万余员工发工资呢。
XP的四条基本价值原则是:沟通,反馈,简单和勇气。在此基础上建立了十多条XP项目应遵循的实践准则。其实,许多准则是以前就存在的并经过实践检验的,而常常被忽略了的。XP重新建立了这些准则,并把它们编织成了一个和谐的整体,使得每一项准则都能在其他准则里得以强化。
XP有一个最具冲击力的,也是最初吸引我的特点,是它对测试的极端重视。诚然,所有的过程都提到测试,但一般都不怎么强调。可是XP将测试作为开发的基础,要求每个程序员写一段源码时都得写相应的测试码。这些测试片段不断地积累并被整合到系统中。这样的过程会产生一个高度可靠的建造平台,为进一步开发提供了良好的基础。
在此基础上XP建立了一个渐进型的开发过程,它依赖于每次迭代时对源码的重组(refactoring)。所有的设计都是围绕着当前这次迭代,而不管将来的需求。这种设计过程的结果是“纪律性”与“适配性”的高度统一,使得XP在适配性方法中成为发展的最好的一种方法。
XP产生了一批领军人物,许多是从C3项目中出来的。关于XP有许多文献可读。最好的一篇总结文章是Jim Highsmith的Cutter论文(有趣的是Jim Highsmith并不是XP道中人,他的方法我将稍后介绍)。Kent Beck写的 Extreme Programming Explained,是一篇XP的宣言,它阐述了隐藏在 XP后面的道理。此书对有心于XP并致力于将其发扬光大者提供了充足的说明和解释。过去两年里也出版了一批“多姿多彩”的XP书籍,但多数都很相似,主要是从一些XP早期的实践者们的角度上描述了 XP的整个过程。
除了书之外,还有不少网上资源。如果你想找到更有结构性的材料,你最好访问两位C3成员的网站:Ron Jefferies的 xProgramming.com 和Don Wells的 extremeProgramming.org。 Bill Wake的 xPlorations 里也有一些很有用的文章。许多XP早期的倡导和发展可在Ward Cunningham的 wiki web (合作写作)中找到。wiki是个令人着迷的地方,尽管它的漫游性质常令人身不由己的陷入其中。 Robert Martin是一位知名的C++和OO设计的专家,他也加入了XP鼓吹者行列。他的公司 ObjectMentor 网站上有不少文章论及XP,其中一篇提出可把XP看成是一个最小RUP实现,他称之为 dX。另外,他们也资助 XP讨论组〔xp discussion egroup)。还有一篇很有意思的文章从“外面”来审视XP,这就是Mark Paulk所写的 从CMM的角度看XP。Mark Paulk是CMM的领军人物之一。
Cockburn的水晶系列方法
Alistair Cockburn 在90年代初受IBM之约进行正规方法的研究。从那时起他就活跃于这个领域。他的研究途径和其他方法学者有所不同。一般的方法学者是将他们个人的经验升华成理论。而Cockburn除了归纳整理他自己的实践经验以外,他还积极地造访其他项目,和项目组成员进行广泛的讨论,考察这些项目是怎样运作的。难能可贵的是,他从不固守自己的观点,他会根据新的发现而随时修正自己的理论。他的这些特点使得他成为我最喜欢的方法学者。
他的著作 “Surviving Object-Oriented Projects” 汇集了很多如何顺利运行软件开发项目的建议,此书也是我推荐的运行迭代式项目的首选书。最近,Alistair写了一本关于 敏捷型软件开发 的综述性著作,探讨了这些方法的基本原则。
Alistair还更进一步地探索了敏捷型方法,并提出了 水晶(Crystal)方法系列。之所以是个系列,是因为他相信不同类型的项目需要不同的方法。他认为决定一个方法与两个因素有关:项目参与人数和出错后果。如果用两个坐标轴来分别表示这两个变量的话,那么在这张图上,每一种方法都有其相应的位置。例如,有两个项目,一个是有40人参加,如果失败造成的资金损失可以接受;另一个项目只有6人,其成败生存悠关。那么这两个项目所用的方法在坐标图上就有不同的位置。
水晶系列与XP一样,都有以人为中心的理念,但在实践上有所不同。Alistair 考虑到人们一般很难严格遵循一个纪律约束很强的过程,因此,与XP的高度纪律性不同,Alistair探索了用最少纪律约束而仍能成功的方法,从而在产出效率与易于运作上达到一种平衡。也就是说,虽然水晶系列不如XP那样的产出效率,但会有更多的人能够接受并遵循它。
Alistair也费了不少笔墨强调每次迭代后的总结回顾,因而鼓励过程本身的自我完善。他的理由是迭代式开发是用来尽早发现问题并解决之。这样就更加强调了开发人员要随时观察他们所用的过程,并随着项目的进行而调整。
2001年2月,Alistair宣布他和Jim Highsmith将合并他们的方法。这个方法有何影响,如何命名,都还是有待回答的问题。
开放式源码
看到这个标题你可能会有些意外。毕竟,开放式源码(Open Source)是软件的一类风格,而非一种过程。这里我是指开放源码界所用的一种运作方式,这种方式适用于开放源码项目,其实它的许多做法也可为封闭式源码项目所用。开放式源码项目有一个特别之处,就是程序开发人员在地域上分布很广。注意到这点相当重要,因为一般适配性过程都强调项目组成员在同一地点工作。
多数开放源码项目有一个或多个源码维护者(maintainer)。只有维护者才能将新的或修改过的源码段并入源码库。其他众人可以修改源码,但需将他们所做的改动送交给维护者,由维护者对这些改动进行审核并决定是否并入源码库。通常来说,这些改动是以“补丁”(patch)文件的形式,这样处理起来容易一些。维护者负责协调这些改动并保持设计的一致性。
维护者的角色在不同的项目中有不同的产生和处理方式。有些项目只有一个维护者,有些项目把整个系统分成若干个模块,每个模块有一个维护者。有些是轮流做维护者,有些是同一个源码部分有多个维护者,有些则是这些方式的组合。许多开放源码项目的参与者只是部分时间(或业余时间)干,如果项目要求是全日制的,那么这有一个问题,就是怎样才能把这些开发人员有效地协调组织起来。
开放源码的一个突出特点就是查错排故(debug)的高度并行性,因为许多人都能同时参与查错排故。如果他们发现了错误,他们可将改正源码的 “补丁”文件发给维护者。这种查错排故角色对非维护者来说合适,对那些设计能力不是很强的人来说,也是一项挺好的工作。
关于开放源码的方法过程还没有很系统的文献。目前最著名的一篇文章是 Eric Raymond写的 The Cathedral and the Bazaar(教堂与集市),文章虽短,但很精彩。另外,Karl Fogel所著的 关于CVS的书中也有几章描述了开放源码的方法。即使你不想使用CVS,这几章还是值得一看。
Highsmith的适配性软件开发方法(ASD--Adaptive Software Development)
Jim Highsmith 多年来一直从事可预性方法的研究,建立和教学,而最后得出的结论是这些方法都有着根本性的缺陷,特别是在用来作现代应用系统的开发时。
他最近的 一本书 集中论述了新方法的适配特性,重点讨论了把一些起源于复杂适配性系统(通常称之为混沌理论--chaos theory)的思想在软件开发中加以应用。此书没有象XP那样提供详尽的实践准则,但它从根本上说明了为什么适配性开发方法是重要的,并进一步说明了其对组织结构和管理层的影响。
ASD的核心是三个非线性的、重迭的开发阶段:猜测,合作与学习。
在一个适配性环境中,因为结果是不可预的,Highsmith把计划看成是一个 “反论”〔paradox)。在传统的计划中,偏离计划是错误,应予纠正。而在一个适配性环境里,偏离计划则是在引导我们向正确的目标迈进。
在不可预的环境里,你需要大家能以多种多样的方式合作来对付不确定性。在管理上,其重点不在于告诉大家做什么,而是鼓励大家交流沟通,从而使他们能自己提出创造性的解决方案。
在可预性环境里,通常是不大鼓励学习的。设计师已经都设计好了,你跟着走就行了。
在适配性环境中,学习对所有各方,包括开发人员和客户, 都是一个挑战。他们需要学习以检验他们作的假设,需要学 习以便能用每次开发周期的结果去适配下一个周期。
-- Highsmith
这样的学习是连续不断的,这已成为这种方法的一个重要特点,因此我们必须得认识到计划和设计都得随开发的推进而改变。
适配性开发周期的最大而不可见的好处是其对我们自以为是的心理 模式的挑战,它迫使我们更实际地估计自己的能力。
-- Highsmith
有了这样的出发点,Highsmith把他的工作集中放在适配性开发的难点上,特别是如何在一个项目中增强合作和学习。基本上说,他的这本书是侧重于“软”方法,这样对那些从开发实践中提炼出来的方法如XP,FDD 和水晶系列来说,这本书将是一个很有益的互补。因此Highsmith在2001年 2月宣布他将把他的方法于Cockburn的水晶系列合并,就是顺理成章并且很有意义的了。
SCRUM
SCRUM在OO界里已很有些时日了,不过我得承认我对其历史发展并不是太知其详。象前面所论及的方法一样,该方法强调这样一个事实,即明确定义了的可重复的(defined and repeatable)方法过程只限于在明确定义了的可重复的环境中,为明确定义了的可重复的人员所用,去解决明确定义了的可重复的问题。
SCRUM把一个项目分成若干个为期30天的迭代阶段,称之为一“冲” (sprint)。开“冲”之前,你得明确这一“冲”要实现的功能,然后交给开发组去完成。但是,在“冲”期间,需求必须是固定的。
管理人员并非在“冲”的时候就撒手不管了。每天,他需召集一个短会(15分钟左右),称之为一个scrum,会上大家讨论决定第二天干什么。特别是大家会对管理层提出那些阻碍项目进行的因素,并希望管理层能予以解决。当然,他们也需要报告目前完成了什么,这样管理层每天都能了然项目的进展情况。
SCRUM文献多集中论述迭代阶段计划与进度跟踪。它与其他敏捷型方法在许多方面都很相似,特别是它可以与XP的编程准则很好地结合起来。
相当长的一段时间没有关于SCRUM的专门书籍,直到最近 Ken Schwaber和Mike Beedle写了 第一本SCRUM的专著。Ken Schwaber还主持了一个网站 ControlChaos.com,可能是对SCRUM的最好的综述。Jeff Suthurland有个总是很活跃的网站讨论OO技术,其中有 一部分是专门讨论SCRUM的。另外,在 PLoPD 4书中也有一篇关于SCRUM的很好的综述。
Coad的功用驱动开发方法(FDD--Feature Driven Development)
FDD是由Jeff De Luca和OO大师Peter Coad提出来的。象其他方法一样,它致力于短时的迭代阶段和可见可用的功能。在FDD中,一个迭代周期一般是两周。
FDD有以下五项任务:
建立总体模型
提出功用清单
针对功用逐项制订计划
针对功用逐项进行设计
针对功用逐项开发实现
头三项在项目开始时完成,后两项在每一次迭代周期时都要做。每一项任务又可进一步分解并制订出相应的检验准则。
在FDD中,编程开发人员分成两类:首席程序员和“类”程序员(class owner)。首席程序员是最富有经验的开发人员,他们负责开发实现系统的各项功能。对每一项功能,首席程序员要定出需要哪些类(class)来实现这项功能,并召集“类”程序员们组成一个针对这项功能的开发组。首席程序员作为协调者,设计者和指导者,而“类”程序员则主要作源码编写。
FDD的主要论述见于Peter Coad等所著的 UML in Color 。他的公司 TogetherSoft 也从事FDD的咨询和培训工作。
动态系统开发方法〔DSDM--Dynamic System Development Methods)
DSDM在1994年始于英国。 英国一些想用RAD和迭代方式进行系统开发的公司组成了一个社团〔Consortium)。刚开始有17个组建成员,到现在成员已超过1000个,遍布英国内外。DSDM由于是由一个社团所发展,它与其他一些敏捷型方法有些不同。它有专门的组织支持,有手册,培训课程,认证程序等。因为它上面的价格标签而限制了我对此方法的进一步调查。不过Jenifer Stapleton已写了 一本书来介绍这种方法。
如果你要用这种方法,你得先作可行性和应用域分析。可行性分析要考虑 DSDM是否适合手上这个项目。而应用域分析则是开一系列的讨论会,以期能充分了解应用域,同时也要提出大致的系统结构与项目计划。
余下的工作由三个互相交织的周期组成:功能模型周期产生文档和原型(实验系统),设计建造周期生成可操作使用的系统,实现周期处理系统安装部署(deployment)问题。
DSDM有一些基本的原则包括与用户积极的沟通,频繁的出活(delivery)。有充分职权的项目组,完全的系统测试。象其他敏捷型方法一样, DSDM的一个周期在2-6周之间。它强调高质量的系统以及需求变更的高度适配性。
我还没有在英国之外的地方看到有项目使用DSDM。DSDM的基本结构有许多成熟的传统方法的东西,同时又遵循了敏捷型途径。但这里的确有一点值得注意,即是这种方法是否有鼓励一种面向过程与繁琐的倾向。
敏捷软件开发宣言
可以看出,前面所提到的这些方法有很多的相似之处,那么自然大家就会有兴趣进行某种形式的合作。 2001年2月,这些方法的代表人物们被邀至犹它州Snowbird 举行了一个为期两天的讨论会。我也在其列,但开始并未抱太大希望。毕竟,当你把一堆方法学者塞进一间房子时,他们能以礼相待就是上上大吉了。
结果却出乎我的意料之外。每个与会者都认识到这些方法有许多的共同点,这种共识远远大于他们之间的分歧。这次讨论会使这些一流的方法学者们增进了联系,大家还有意发表一份联合声明--呼吁推动发展敏捷型开发过程(我们也同意用“敏捷”(agile)这个词来表达我们共有的理念)。
成果便是一份 敏捷软件开发宣言〔Manifesto for Agile Software Development),它表述了敏捷型过程所共同具备的价值和原则。与会者也有意在将来进一步合作,并鼓励方法学者与商界人士使用敏捷型方法进行软件开发。 Software Development Magazine〔软件开发杂志)有一篇关于 宣言的评注与解释的文章,它的片断可见于 敏捷宣言的将来。
RUP是一种敏捷型方法吗?
当我们开始讨论OO领域的方法时,不可避免地会碰到 RUP(Rational Unified Process)。该过程由Philippe Kruchten, Ivar Jacobson以及Rational Rose 的其他一些人士开发,主要是作为一个与UML相配合和补充的过程。RUP其实是个过程的框架,它可以包容许多不同类型的过程,这一点正是我对RUP的主要批评。因为它可以是任何东西,那么就跟什么都不是一样了。我愿意选择的过程是它能明确告诉你干什么,而不是给你无穷无尽的选择。
由于RUP是一种框架,你可以以不同的方式来使用它,如象非常传统的“瀑布” 式开发方式,或敏捷式。你可以把用得轻捷灵便,也可把它弄成繁文缛节。这取决于你如何在你的环境中对它裁剪运用。
Craig Larman极力主张以敏捷型方式来使用RUP。在他的关于OO开发的 引论著作 中,他提出了一个过程,就是基于这种“轻型”RUP的思想。他的观点是:目前如此众多的努力以推进敏捷型方法,只不过是在接受能被视为RUP 的主流OO开发方法而已。在做一个项目时,Craig要干的事情之一便是在为期一月的迭代周期的头两三天和整个开发组呆在一起,用UML勾勒出这个迭代阶段的设计。这个设计并非是一个不可更改的,它只是一个使大家能知道这个阶段如何干的草图。
另一种对待RUP的策略是Robert Martin的 dX过程。dX过程是一个完全符合RUP 的过程,而又碰巧与XP完全等同(把dX转180度可见,一句戏言)。dX是特别适合于那些不得不用RUP而又想用XP的伙计们。由于dX既是XP又同时是 RUP,它可作为以敏捷方式运用RUP的一个极好的例子。
对我而言,在运用RUP时的一个关键之处在于业界RUP的领头者们需强调他们的软件开发途径。曾经不止一次,我听到使用RUP的人是在使用“瀑布”式开发过程。根据我在业界的联系,我知道Philippe Kruchten和他的小组是坚定的迭代式开发信奉者。澄清这些原则并鼓励敏捷式使用RUP,如象Craig Robert的工作,将对软件开发有着重要的影响和作用。
其他参考材料
关于敏捷型方法有不少文章和讨论组,它们可能不会提供完整的方法,但可以给你一个窗口以观察这个正兴起的领域在如何发展。
程序设计的模式语言(Patterns Language of Programming) 大会经常会有一些材料讨论这个题目,这也许是因为许多对模式(Pattern)感兴趣者也对适配型和“人道”方法过程感兴趣的缘故吧。这方面有一篇早期的一流论文, Jim Coplein所著,收集在 PLoP1 中。Ward Cunningham的Episodes模式语言收集 PLoP2 中。Jim Coplein现主持一个网站, OrgPatterns,以wiki方式收集了不少组织结构模式。 Dirk Riehle在XP2000大会上提交了一篇论文,该文比较了XP和适配性软件开发(Adaptive Software Development, ASD)的 价值系统。Coad Letter的 七月期比较了XP和FDD。IEEE Software的七月期有几篇文章论述 “过程多样性”(process diversity),也提及这些方法。
Mary Poppendieck写了一篇很精彩的文章 比较敏捷型方法与精悍(lean)型制造业。
你是否应走向敏捷?
并非人人都能使用敏捷型方法。当你决定走这条路时,你得记住许多准则。但是,我确切相信,这些新方法可被广泛的应用。只是考虑使用它们远远不够,应该有更多的人来实践中运用它们。
在目前的软件开发中,多数方法仍是边写边改(code and fix),那么,引入一些纪律约束肯定会比一片混乱要好。敏捷型途径的主要优点在于它比重型方法的步骤要少得多。如果你已习惯于无过程,那么遵循简单过程应该比遵循繁琐过程更容易一些。
这些新方法的主要局限是如何对付较大的项目组。水晶类方法可在最多到50人的项目组内使用。如果超过了这个规模,则还没有证据或经验来说明如何运用这些适配性方法,甚至这些方法是否工作都很难说。
这篇文章至少传递了这样一个信息,就是适配性方法对需求不确定或常常变更的情形是有效的。如果你没有稳定的需求,那么你就不可能进行稳定的设计并遵循一个计划好了的过程。这种情况下,适配性过程可能感觉上不太舒服,但实践上会更有效一些。通常来说,使用适配性方法最大的障碍来自客户。我认为,重要的一点是让客户理解在一个需求不断变更的环境中,遵循可预性过程对他们是有风险的,同样对开发方也是有风险的。
你可能已注意到我说过50人以上的项目组应使用传统的可预性过程,需求不断变更的话,则应使用适配性过程。那么,如果你的项目很大而需求又在不断地变更,又当如何呢?对这个问题我并无一个满意的答案,我建议你去寻求其他意见。但我可以告诉你,这种情形下事情将会非常困难,不过我想你肯定已知道这一点了。
如果你要采用适配性方法,你需要信任你的开发人员,并让他们参与(技术)决策。适配性过程的成功依赖于你对你的开发人员的信任。如果你认为你的开发人员素质不够,那么你应采用可预性途径。
总结一下,如下的因素建议你采用适配性过程:
不确定或常变更的需求
负责任的,自觉自励的开发人员
理解并愿意参与其中的客户
而如下这些因素则建议你使用可预性过程:
50人以上的项目组
固定价格,或更确切的说,固定任务范围的合同
该用哪个适配性过程?
本文论及的这些适配性过程都还很新,我只能提供一些第一手经验以供参考。我对过程的选择通常视项目组人数,以及他们愿意遵循多少纪律规章而定。
如果开发人员有十二个或以下,那么我肯定推荐XP。开发组有可能不会严格地把所有XP的过程都走一遍(特别是刚开始时),但这种部分XP过程仍能让你获益不少。我认为,用好XP的一个关键的部分是要将单元测试(unit test)自动化。如果开发组愿意这样做,系统就有了一个坚实的技术基础。如果他们不想这样干,我不怀疑他们自己就得来做这些测试。
如果没有纪律规章,或项目组太大,那么我倾向于水晶系列。水晶系列肯定是敏捷型方法中最轻的,Cockburn特别主张吸取开发中的经验教训(而对过程进行调整)。不过,在这种情况下,我仍会用XP来作过程计划。
我虽然这样说了,可是我现在的项目组有40人,我们成功地试验了许多XP准则,实际上也很接近完全的XP了。所以说,如果有一个有决心有热忱的团队,你在选择过程的时候,完全可以突破一些我提到的边界条件。
还有一点非常关键,那就是不管你开始时用的是什么过程,该过程都不会是完全如你想象的那样得心应手,你得不停地对它进行监查与修改以适配你的环境。最后一点,它必须得是你自己的过程,其他标签都是次要的。
鸣谢
本文得益于许多朋友的意见,恕难一一列出。但是,我要特别感谢Marc Balcer, Kent Beck,Alistair Cockburn,Ward Cunningham,Bill Kimmel 和Frank Westphal。
请记住这是一篇不断改进的网络文章。我将附上主要修改记录,而小改动将不作记录。
修改记录
2001年11月:更新一些最近的参考材料。
2001年3月: 加上关于“敏捷联盟”的内容。
2000年12月:本文缩写发表于Software Development杂志。
2000年11月:更新ASD部分并加上DSDM和RUP的章节。
2000年7月: 初稿发于martinfowler.com。
--------------------------------------------------------------------------------
译后注:
我去年(2000年)曾参加过一个ECommerce系统的软件开发工作。这个项目采用了一种类似XP(极端编程)的开发方式,一个迭代周期约为三周,实现一项use case〔use case driven)。开发中特别强调单元测试(unit testing,使用JUnit)与每天的“冒烟测试”(smoke test)。今年〔2001年)初读到Martin Fowler的网站(www.martinfowler.com)上的这篇 “The New Methodology”时,我正参加一个投资银行的证券分析信息系统的开发工作,该项目也采用了迭代式开发过程。但由于环境不同,这个项目的迭代周期较长一些,约六到八周。这个项目的另一个特点是开发人员和系统分析员〔business analysts)以及测试人员〔testers)的沟通特别频繁。读了这篇文章后,我觉得它能够让人从一个比较广阔而系统的角度来考察一个迭代式项目的运作。
诚如作者所言,这是一篇不断改进的网络文章。我将尽力随原文的更新而及时更新译文。此译文中如有所译不当之处,望诸位同行不吝赐教。
原文: http://www.martinfowler.com/articles/newMethodology.html
译文: http://members.tripod.com/jian_hu/fowler/newMethodology.html
2001年12月:译自原文2001年11月版。
胡健
Email: jian4_hu2@hotmail.com
Web: http://members.tripod.com/jian_hu
英文原文版权由Martin Fowler拥有
Original text is copyrighted by Martin Fowler
Martin Fowler
Chief Scientist, ThoughtWorks
过去几年中兴起的敏捷型(agile)软件开发方法,以矫正官僚繁琐过程,或者许可对过程进行自主调整为特征,在软件业引起了极大的兴趣。在这篇文章里,我将探索敏捷型方法的合理性,着重点并不是放在其“轻重”上,而是于它们的适配性(adaptive)性质和以人优先的理念。我在本文也简要介绍了一些敏捷型方法并给出了进一步的参考材料。另外,我还给出了一些你在决定是否要走这条刚踏出来的敏捷之路时需考虑的因素。
最近一次主要修改: 2001年11月
在SD East 上我作了一次演讲 “让软件恒软〔Keeping Software Soft)” 其材料就是基于这篇文章(你若有充足的时间可浪费的化,不妨一观)。此文的节略版发表于 Software Development Magazine(软件开发杂志) 的2000年12月期。
从无,到繁重, 再到敏捷
预设性与适配性
将设计与建造分离开来
需求的不可预设性
预设性是不可能的吗?
不可预设过程的控制
适配性的客户
让人优先
可兼容性程序插件
程序员是负责任的专业人员
面向人的过程的管理
应用域专家的引领作用
自适配过程
敏捷型方法
XP(Extreme Programming -- 极端编程)
Cockburn的水晶系列方法
开放式源码
Highsmith的适配性软件开发方法〔ASD)
SCRUM
Coad的功用驱动开发方法〔FDD)
动态系统开发方法〔DSDM)
敏捷软件开发宣言
RUP是一种敏捷型方法吗?
其他参考材料
你是否应走向敏捷?
该用哪个适配性过程?
鸣谢
修改记录
从无,到繁重, 再到敏捷
多数软件开发仍然是一个显得混乱的活动,即典型的“边写边改” (code and fix)。设计过程充斥着短期的,即时的决定,而无完整的规划。这种模式对小系统开发其实很管用,但是当系统变得越大越复杂时,要想加入新的功能就越来越困难。同时错误故障越来越多,越来越难于排除。一个典型的标志就是当系统功能完成后有一个很长的测试阶段,有时甚至有遥遥无期之感,从而对项目的完成产生严重的影响。
我们使用这种开发模式已有很长时间了,不过我们实际上也有另外一种选择,那就是“正规方法”(methodology)。这些方法对开发过程有着严格而详尽的规定,以期使软件开发更有可预设性并提高效率,这种思路是借鉴了其他工程领域的实践。
这些正规方法已存在了很长时间了,但是并没有取得令人瞩目的成功,甚至就没怎么引起人们的注意。对这些方法最常听见的批评就是它们的官僚繁琐,要是按照它的要求来,那有做太多的事情需要做,而延缓整个开发进程。所以它们通常被认为是“繁琐滞重型”方法,或 Jim Highsmith 所称的“巨型”(monumental)方法。
作为对这些方法的反叛,在过去几年中出现了一类新方法。尽管它们还没有正式的名称,但是一般被称为“敏捷型”方法。对许多人来说,这类方法的吸引之处在于对繁文缛节的官僚过程的反叛。它们在无过程和过于繁琐的过程中达到了一种平衡,使得能以不多的步骤过程获取较满意的结果。
敏捷型与滞重型方法有一些显著的区别。其中一个显而易见的不同反映在文档上。敏捷型不是很面向文档,对于一项任务,它们通常只要求尽可能少的文档。从许多方面来看,它们更象是“面向源码”(code-oriented)。事实上,它们认为最根本的文档应该是源码。
但是,我并不以为文档方面的特点是敏捷型方法的根本之点。文档减少仅仅是个表象,它其实反映的是更深层的特点:
敏捷型方法是“适配性”而非“预设性”。 重型方法试图对一个软件开发项目在很长的时间跨度内作出详细的计划,然后依计划进行开发。这类方法在计划制定完成后拒绝变化。而敏捷型方法则欢迎变化。其实,它们的目的就是成为适应变化的过程,甚至能允许改变自身来适应变化。
敏捷型方法是“面向人”的(people-oriented) 而非“面向过程”的 (process-oriented)。 它们试图使软件开发工作顺应人的天性而非逆之。它们强调软件开发应当是一项愉快的活动。
在以下各节中,我将详细地探讨这些差别,这样你可以了解适配性和以人为中心的过程是什么,它们的好处与不足,以及你作为软件开发人员或用户时是否应该使用它们。
预设性与适配性
将设计与建造分离开来
传统的软件开发正规方法的基本思路一般是从其他工程领域借鉴而来如土木工程模式对软件工程的影响较大。这类工程实践中,在实际建造之前,通常非常强调设计规划。工程师首先给出一系列的图纸,这些图纸准确地说明了要建造什么以及如何建造(包括部分和整体)。许多工程问题,如怎样处理一座桥梁的负荷,图纸上都有说明。然后,这些图纸分发给另外一组人员,通常是另外一个公司,去建造。这种方式其实已假定了建造过程将按图纸而来。当然,施工中也会碰到一些问题,但这些都是次要的。
图纸其实就是一个详细的建造计划,它说明了一个项目中必须完成的各项任务,以及这些任务之间的依赖关系。这样,管理层能较为合理地制订出生产进度表和项目预算。这种模式实际上也规定了建造者如何做(施工),这也隐含着建造者不须是高智能型的,尽管他们可能都有非常高超的手上功夫。
在此,我们看到的是两类非常不同的活动。设计是难于预设的,并且需要昂贵的有创造你的人员,建造则要易于预设。我们有了设计之后,便可对建造进行计划了。而有了建造计划后,我们进行建造则可以是非常可预设性的了。在土木工程中,建造不论在经费上还是在时间上的花销都要比设计和计划大得多。
所以,多数正规方法的途径是象这样的:我们想要可预定的生产进度计划,以便能使用技能较低的人员。要达到这一点,我们必须得把设计与建造分离开来。因此,在软件开发中,我们得想法作出这样的设计,使得计划一经完成,建造将会是直接而明确的。
那么,计划应该采用什么形式呢?对许多人来说,这是设计“标识符号” (notation),如象UML,需承担的角色了。如果我们能用UML作出所有主要的技术决定,那么就可以用UML来做建造计划,然后把计划交给程序员去编码,即是建造活动。
但这里存在几个问题。你是否能作出这样的设计使得它能够让编码成为一项建造活动?如果能,那么建造是否能在资金和时间上的花销都充分地大于设计而使得这种途径值得一用?
第一个问题是到底有多困难能使一个用类似UML作出的设计达到交给程序员就能直接编码的状态。用象UML那样的语言作出的设计在纸上看起来非常漂亮,而实际编程时可能会发现严重的缺陷。土木工程师使用的模型是基于多年的工程实践,并结晶在工程典章中。更进一步来说,一些设计上的关键部分,如应力作用,都是建立于坚实的数学分析之上。而在软件设计中,我们对UML图纸所能做的只是请专家审阅。这当然是很有帮助的,但是往往一些设计错误只能在编码和测试时才能发现。甚至于熟练的设计者,我自认为我属此列,就常常对在把设计变成软件的过程中出现的错误感到意外。
另一个问题是费用比较。建一座桥梁时,设计费用一般占整个工程的10%,左右,余下的90%左右为施工建造费用。而在软件开发中,编码所占的时间一般要少得多(McConnell 指出在大型项目中,编码和单元测试只占15%,这几乎和桥梁工程中的比例倒过来了。即使把所有测试工作都算作是建造的一部分,设计仍要占到50%)。这就提出了一个重要问题,那就是和其他过程领域的设计相比,软件设计到底是什么性质。
更有甚者,Jack Reeves 认为源码也应是设计文档,而建造应该是编译和链接,因为任何属于建造的工作都应当是自动化的。
这些讨论导致了下面一些结论:
在软件开发中,具体建造费用非常低,几可忽略不计。
软件开发的绝大部分工作是设计,因此需要富有创造性的才智之士。
创造性的过程是不太容易计划的,因此,可预设性不可能成为一个要达到的目标。
我们应该对用传统工程模式来进行软件开发的做法保持足够的警觉,因为它们是不同类型的活动,因此需要不同的过程。
需求的不可预设性
在每个我参加的项目都有这样一种情况,开发人员跑来抱怨说, “这个项目的问题是需求老是在变”。而让我意外的是每个人都对此感到意外。其实在建造商用软件系统中,需求变更是常态,问题是我们如何来处理它。
一种方法是把需求变更看成是因需求工程(requirements engineering)没作好而导致的结果。一般来说,需求工程(或曰进行需求分析)是要在着手建造软件之前,获取一幅已完全理解了的待建系统的画面,然后取得客户认可签发,并且还要建立一套规章来限制需求变更。
该方法的一个问题是要准确获取所有需求是困难的,特别是当开发商不能提供某些需求的费用信息时。例如,你买车时想在你的车上装一个天窗,而推销员却不能告诉你要在车价上只再加10元钱呢,还是10000元。如果不知道这点,你如何能决定你是否愿意在车上加个天窗呢。
作软件开发的费用估算是不容易的,这有多种原因。部分原因是因为软件开发是一种设计活动,因此难于精确计划。部分原因是系统的“基本材料”变化非常之快。部分原因是开发活动极大地依赖于项目参与人员,而个体是难于预测和量化的。
软件的“不可触摸”性也是一个原因。在系统建成之前,有时很难判断一项功能的具体价值。也就是说,只有当你在实实在在地使用系统时,你才能知道哪些功能是有用的,哪些没什么用。
这样的结果颇具讽刺意味,即人们期待需求应该是可变的。毕竟,软件应该是 “软”的。所以,需求不仅是可变的,简直就是应该变的。要让客户把需求固定下来要花很大的力气,特别是当他们“参与”了软件开发并且“知道”软件是多么易于修改。
但是,即使你能把所有的需求都固定下来,并不意味着你的开发就是阳光灿烂了,你可能仍然会在昏暗之中。在当今的经济形势下,决定并推动软件系统功能特性的商业因素飞快地变化着。现在一组很好的功能六个月以后可能就不那么好了。
商业世界并不会因你的系统的需求固定下来了而停止不动,商业世界的许多变化是完全不可预测的。如果有人不承认这一点,要么他在撒谎,要么他已炒股成了百万富翁了。
软件开发的一切都取决于系统需求,如果需求不固定,你就不能制订出一个可预设性的计划。
预设性是不可能的吗?
一般来说,不可能。当然,有一些软件开发项目中,预设性是可能的。象 NASA的航天飞机的软件开发项目,应是这样一个例子。它需要大量的会议,充足的时间,庞大的团队,以及稳定的需求。毕竟,这些是航天飞机的项目。但我并不认为一般的商用软件开发属于这类系统,所以你需要不同的开发过程。
如果你不能遵循一个可预性方法,而你强装能够,那么这是非常危险的。通常,一个正规方法的创造者不是很善于(或乐于)给出其方法的边界条件,换句话说,当这些边界条件不满足时,则该方法就不适用。许多方法学者希望他们的方法能够放之四海而皆准,所以他们既不去了解,也不公布他们方法的边界条件。这导致了人们在错误的情形下来使用一种方法,例如,在不可预设性的环境中使用一种预设性的方法。
使用预设性方法具有强烈的诱惑力,因为预设性毕竟是一个非常需要的特性。可是,当你不能达到预设性时而你相信你能够,这将会导致这样一种局面:你可以很早就制订出计划,但不能适当地处理计划崩溃的情形。你看见现实与计划慢慢的偏离,而你可以在很长的时间里,装着认为计划仍是有效可行的。但是当偏离积累到足够的时候,你的计划就崩溃了,这通常是很痛苦的。
所以说,在不可预设性的环境中是不能使用预设性方法的。认识到这点是一个很大的冲击。它意味着我们用的许多控制项目的模式,许多处理客户关系的模式,都不会再是正确的了。预设性的确有非常多的好处,我们很难就放弃预设性而失去这些益处。象很多问题一样,最困难的一点是认识到这些问题的存在。
可是,放弃预见性并不意味着回到不可控制的一片混乱之中。你所需要的是另一类过程,它们可以让你对不可预设性进行控制,这就是“适配性” 的作用了。
不可预设过程的控制
那么,我们如何对付一个不可预测的世界呢?最重要,也是最困难的是要随时知道我们在开发中的情形处境,这需要一个诚实的反馈机制来不断准确地告诉我们。
这种机制的关键之点是“迭代式”(iterative)开发方法。这并不是一个新思路,迭代式开发方法已存在很久了,只是名称不同,如“递增式”(Incremental),“渐进式”(Evolutionary),“阶段式”(Staged),“螺旋式”(Spiral)等等。迭代式开发的要点是经常不断地出最终系统的工作版本,这些版本逐部地实现系统所需的功能。它们虽然功能不全,但已实现的功能必须忠实于最终系统的要求,它们必须是经过全面整合和测试的产品。
这样做的理由是:没有什么比一个整合了的、测试过的系统更能作为一个项目扎扎实实的成果。文档可以隐藏所有的缺陷,未经测试的程序可能隐藏许多缺陷。但当用户实实在在地坐在系统前来使用它时,所有的问题都会暴露出来。这些问题可能是源码缺陷错误(bug),也有可能是对需求理解有误。
虽然迭代式开发也可用于可预性环境,但它基本上还是用作“适配性” (adaptive)过程,因为适配性过程能及时地对付需求变更。需求变更使得长期计划是不稳定的,一个稳定的计划只能是短期的,这通常是一个“迭代周期”(iteration)。迭代式开发能让每个迭代周期为下面的开发计划提供一个坚实的基础。
迭代式开发的一个重要问题是一个迭代阶段需要多长。不同的人有不同的答案, XP(极端编程)建议一到两周,SCRUM建议一个月,Crystal(水晶系列)更长一些。不过,一般的趋势是让每一个周期尽可能地短。这样你就能得到频繁的反馈,能不断地知道你所处的状况。
适配性的客户
这类适配性过程需要与客户建立一种新型的关系,特别是当开发是由一家签约公司来进行的时候。因为当雇佣一家签约公司来进行开发时,多数客户愿意订一个固定价格的合同。他们告诉开发方他们所需要的功能,招标,签约,然后剩下的便是开发方去建造系统了。
固定价格合同需要稳定的需求,即一个可预设性过程。适配性过程和不稳定的需求意味着你不能做这种固定价格的合同。把一个固定价格模式弄到适配性过程将导致一个痛苦的结局。最糟糕的是客户将与软件开发者受到同样的伤害,毕竟客户不会想要一个不需要软件。即使他们未付开发方一分钱,他们仍然失去许多。
因此,在可预设性过程不能用的情况下,签订固定价格合同对双方来说都有危险。这意味着客户须换一种工作方式。
在适配性过程中,客户实际上能够对软件开发过程进行很深入细微的控制。在每一个迭代阶段中,他们都能检查开发进度,也能变更软件开发方向。这导致了与软件开发者更密切的关系,或曰真正的伙伴关系。但并不是每一个客户,也并不是每一个开发商都准备接受这种程度的介入,不过如要让适配性过程能很好工作,这种合作程度是基本的要求。
适配性过程对客户最关键的益处是软件开发中的“回应性”很好。一个可用的,尽管是很小的系统能够尽早投入使用。根据实际使用情况,以及变更了的需求,客户可及时改变一些系统功能。
让人优先
实施一个适配性过程并不容易,特别是它要求一组高效的开发人员。高效既体现在高素质的个体,也体现在有能让团队协调一致的工作方式。这里有一个有趣的和谐:并非只是适配性过程需要很强的团队,多数优秀的开发人员也愿意采用适配性过程。
可兼容性程序插件
传统正规方法的目标之一是发展出这样一种过程,使得一个项目的参与人员成为可替代的部件。这样的一种过程将人看成是一种资源,他们具有不同的角色,如分析员,程序员,测试员及管理人员。个体是不重要的,只有角色才是重要的。这样一来,在你计划一个项目时,你并不在乎你能得到哪个分析员,哪些测试员,你只需关心你可得到多少,知道资源数量会如何影响你的计划。但这有一个关键问题:参与软件开发的人员是可替代的部件吗?轻灵型方法的一个重要特征就是拒绝这种观点。
也许最明确地反对这种观点的当数Alistair Cockburn. 在他的论文 “人是非线性,一阶的部件”中,他指出可预设性软件开发过程要求 “部件”的行为也是可预性的。
但是,人并非可预性的部件。更进一步,他对软件项目的研究导致了如下结论:人是软件开发中最重要的因素。
在本文的标题里,我将人称为“部件”。其实(传统)过程/方法就是这样看待人的。这种观点的错误在于“人”是非常可变的和非线性的,不同的个体具备特有的成功或失败模式。那些因素是一阶的,不可忽略的。一种过程或方法的设计者如不能充分考虑到这些因素,那麽其后果就是项目的无计划轨迹。就象我们经常看到的那样。
-- Alistair Cockburn
Cockburn是最鲜明地主张在软件开发中应以人为中心,其实这种概念在许多软件行业的有识人士中已是共识。问题在于所使用的方法是与这种理念背道而驰的,这造成了一个很强的正反馈机制。如果你期望你的开发人员是可互替的编程插件,则你不会去试着把他们看成是不同的个体。这会降低士气(和生产率),并使优秀的人才跳到一个能发挥其个性特长的地方,最后你倒是得到你所需要的:可互替的编程插件。
决定使人优先是件大事,它需要很大的决心来推行。把人作为资源的思想在工商界是根深蒂固的,其根源可追溯到 泰勒的“科学管理”方法。当管理一个工厂时,这种泰勒主义途径是有效的。但是对有着高度创造性和专业性的工作,我相信软件开发当属此类,泰勒主义并不适用(事实上现代制造业也在脱离泰勒主义模式)。
程序员是负责任的专业人员
泰勒主义的一个关键的理念是认为干活的人并非是那些知道怎样才能把这件活干的好的人。在工厂中可能是这样,原因是许多工厂里的普通工人并非是最具聪明才智和最富创造力的人员。另一个原因也许是由于管理层和工人的的工资悬殊太大而导致的关系紧张。
历史证明这种情形在软件开发中是不存在的。不断有优秀人才被吸引到软件行业中,吸引他们的既有耀眼的光芒也有丰厚的回报(正是这两样诱使我离开电子工程)。其他一些福利如对公司的股份持有使得程序员的利益与公司紧联在一起。
〔可能还有一个“产生”(generational)效应。一些所见所闻让我想到是否在过去十来年中有很多的优秀人才转入软件行业。如果是这样,这可能是当今年轻人崇尚IT业的原因,就象其他时尚一样,其后总有一些实在的理由。)
如果你想聘到并留住优秀人才,你得认识到他们是有能力的专业人员。因此,他们最有资格决定如何干好他们的技术工作。泰勒主义里让计划部门来决定如何干好一件工作的作法只有当计划者比实际操作者更能知道怎样作时才有效。如果你拥有优秀的、自觉自励的员工,那么这点并不成立。
面向人的过程的管理
敏捷型过程中“以人为本”的理念可以有不同的表现,这会导致不同的效果,而并非所有结果都是完全一致的。
实施敏捷型过程的一个关键之处是让大家接受一个过程而非强加一个过程。通常软件开发的的过程是由管理人员决定的,因此这样的过程经常受到抵制,特别是如果管理人员已脱离实际的开发活动很长时间了。而接受一个过程需要一种“自愿致力”,这样大家就能以积极的态度参与进来。
这样导致了一个有趣的结果,即只有开发人员他们自己才能选择并遵循一个适配性过程。这一点在XP中特别明显,因为这需要很强的自律性来运行这个过程。作为一个互补,Crystal(水晶系列)过程则只要求最少的自律。
另一点是开发人员必须有权作技术方面的所有决定。XP非常强调这一点。在前期计划中,它就说明只有开发人员才能估算干一件工作所需的时间。
对许多管理人员来说,这样形式的技术领导是一个极大的转变。这种途径要求分担责任,即开发人员和管理人员在一个软件项目的领导方面有同等的地位。注意我说的同等。管理人员仍然扮演着他们的角色,但需认识并尊重开发人员的专业知识。
之所以强调开发人员的作用,一个重要的原因是IT行业的技术变化速度非常之快。今天的新技术可能几年后就过时了。这种情况完全不同于其他行业。即使管理层里的以前干技术的人都要认识到进入管理层意味着他们的技术技能会很快消失。因此必须信任和依靠当前的开发人员。
应用域专家的引领作用(The Role of Business Leadership)
技术人员并不能包打天下,他们需要应用系统的需求分析,即他们需要与应用领域专家非常紧密的联系,这是适配性过程一个重要的方面。这种联系的紧密度远远超过了一般项目中应用领域分析人员的介入程度。如果开发人员和应用领域专家只有偶尔的沟通,那么敏捷型过程是不可能存在的。此外,这种沟通不是由管理层来处理的,而是每个开发人员需要做的事。因为开发人员在他们的行业里是有能力的专业人员,因此他们能够与其他行业的专业人员同等地在一起工作。
这是由适配性过程的特点来决定的。因为在整个开发过程中,事情变化很快,你需要经常不断的联系沟通以使每个人都能及时知道这些变化。
对开发人员来说,没有什么比看见自己的辛勤工作白白浪费更让人痛苦的了。因此,开发人员能随时获取准确的高质量的应用系统的(需求)知识就显得很重要了。
自适配过程
到目前为止,我谈到的适配性是指在一个开发项目中如何频繁地修改软件以适应不断的需求变更。但是,还有另一种适配性,即是过程本身随着时间推移变化。一个项目在开始时用一个适配性过程,不会到一年之后还在用这个过程。随着时间的推移,开发组会发现他们的工作有些什么变化,然后改变过程以适应之。
自适配的第一步是经常对过程进行总结检讨。一般来说,在每一次迭代结束后,你可以问自己如下问题〔Norm Kerth):
有哪些做的好的部分
有哪些教训
有哪些可以改进的部分
有哪些没搞清楚的部分
这些问题会帮助你考虑在下一次迭代中如何对过程进行修正。在样,如果开始时使用的过程有问题的话,随着项目的进行,该过程会得以逐步的完善,以使其能更好地适合开发组。
如果一个项目采用了自适配方法,则可以进一步在一个组织内引入这种方法。如果要深化自适配过程,我建议开发人员专门用一段时间做一次更为正式的回顾总结,象Norm Kerth所建议的那样,这些活动包括离开工作地点,到另外一个地方开2-3天的总结会。这不仅是给开发组提供一次学习机会,同时也给整个组织一次学习机会。
自适配性导致的结果是你绝不能期待着只用一个过程。相反,每个项目组不仅能选择他们自己的过程,并且还能随着项目的进行而调整所用的过程。公开发表的过程和其他项目的经验都可以拿来作为参考和样本。但是开发人员需根据手中项目的具体情况而对其加以调整,这也是开发人员的专业职责。
这种自适配性在ASD和Crystal(水晶系列)中都鲜明地提及。XP的严格规则似乎不允许这样,但这只是表面现象,因为XP是鼓励调整过程的。这一点上XP和其他方法的主要区别之处在于,XP的倡导者建议在采用XP时,先根据书本循规蹈矩不走样地做几个迭代之后,再考虑调整。另外,回顾总结这点在XP中没有被强调,也不是这个过程的组成部分,尽管XP建议经常性的回顾应作为XP的实践准则之一。
敏捷型方法
好几个方法都可以归入敏捷型旗下,它们有许多的共同特征,但也有一些重要的不同之处。在此简短的综述中,我不可能列出这些过程所有的特点,但至少我可以告诉你可以到什么地方去查找更详细的材料。对大多数这些方法我都没有深入的实际经验。我有很多工作是基于XP的,也对RUP有些经验。但是对其他方法来说,我的知识主要是来自书本(当然这是很不够的)。
XP(Extreme Programming -- 极端编程)
在所有的敏捷型方法中,XP是最为引人瞩目的。部分原因是因为XP的领军人物们的卓越能力,特别是Kent Beck,他能够把人们吸引到这种方法来,并一直处于领先地位。但是XP热也带来了一个问题,就是它把其他一些方法和它们非常有价值的思想给挤了出去。
XP根源于Smalltalk圈子,特别是Kent Beck和Ward Cunningham在80年代末的密切合作。90年代初,他们在一系列项目上的实践深化扩展了他们关于软件开发应是适配性的、应以人为中心思想。
从非正式的、探索性的实践到形成系统化的正规方法的关键一步是在1996年春。Kent被邀对Chrysler的一个工资管理项目(C3)的开发进度进行审核。该项目由一个签约公司用Smalltalk开发,正处于困境之中。由于源码质量低劣,Kent建议推倒重来。该项目然后在他的领导下从头开始并成了早期 XP的旗舰和培训基地。
C3的第一期系统在1997年初投入运行。项目继续进行了一段时间后,遇到了麻烦,导致了在1999年开发计划被撤销。在我写此文时,该系统还在用来给万余员工发工资呢。
XP的四条基本价值原则是:沟通,反馈,简单和勇气。在此基础上建立了十多条XP项目应遵循的实践准则。其实,许多准则是以前就存在的并经过实践检验的,而常常被忽略了的。XP重新建立了这些准则,并把它们编织成了一个和谐的整体,使得每一项准则都能在其他准则里得以强化。
XP有一个最具冲击力的,也是最初吸引我的特点,是它对测试的极端重视。诚然,所有的过程都提到测试,但一般都不怎么强调。可是XP将测试作为开发的基础,要求每个程序员写一段源码时都得写相应的测试码。这些测试片段不断地积累并被整合到系统中。这样的过程会产生一个高度可靠的建造平台,为进一步开发提供了良好的基础。
在此基础上XP建立了一个渐进型的开发过程,它依赖于每次迭代时对源码的重组(refactoring)。所有的设计都是围绕着当前这次迭代,而不管将来的需求。这种设计过程的结果是“纪律性”与“适配性”的高度统一,使得XP在适配性方法中成为发展的最好的一种方法。
XP产生了一批领军人物,许多是从C3项目中出来的。关于XP有许多文献可读。最好的一篇总结文章是Jim Highsmith的Cutter论文(有趣的是Jim Highsmith并不是XP道中人,他的方法我将稍后介绍)。Kent Beck写的 Extreme Programming Explained,是一篇XP的宣言,它阐述了隐藏在 XP后面的道理。此书对有心于XP并致力于将其发扬光大者提供了充足的说明和解释。过去两年里也出版了一批“多姿多彩”的XP书籍,但多数都很相似,主要是从一些XP早期的实践者们的角度上描述了 XP的整个过程。
除了书之外,还有不少网上资源。如果你想找到更有结构性的材料,你最好访问两位C3成员的网站:Ron Jefferies的 xProgramming.com 和Don Wells的 extremeProgramming.org。 Bill Wake的 xPlorations 里也有一些很有用的文章。许多XP早期的倡导和发展可在Ward Cunningham的 wiki web (合作写作)中找到。wiki是个令人着迷的地方,尽管它的漫游性质常令人身不由己的陷入其中。 Robert Martin是一位知名的C++和OO设计的专家,他也加入了XP鼓吹者行列。他的公司 ObjectMentor 网站上有不少文章论及XP,其中一篇提出可把XP看成是一个最小RUP实现,他称之为 dX。另外,他们也资助 XP讨论组〔xp discussion egroup)。还有一篇很有意思的文章从“外面”来审视XP,这就是Mark Paulk所写的 从CMM的角度看XP。Mark Paulk是CMM的领军人物之一。
Cockburn的水晶系列方法
Alistair Cockburn 在90年代初受IBM之约进行正规方法的研究。从那时起他就活跃于这个领域。他的研究途径和其他方法学者有所不同。一般的方法学者是将他们个人的经验升华成理论。而Cockburn除了归纳整理他自己的实践经验以外,他还积极地造访其他项目,和项目组成员进行广泛的讨论,考察这些项目是怎样运作的。难能可贵的是,他从不固守自己的观点,他会根据新的发现而随时修正自己的理论。他的这些特点使得他成为我最喜欢的方法学者。
他的著作 “Surviving Object-Oriented Projects” 汇集了很多如何顺利运行软件开发项目的建议,此书也是我推荐的运行迭代式项目的首选书。最近,Alistair写了一本关于 敏捷型软件开发 的综述性著作,探讨了这些方法的基本原则。
Alistair还更进一步地探索了敏捷型方法,并提出了 水晶(Crystal)方法系列。之所以是个系列,是因为他相信不同类型的项目需要不同的方法。他认为决定一个方法与两个因素有关:项目参与人数和出错后果。如果用两个坐标轴来分别表示这两个变量的话,那么在这张图上,每一种方法都有其相应的位置。例如,有两个项目,一个是有40人参加,如果失败造成的资金损失可以接受;另一个项目只有6人,其成败生存悠关。那么这两个项目所用的方法在坐标图上就有不同的位置。
水晶系列与XP一样,都有以人为中心的理念,但在实践上有所不同。Alistair 考虑到人们一般很难严格遵循一个纪律约束很强的过程,因此,与XP的高度纪律性不同,Alistair探索了用最少纪律约束而仍能成功的方法,从而在产出效率与易于运作上达到一种平衡。也就是说,虽然水晶系列不如XP那样的产出效率,但会有更多的人能够接受并遵循它。
Alistair也费了不少笔墨强调每次迭代后的总结回顾,因而鼓励过程本身的自我完善。他的理由是迭代式开发是用来尽早发现问题并解决之。这样就更加强调了开发人员要随时观察他们所用的过程,并随着项目的进行而调整。
2001年2月,Alistair宣布他和Jim Highsmith将合并他们的方法。这个方法有何影响,如何命名,都还是有待回答的问题。
开放式源码
看到这个标题你可能会有些意外。毕竟,开放式源码(Open Source)是软件的一类风格,而非一种过程。这里我是指开放源码界所用的一种运作方式,这种方式适用于开放源码项目,其实它的许多做法也可为封闭式源码项目所用。开放式源码项目有一个特别之处,就是程序开发人员在地域上分布很广。注意到这点相当重要,因为一般适配性过程都强调项目组成员在同一地点工作。
多数开放源码项目有一个或多个源码维护者(maintainer)。只有维护者才能将新的或修改过的源码段并入源码库。其他众人可以修改源码,但需将他们所做的改动送交给维护者,由维护者对这些改动进行审核并决定是否并入源码库。通常来说,这些改动是以“补丁”(patch)文件的形式,这样处理起来容易一些。维护者负责协调这些改动并保持设计的一致性。
维护者的角色在不同的项目中有不同的产生和处理方式。有些项目只有一个维护者,有些项目把整个系统分成若干个模块,每个模块有一个维护者。有些是轮流做维护者,有些是同一个源码部分有多个维护者,有些则是这些方式的组合。许多开放源码项目的参与者只是部分时间(或业余时间)干,如果项目要求是全日制的,那么这有一个问题,就是怎样才能把这些开发人员有效地协调组织起来。
开放源码的一个突出特点就是查错排故(debug)的高度并行性,因为许多人都能同时参与查错排故。如果他们发现了错误,他们可将改正源码的 “补丁”文件发给维护者。这种查错排故角色对非维护者来说合适,对那些设计能力不是很强的人来说,也是一项挺好的工作。
关于开放源码的方法过程还没有很系统的文献。目前最著名的一篇文章是 Eric Raymond写的 The Cathedral and the Bazaar(教堂与集市),文章虽短,但很精彩。另外,Karl Fogel所著的 关于CVS的书中也有几章描述了开放源码的方法。即使你不想使用CVS,这几章还是值得一看。
Highsmith的适配性软件开发方法(ASD--Adaptive Software Development)
Jim Highsmith 多年来一直从事可预性方法的研究,建立和教学,而最后得出的结论是这些方法都有着根本性的缺陷,特别是在用来作现代应用系统的开发时。
他最近的 一本书 集中论述了新方法的适配特性,重点讨论了把一些起源于复杂适配性系统(通常称之为混沌理论--chaos theory)的思想在软件开发中加以应用。此书没有象XP那样提供详尽的实践准则,但它从根本上说明了为什么适配性开发方法是重要的,并进一步说明了其对组织结构和管理层的影响。
ASD的核心是三个非线性的、重迭的开发阶段:猜测,合作与学习。
在一个适配性环境中,因为结果是不可预的,Highsmith把计划看成是一个 “反论”〔paradox)。在传统的计划中,偏离计划是错误,应予纠正。而在一个适配性环境里,偏离计划则是在引导我们向正确的目标迈进。
在不可预的环境里,你需要大家能以多种多样的方式合作来对付不确定性。在管理上,其重点不在于告诉大家做什么,而是鼓励大家交流沟通,从而使他们能自己提出创造性的解决方案。
在可预性环境里,通常是不大鼓励学习的。设计师已经都设计好了,你跟着走就行了。
在适配性环境中,学习对所有各方,包括开发人员和客户, 都是一个挑战。他们需要学习以检验他们作的假设,需要学 习以便能用每次开发周期的结果去适配下一个周期。
-- Highsmith
这样的学习是连续不断的,这已成为这种方法的一个重要特点,因此我们必须得认识到计划和设计都得随开发的推进而改变。
适配性开发周期的最大而不可见的好处是其对我们自以为是的心理 模式的挑战,它迫使我们更实际地估计自己的能力。
-- Highsmith
有了这样的出发点,Highsmith把他的工作集中放在适配性开发的难点上,特别是如何在一个项目中增强合作和学习。基本上说,他的这本书是侧重于“软”方法,这样对那些从开发实践中提炼出来的方法如XP,FDD 和水晶系列来说,这本书将是一个很有益的互补。因此Highsmith在2001年 2月宣布他将把他的方法于Cockburn的水晶系列合并,就是顺理成章并且很有意义的了。
SCRUM
SCRUM在OO界里已很有些时日了,不过我得承认我对其历史发展并不是太知其详。象前面所论及的方法一样,该方法强调这样一个事实,即明确定义了的可重复的(defined and repeatable)方法过程只限于在明确定义了的可重复的环境中,为明确定义了的可重复的人员所用,去解决明确定义了的可重复的问题。
SCRUM把一个项目分成若干个为期30天的迭代阶段,称之为一“冲” (sprint)。开“冲”之前,你得明确这一“冲”要实现的功能,然后交给开发组去完成。但是,在“冲”期间,需求必须是固定的。
管理人员并非在“冲”的时候就撒手不管了。每天,他需召集一个短会(15分钟左右),称之为一个scrum,会上大家讨论决定第二天干什么。特别是大家会对管理层提出那些阻碍项目进行的因素,并希望管理层能予以解决。当然,他们也需要报告目前完成了什么,这样管理层每天都能了然项目的进展情况。
SCRUM文献多集中论述迭代阶段计划与进度跟踪。它与其他敏捷型方法在许多方面都很相似,特别是它可以与XP的编程准则很好地结合起来。
相当长的一段时间没有关于SCRUM的专门书籍,直到最近 Ken Schwaber和Mike Beedle写了 第一本SCRUM的专著。Ken Schwaber还主持了一个网站 ControlChaos.com,可能是对SCRUM的最好的综述。Jeff Suthurland有个总是很活跃的网站讨论OO技术,其中有 一部分是专门讨论SCRUM的。另外,在 PLoPD 4书中也有一篇关于SCRUM的很好的综述。
Coad的功用驱动开发方法(FDD--Feature Driven Development)
FDD是由Jeff De Luca和OO大师Peter Coad提出来的。象其他方法一样,它致力于短时的迭代阶段和可见可用的功能。在FDD中,一个迭代周期一般是两周。
FDD有以下五项任务:
建立总体模型
提出功用清单
针对功用逐项制订计划
针对功用逐项进行设计
针对功用逐项开发实现
头三项在项目开始时完成,后两项在每一次迭代周期时都要做。每一项任务又可进一步分解并制订出相应的检验准则。
在FDD中,编程开发人员分成两类:首席程序员和“类”程序员(class owner)。首席程序员是最富有经验的开发人员,他们负责开发实现系统的各项功能。对每一项功能,首席程序员要定出需要哪些类(class)来实现这项功能,并召集“类”程序员们组成一个针对这项功能的开发组。首席程序员作为协调者,设计者和指导者,而“类”程序员则主要作源码编写。
FDD的主要论述见于Peter Coad等所著的 UML in Color 。他的公司 TogetherSoft 也从事FDD的咨询和培训工作。
动态系统开发方法〔DSDM--Dynamic System Development Methods)
DSDM在1994年始于英国。 英国一些想用RAD和迭代方式进行系统开发的公司组成了一个社团〔Consortium)。刚开始有17个组建成员,到现在成员已超过1000个,遍布英国内外。DSDM由于是由一个社团所发展,它与其他一些敏捷型方法有些不同。它有专门的组织支持,有手册,培训课程,认证程序等。因为它上面的价格标签而限制了我对此方法的进一步调查。不过Jenifer Stapleton已写了 一本书来介绍这种方法。
如果你要用这种方法,你得先作可行性和应用域分析。可行性分析要考虑 DSDM是否适合手上这个项目。而应用域分析则是开一系列的讨论会,以期能充分了解应用域,同时也要提出大致的系统结构与项目计划。
余下的工作由三个互相交织的周期组成:功能模型周期产生文档和原型(实验系统),设计建造周期生成可操作使用的系统,实现周期处理系统安装部署(deployment)问题。
DSDM有一些基本的原则包括与用户积极的沟通,频繁的出活(delivery)。有充分职权的项目组,完全的系统测试。象其他敏捷型方法一样, DSDM的一个周期在2-6周之间。它强调高质量的系统以及需求变更的高度适配性。
我还没有在英国之外的地方看到有项目使用DSDM。DSDM的基本结构有许多成熟的传统方法的东西,同时又遵循了敏捷型途径。但这里的确有一点值得注意,即是这种方法是否有鼓励一种面向过程与繁琐的倾向。
敏捷软件开发宣言
可以看出,前面所提到的这些方法有很多的相似之处,那么自然大家就会有兴趣进行某种形式的合作。 2001年2月,这些方法的代表人物们被邀至犹它州Snowbird 举行了一个为期两天的讨论会。我也在其列,但开始并未抱太大希望。毕竟,当你把一堆方法学者塞进一间房子时,他们能以礼相待就是上上大吉了。
结果却出乎我的意料之外。每个与会者都认识到这些方法有许多的共同点,这种共识远远大于他们之间的分歧。这次讨论会使这些一流的方法学者们增进了联系,大家还有意发表一份联合声明--呼吁推动发展敏捷型开发过程(我们也同意用“敏捷”(agile)这个词来表达我们共有的理念)。
成果便是一份 敏捷软件开发宣言〔Manifesto for Agile Software Development),它表述了敏捷型过程所共同具备的价值和原则。与会者也有意在将来进一步合作,并鼓励方法学者与商界人士使用敏捷型方法进行软件开发。 Software Development Magazine〔软件开发杂志)有一篇关于 宣言的评注与解释的文章,它的片断可见于 敏捷宣言的将来。
RUP是一种敏捷型方法吗?
当我们开始讨论OO领域的方法时,不可避免地会碰到 RUP(Rational Unified Process)。该过程由Philippe Kruchten, Ivar Jacobson以及Rational Rose 的其他一些人士开发,主要是作为一个与UML相配合和补充的过程。RUP其实是个过程的框架,它可以包容许多不同类型的过程,这一点正是我对RUP的主要批评。因为它可以是任何东西,那么就跟什么都不是一样了。我愿意选择的过程是它能明确告诉你干什么,而不是给你无穷无尽的选择。
由于RUP是一种框架,你可以以不同的方式来使用它,如象非常传统的“瀑布” 式开发方式,或敏捷式。你可以把用得轻捷灵便,也可把它弄成繁文缛节。这取决于你如何在你的环境中对它裁剪运用。
Craig Larman极力主张以敏捷型方式来使用RUP。在他的关于OO开发的 引论著作 中,他提出了一个过程,就是基于这种“轻型”RUP的思想。他的观点是:目前如此众多的努力以推进敏捷型方法,只不过是在接受能被视为RUP 的主流OO开发方法而已。在做一个项目时,Craig要干的事情之一便是在为期一月的迭代周期的头两三天和整个开发组呆在一起,用UML勾勒出这个迭代阶段的设计。这个设计并非是一个不可更改的,它只是一个使大家能知道这个阶段如何干的草图。
另一种对待RUP的策略是Robert Martin的 dX过程。dX过程是一个完全符合RUP 的过程,而又碰巧与XP完全等同(把dX转180度可见,一句戏言)。dX是特别适合于那些不得不用RUP而又想用XP的伙计们。由于dX既是XP又同时是 RUP,它可作为以敏捷方式运用RUP的一个极好的例子。
对我而言,在运用RUP时的一个关键之处在于业界RUP的领头者们需强调他们的软件开发途径。曾经不止一次,我听到使用RUP的人是在使用“瀑布”式开发过程。根据我在业界的联系,我知道Philippe Kruchten和他的小组是坚定的迭代式开发信奉者。澄清这些原则并鼓励敏捷式使用RUP,如象Craig Robert的工作,将对软件开发有着重要的影响和作用。
其他参考材料
关于敏捷型方法有不少文章和讨论组,它们可能不会提供完整的方法,但可以给你一个窗口以观察这个正兴起的领域在如何发展。
程序设计的模式语言(Patterns Language of Programming) 大会经常会有一些材料讨论这个题目,这也许是因为许多对模式(Pattern)感兴趣者也对适配型和“人道”方法过程感兴趣的缘故吧。这方面有一篇早期的一流论文, Jim Coplein所著,收集在 PLoP1 中。Ward Cunningham的Episodes模式语言收集 PLoP2 中。Jim Coplein现主持一个网站, OrgPatterns,以wiki方式收集了不少组织结构模式。 Dirk Riehle在XP2000大会上提交了一篇论文,该文比较了XP和适配性软件开发(Adaptive Software Development, ASD)的 价值系统。Coad Letter的 七月期比较了XP和FDD。IEEE Software的七月期有几篇文章论述 “过程多样性”(process diversity),也提及这些方法。
Mary Poppendieck写了一篇很精彩的文章 比较敏捷型方法与精悍(lean)型制造业。
你是否应走向敏捷?
并非人人都能使用敏捷型方法。当你决定走这条路时,你得记住许多准则。但是,我确切相信,这些新方法可被广泛的应用。只是考虑使用它们远远不够,应该有更多的人来实践中运用它们。
在目前的软件开发中,多数方法仍是边写边改(code and fix),那么,引入一些纪律约束肯定会比一片混乱要好。敏捷型途径的主要优点在于它比重型方法的步骤要少得多。如果你已习惯于无过程,那么遵循简单过程应该比遵循繁琐过程更容易一些。
这些新方法的主要局限是如何对付较大的项目组。水晶类方法可在最多到50人的项目组内使用。如果超过了这个规模,则还没有证据或经验来说明如何运用这些适配性方法,甚至这些方法是否工作都很难说。
这篇文章至少传递了这样一个信息,就是适配性方法对需求不确定或常常变更的情形是有效的。如果你没有稳定的需求,那么你就不可能进行稳定的设计并遵循一个计划好了的过程。这种情况下,适配性过程可能感觉上不太舒服,但实践上会更有效一些。通常来说,使用适配性方法最大的障碍来自客户。我认为,重要的一点是让客户理解在一个需求不断变更的环境中,遵循可预性过程对他们是有风险的,同样对开发方也是有风险的。
你可能已注意到我说过50人以上的项目组应使用传统的可预性过程,需求不断变更的话,则应使用适配性过程。那么,如果你的项目很大而需求又在不断地变更,又当如何呢?对这个问题我并无一个满意的答案,我建议你去寻求其他意见。但我可以告诉你,这种情形下事情将会非常困难,不过我想你肯定已知道这一点了。
如果你要采用适配性方法,你需要信任你的开发人员,并让他们参与(技术)决策。适配性过程的成功依赖于你对你的开发人员的信任。如果你认为你的开发人员素质不够,那么你应采用可预性途径。
总结一下,如下的因素建议你采用适配性过程:
不确定或常变更的需求
负责任的,自觉自励的开发人员
理解并愿意参与其中的客户
而如下这些因素则建议你使用可预性过程:
50人以上的项目组
固定价格,或更确切的说,固定任务范围的合同
该用哪个适配性过程?
本文论及的这些适配性过程都还很新,我只能提供一些第一手经验以供参考。我对过程的选择通常视项目组人数,以及他们愿意遵循多少纪律规章而定。
如果开发人员有十二个或以下,那么我肯定推荐XP。开发组有可能不会严格地把所有XP的过程都走一遍(特别是刚开始时),但这种部分XP过程仍能让你获益不少。我认为,用好XP的一个关键的部分是要将单元测试(unit test)自动化。如果开发组愿意这样做,系统就有了一个坚实的技术基础。如果他们不想这样干,我不怀疑他们自己就得来做这些测试。
如果没有纪律规章,或项目组太大,那么我倾向于水晶系列。水晶系列肯定是敏捷型方法中最轻的,Cockburn特别主张吸取开发中的经验教训(而对过程进行调整)。不过,在这种情况下,我仍会用XP来作过程计划。
我虽然这样说了,可是我现在的项目组有40人,我们成功地试验了许多XP准则,实际上也很接近完全的XP了。所以说,如果有一个有决心有热忱的团队,你在选择过程的时候,完全可以突破一些我提到的边界条件。
还有一点非常关键,那就是不管你开始时用的是什么过程,该过程都不会是完全如你想象的那样得心应手,你得不停地对它进行监查与修改以适配你的环境。最后一点,它必须得是你自己的过程,其他标签都是次要的。
鸣谢
本文得益于许多朋友的意见,恕难一一列出。但是,我要特别感谢Marc Balcer, Kent Beck,Alistair Cockburn,Ward Cunningham,Bill Kimmel 和Frank Westphal。
请记住这是一篇不断改进的网络文章。我将附上主要修改记录,而小改动将不作记录。
修改记录
2001年11月:更新一些最近的参考材料。
2001年3月: 加上关于“敏捷联盟”的内容。
2000年12月:本文缩写发表于Software Development杂志。
2000年11月:更新ASD部分并加上DSDM和RUP的章节。
2000年7月: 初稿发于martinfowler.com。
--------------------------------------------------------------------------------
译后注:
我去年(2000年)曾参加过一个ECommerce系统的软件开发工作。这个项目采用了一种类似XP(极端编程)的开发方式,一个迭代周期约为三周,实现一项use case〔use case driven)。开发中特别强调单元测试(unit testing,使用JUnit)与每天的“冒烟测试”(smoke test)。今年〔2001年)初读到Martin Fowler的网站(www.martinfowler.com)上的这篇 “The New Methodology”时,我正参加一个投资银行的证券分析信息系统的开发工作,该项目也采用了迭代式开发过程。但由于环境不同,这个项目的迭代周期较长一些,约六到八周。这个项目的另一个特点是开发人员和系统分析员〔business analysts)以及测试人员〔testers)的沟通特别频繁。读了这篇文章后,我觉得它能够让人从一个比较广阔而系统的角度来考察一个迭代式项目的运作。
诚如作者所言,这是一篇不断改进的网络文章。我将尽力随原文的更新而及时更新译文。此译文中如有所译不当之处,望诸位同行不吝赐教。
原文: http://www.martinfowler.com/articles/newMethodology.html
译文: http://members.tripod.com/jian_hu/fowler/newMethodology.html
2001年12月:译自原文2001年11月版。
胡健
Email: jian4_hu2@hotmail.com
Web: http://members.tripod.com/jian_hu