敏捷过程

http://softwarepractitioner.org/translations/fowler/newMethodology.shtml

新方法学

Martin Fowler

过去几年中蓬勃兴起的一种称之为敏捷型(agile〕的软件开发方法,以矫正 官僚繁琐过程、许可对过程进行自主调整为特征,在软件业引起了极大的兴趣。 在这篇文章里,我将探索敏捷型方法的合理性, 着重点并不是放在其“轻重”上,而是于它们的适应性(adaptive〕性质 和以人优先的理念。

最近一次主要修改: 2005年12月13日

 

相关文章

 

过去几年中,关于软件开发过程,其最大的变化也许是敏捷(agile)这个词的 出现。我们谈论敏捷开发方法,如何在项目团队中引入敏捷性,或如何抵御 敏捷论者们即将掀起的旨在改变业已确立的开发实践的风暴。

这场运动源自1990年代一些与软件开发过程打交道的人士的工作,他们发现需要 寻找软件开发过程的新途径。其实,这些途径中的大部分思想并不是新的,许多 认为,很长一段时间以来的成功软件都是依据这些思想来建造的。但这些思想却 被压抑了,没有受到足够的重视,特别是在那些从事软件开发过程的人士中。

这篇文章最初是作为这场运动的一部分,初稿发表于2000年7月。象我的其他文章 一样,我写这篇文章的部分目的是想很好地理解这个问题。那时,我已使用了好 几年的极限编程(XP)。这始于1996年,当时我有幸与Ken Beck, Ron Jefferies, Don Wells以及所有的Chrysler C3的成员们一起工作。从那以后,我也同其他有 相似思想却并非一定要采取XP的同行们进行了交流,阅读了他们的著作。因此,在 文章中也试图探讨这些方法的相似与不同之处。

我的结论是,我现在仍然认为,有一些根本性的原则是这些方法的共同之处,这些 原则与那些业已确立的方法的前提假设是截然相反的。

这篇文章一直是我的网站中最热门的文章之一,因此我感到有责任随时更新。在初稿 中,我既探讨了敏捷方法与业已确立的方法在原则上的不同,也对一些敏捷型方法 根据我当时的理解作了一点综述。从那时以来,敏捷方法已改变了许多,要完全地 随时更新已是比较困难,当然我还是给出了若干链接以便于读者能继续探索。敏捷 方法与老方法的原则上的差异部分则基本保留没变。

从无、到繁重、再到敏捷

多数软件开发仍然是一个显得混乱的活动,即典型的“边写边改” (code and fix〕。设计过程充斥着短期的、即时的决定,而无完整的规划。 这种模式对小系统开发其实很管用,但是当系统变得越大越复杂时,要想加 入新的功能就越来越困难。同时错误故障越来越多,越来越难于排除。一个典 型的标志就是当系统功能完成后有一个很长的测试阶段,有时甚至有遥遥无期 之感,从而对项目的完成产生严重的影响。

软件行业中最初的一场运动是要改变这种情况,而引入了“正规方法” (methodology〕的概念。这些(正规)方法对开发过程有着严格而详 尽的规定,以期使软件开发更有可预设性并提高效率,这种思路是借鉴了其他 工程领域的实践 - 因此我把它们称为工程方法(engineering methodologies)(另一个广泛使用的词汇是计划驱动方法(plan-driven methodologies))。

工程方法已存在了很长时间了,但是没有取得令人瞩目的成功,甚至就 没怎么引起人们的注意。对这些方法最常听见的批评就是它们的官僚繁琐, 要是按照它的要求来,那有做太多的事情需要做,而延缓整个开发进程。

敏捷型方法(agile methodologies)的发展是对这些工程方法的反叛。 对许多人来说,这类方法的吸引之处在于对繁文缛节的官僚过程的反叛。它们 在无过程和过于繁琐的过程中达到了一种平衡,使得能以不多的步骤过程获取 较满意的结果。

敏捷型与工程型方法有一些显著的区别。其中一个显而易见的不同反映在文档 上。敏捷型不是很面向文档,对于一项任务,它们通常只要求尽可能少的文档。 从许多方面来看,它们更象是“面向源码”(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(水晶系列〕 更长一些。不过,一般的趋势是让每一个周期尽可能地短。这样你就能得 到频繁的反馈,能不断地知道你所处的状况。

适应性的客户

这类适应性过程需要与客户建立一种新型的关系,特别是当开发是由一家签约公 司来进行的时候。因为当雇佣一家签约公司来进行开发时,多数客户愿意订一 个固定价格的合同。他们告诉开发方他们所需要的功能,招标,签约,然后剩下 的便是开发方去建造系统了。

固定价格合同需要稳定的需求,即一个可预见性过程。适应性过程和不稳定的需 求意味着你不能做这种固定价格的合同。把一个固定价格模式弄到适应性过程 将导致一个痛苦的结局。最糟糕的是客户将与软件开发者受到同样的伤害,毕 竟客户不会想要一个不需要软件。即使他们未付开发方一分钱,他们仍然失去 许多。的确,他们失去的比要付给开发商的要多(他们凭什么付这笔钱,如果 这个软件的商业价值很小?)

因此,在可预见性过程不能用的情况下,签订固定价格合同对双方来说都有危 险。这意味着客户须换一种工作方式。

这并不是说,你不能为你的软件固定一笔预算。这实际意味着你不能固定时间、 价格和范围(scope)。通常一个敏捷方法是固定时间和价格,而让范围能够 可控制地变化。

在适应性过程中,客户实际上能够对软件开发过程进行很深入细微的控制。在 每一个迭代阶段中,他们都能检查开发进度,也能变更软件开发方向。这导致 了与软件开发者更密切的关系,或曰真正的商业伙伴关系。但并不是每一个客户, 也并不是每一个开发商都准备接受这种程度的介入,不过如要让适应性过程能 很好工作,这种合作程度是基本的要求。

这种开发方式可以给客户带来很多的益处。首先,这种开发的“回应性”0 (responsive)是很好的。一个可用的,尽管是很小的系统能够尽早投入使用。 客户可以根据变更了的业务需求和实际使用情况,来及时要求改变一些系统功能。

这样一种方式能够更真实地反映出项目的实际状态。可预见性过程的问题是: 项目的质量是根据与计划的一致性来衡量的。当实际情况与计划脱节时,人们 很难提出来。一般的结果是在项目的后期出现进度上的大滑坡。 在敏捷型的项目中,每一个周期都对计划进行评审。如果有什么糟糕的事情 的话,它也会早点被发现,因此仍然会有时间来解决。的确,这种风险控制 是迭代式开发的一个关键优点。

而敏捷型开发还更进了一步,因为不仅它的周期很短,同时它也从另外一个角度 来看这些变化。我认为最好的表述是Mary Poppendieck的总结“后期的需求变化 是个很大的优势”。我想许多人都注意到业务人员很难在一开始就清楚到底需要 软件具备什么功能。通常我们看到的是他们在开发过程中逐步认识到什么功能是 重要的,什么不是那么重要的。最有价值的功能经常是要等到客户使用了系统之后 才明朗起来。敏捷方法正是要利用这一点,鼓励业务人员在开发过程中来梳理他们 的需求,在系统建造中把这些变化尽快地整合进去。 TODO

这点对于定义什么是成功项目有重要的意义。预见性项目是否成功是由它是否 很好地按计划执行来衡量的。一个项目如果在规定的时间和预算内完成,那 就是成功的。对于敏捷型环境而言,这种衡量是没有意义的。对于敏捷型 项目实践者来说,最重要的是商业价值(business value)- 客户得到的 软件的价值是否大于他们的投入。一个好的预见性项目是依计划而行,而一个 好的敏捷型项目会建造出一个与最初计划不太一样却是更好的软件。

把人放在第一位

实施一个适应性过程并不容易,特别是它要求一组高效的开发人员。高效既 体现在高素质的个体,也体现在有能让团队协调一致的工作方式。这里有一 个有趣的和谐:并非只是适应性过程需要强的团队,多数优秀的开发人 员也愿意采用适应性过程。

可兼容性程序插件

传统正规方法的目标之一是发展出这样一种过程,使得一个项目的参与人员 成为可替代的部件。这样的一种过程将人看成是一种资源,他们具有不同的 角色,如一个分析员,一些程序员,测试员及一个管理人员。个体是不重要的, 只有角色才是重要的。这样一来,在你计划一个项目时,你并不在乎你能得到哪个分 析员,哪些测试员,你只需关心你可得到多少,知道资源数量会如何影响你 的计划。

但这有一个关键问题:参与软件开发的人员是可替代的部件吗?敏捷型方法 的一个重要特征就是拒绝这种观点。

也许最明确地反对这种观点的当数Alistair Cockburn. 在他的论文 “软件开发中人是非线性,一阶的部件”中,他指出可预见性软件开发过程要求 “部件”的行为也是可预见性的。 但是,人并非可预见性的部件。更进一步,他对软件项目的研究导致了如下结论: 人是软件开发中最重要的因素。

在本文的标题里,我将人称为“部件”。(传统〕过程/方法就是这样看待 人的。这种观点的错误在于没有看到“人”是高度可变的和非线性的, 不同的个体具备特有的成功或失败模式。那些因素是一阶的,不可忽略的。 一种过程或方法的设计者如不能充分考虑到这些因素,那么其后果就是项目 的无计划轨迹,就象我们经常看到的那样。 
-- [Cockburn non-linear]

Cockburn是最鲜明地主张在软件开发中应以人为中心,其实这种概念在许多软 件行业的有识人士中已是共识。问题在于所使用的方法是与这种理念背道 而驰的。

这造成了一个很强的正反馈机制。如果你期望你的开发人员是可互替 的编程插件,则你不会去试着把他们看成是不同的个体。这会降低士气(和生 产率〕,并使优秀的人才跳到一个能发挥其个性特长的地方,最后你倒是得到 你所需要的:可互替的编程插件。

作出使人优先的决定是件大事,它需要很大的决心来推行。把人作为资源的思想 在工商界是根深蒂固的,其根源可追溯到 泰勒的“科学管理”方法。当管理一个 工厂时,这种泰勒主义途径是有效的。但是对有着高度创造性和专业性的工作, 我相信软件开发当属此类,泰勒主义并不适用(事实上现代制造业也在脱离 泰勒主义模式〕。

程序员是负责任的专业人员

泰勒主义的一个关键的理念是认为干活的人并非是那些 知道怎样才能把这件活干的好的人。在工厂中可能是这样,原因是许多工厂里 的普通工人并非是最具聪明才智和最富创造力的人员。另一个原因也许是由于 管理层和工人的的工资悬殊太大而导致的关系紧张。

历史证明这种情形在软件开发中是不存在的。不断有优秀人才被吸引到软件行 业中,吸引他们的既有耀眼的光芒也有丰厚的回报(正是这两样诱使我离开电子 工程〕。尽管有2000年代初的衰退,在软件开发行业中仍然有许多富于才智和 创造力的人士。

〔可能还有一个“产生”(generational)效应。一些所见所闻让我想 到是否在过去十来年中有很多的优秀人才转入软件行业。如果是这样,这可能 是当今年轻人崇尚IT业的原因,就象其他时尚一样,其后总有一些实在 的理由。〕

如果你想聘到并留住优秀人才,你得认识到他们是有能力的专业人员。因此, 他们最有资格决定如何干好他们的技术工作。泰勒主义让计划部门来决定如 何干好一件工作的作法只有当计划者比实际操作者更能知道怎样作时才有效。 如果你拥有优秀的、自觉自励的员工,那么这点并不成立。

面向人的过程的管理

敏捷型过程中“以人为本”的理念可以有不同的表现,这会导致不同的效果, 而并非所有结果都是完全一致的。

实施敏捷型过程的一个关键之处是让大家接受一个过程而非强加一个过程。 通常软件开发的的过程是由 管理人员决定的,因此这样的过程经常受到抵制,特别是如果管理人员已脱离 实际的开发活动很长时间了。而接受一个过程需要一种“自愿致力” (commitment),这样大家就能以积极的态度参与进来。

这样导致了一个有趣的结果,即只有开发人员他们自己才能选择并遵循一个适 应性过程。这一点在XP中特别明显,因为这需要很强的自律性来运行这个过程。 作为一个互补,Crystal(水晶系列〕过程则只要求最少的自律。

另一点是开发人员必须有权作技术方面的所有决定。XP非常强调这一点。 在前期计划中,它就说明只有开发人员才能估算干一件工作所需的时间。

对许多管理人员来说,这样形式的技术领导是一个极大的转变。这种途径要求 分担责任,即开发人员和管理人员在一个软件项目的领导方面有同等的地位。 注意我说的同等。管理人员仍然扮演着他们的角色,但需认识并尊重开发 人员的专业知识。

之所以强调开发人员的作用,一个重要的原因是IT行业的技术变化速度非常之快。 今天的新技术可能几 年后就过时了。这种情况完全不同于其他行业。即使管理层里的以前干技术的人 都要认识到进入管理层意味着他们的技术技能会很快消失,因此必须信任和依靠 当前的开发人员。

测度的困难性

如果有一个过程,规定工作应该如何来做的人不是具体去干的人,那么你需要一些 方法来测度干工作的人是否工作有效。在“科学管理”中,有种强烈的力量驱使着 发展出客观性方法来测度人们的工作输出。

这与软件特别有关,但是要测度软件是非常困难的。尽管人们已经尽了很大的努力, 我们仍然不能对软件的一些很简单方面进行测度,如生产率。如果没有一套有效的 测度方法,任何外部的控制都会是困难的(doomed)。

不存在一套有效的测度方法而要在管理中引入测度将会导致管理本身出问题。关于这点, Robert Austin有段出色的讨论。他指出,当进行测度时,你必须要获取影响这种 测度的所有重要因素。任何缺失都将不可避免地使得具体干工作的人改变 他们的工作方式以获得最好的测度成绩,甚至于那样会明显地降低他们真正的工作 有效性。这种测度的“失效”(dynsfunction)正是基于测度的管理方法的 致命之处(Achilles heel,即阿其里斯的脚踝)。

Austin的结论是你得在这两种方法中作选择:基于测度的管理,或是“委托式” (delegatory)管理(干工作的人决定该怎么干)。基于测度的管理是非常适合 简单的、重复性的工作,知识要求低并且易于测度输出 -- 这恰恰与软件开发 相反。

关键之处是传统方法假设的前提是基于测度的管理是最有效的管理方式。而 敏捷开发者则认为软件开发的特性会使得基于测度的管理导致非常高度的测度 “失效”(dysfunction)。实际上使用委托式的管理方式要有效得 多,这正是敏捷论者所持观点的中心所在。

业务专家的引领作用(The Role of Business Leadership〕

但技术人员并不能包打天下,他们需要应用系统的需求引导。这导致了适应性过程 的另一个重要方面:他们需要与应用领域的业务专家非常紧密的联系。

这种联系的紧密度超过了一般项目中业务人员的介入程度。如果开发人员和 业务人员只有偶尔的沟通,那么敏捷型过程是不可能存在的。他们需要不断地 获取业务方面的专门知识。此外,这种沟通不是由管理层来处理的,而是每个开发 人员需要做的事。因为开发人员在他们的行业里是有能力的专业人员,因此他们 能够与其他行业的专业人员同等地在一起工作。

这是由适应性过程的特点来决定的。因为敏捷开发的前提是在整个开发过程中, 事情变化很快,你需要经常不断的联系沟通以使每个人都能及时知道这些变化。

对开发人员来说,没有什么比看见自己的辛勤工作白白浪费更让人痛苦的了。 因此,开发人员能随时获取准确的高质量的应用系统的业务知识就显得很 重要了。

自适应过程

到目前为止,我谈到的适应性是指在一个开发项目中如何频繁地修改软件以适 应不断的需求变更。但是,还有另一种适应性,即是过程本身随着时间推移变 化。一个项目在开始时用一个适应性过程,不会到一年之后还在用这个过程。 随着时间的推移,开发团队会发现什么方式对他们的工作最好,然后改变过程 以适应之。

自适应的第一步是经常对过程进行总结检讨。一般来说,在每一次迭代结束后, 你可以问自己如下问题 〔 Norm Kerth〕:

  • 有哪些做的好的部分
  • 有哪些教训
  • 有哪些可以改进的部分
  • 有哪些没搞清楚的部分

 

这些问题会帮助你考虑在下一次迭代中如何对过程进行修正。这样,如果 开始时使用的过程有问题的话,随着项目的进行,该过程会得以逐步的完善, 以使其能更好地适合开发团队。

如果一个项目采用了自适应方法,则可以进一步在一个组织内引入这种方法。 自适应性导致的结果是你绝不能期待着在一个组织里只用一个过程。相反, 每个项目组不仅能选择他们自己的过程,并且还能随着项目的进行而调整 所用的过程。公开发表的过程和其他项目的经验都可以拿来作为参考和样本。 但是开发人员需根据手中项目的具体情况而对其加以调整,这也是开发人员 的专业职责。

敏捷开发的不同风格

‘敏捷’这个词是指软件开发的一种理念。好些个方法都可以归入敏捷型旗下, 如极限程序设计(XP),Scrum,精悍开发(Lean Development)等等。每种 方法都有自己特定的思路、社群和领军人物。当然,一个社群如果要宣称自己是 敏捷论者,它必须要遵循一些相同的原则。每个社群也从其他社群中借鉴相互的 思想与技术。也有许多人士在不同的社群间来来往往,因此把不同的思想传来播 去。所有这些都让敏捷社会成为一个复杂而动态的生态系统。

现在我已描出了我所定义的敏捷方法的总体图象,下面我要介绍一些特定的敏捷 方法及其社群。这里只是作一些概述,但我同时也给出了相关的参考资料,这样 你如果愿意的话,可以作进一步的探索。

在我给出更多的参考资料之前,最好在这里先给出一些关于敏捷方法的基本参考 材料。首先是Agile Alliance (敏捷联盟)网站,其设立的宗旨是鼓励与研究敏捷 方法。书籍方面我推荐Alistair CockburnJim Highsmith的著作。Craig Larman 的著作 有许多关于迭代开发的历史。关于我自己对敏捷方法的观点可参见我的网站的相关 文章和 博客

一下所列肯定是不完全的,这只是我个人的选择,它们是在过去十来年我最感兴趣 并影响我最深的一些敏捷方法。

敏捷宣言

敏捷一词是在2001被“劫持”的,一些新方法的代表人物们聚集一堂,交换思想, 其成果便是一份 敏捷软件开发宣言〔Manifesto for Agile Software Development〕

在这次会议之前,许多不同的社群都在发展着持相似的软件开发理念。大部分 (当然不是全部)的工作都是出自那些在OO软件开发圈内拥护迭代开发的人士。 本文初稿写于2000年,试图把这些方法归纳一下。那时这些方法还没有一个共同 的名称,但用“轻量”(lightweight)一词来描述这些方法日益见多。许多有关 人士认为这不是一个很恰当的词汇,因为它并没有精确地表达出这些方法的精髓。

2000年Kent Beck曾在Oregon主持过一次讨论会,主要是关于XP的(XP社群在那时 正吸引着大家的注意),但也有几位非XP人士参加,会上也讨论了更广泛一些的 议题。其中一个议题是,是让XP成为一个广泛的运动,或者还是一个具体的运动, 哪种情况对XP要好些。Kent还是希望一个更紧凑的XP社群。

2001年的这次讨论会,如果我没记错的话,首先是由Jim Highsmith和Rob Martin 发起,他们联络了他们认为在此领域持相似观念的人士,最后共有17位人士与会。 最初的相法是大家聚在一起能更好地了解他人的方法和途径。Robert Martin希望 会议能提出一份声明或宣言之类的文件,以便业界能在这些开发技术下联合起来。 我们也决定应该选择一个合适的词汇来涵盖这些不同的方法途径。

我们最后决定用“敏捷”(agile)一词来命名这类方法,并拟出了宣言的价值部分。 至于原则部分在这次会上也开始构想,但主要是在会后的wiki上完成的。

这次讨论会上的努力取得了极大的震撼效应,我想我们大家都对宣言所得到的注意 和肯定程度感到惊讶。尽管宣言并没有对敏捷作出非常准确的定义,但它的确提供 了一份有助于对敏捷开发进行深入探索的文件。在我们完成这份宣言不久,Jim Highsmith和 我在 SD Magazine发表了一篇文章对这份宣言提供了进一步的一些解释。

那年晚些时候,17位中的多数人又在OOPSLA 2001重新聚首,与会还有其他一些同行。 有人建议宣言的作者们应该进一步来推动敏捷运动,但作者们则认为他们只不过是 因缘际会而出席了那次敏捷讨论会并提出了那份宣言,他们决不能就此声称他们 拥有敏捷领域的领导权。我们已尽力帮助发动了这艘敏捷之船,现在应该让它随 这艘船上的船员们的意愿而行驶。这便是17位宣言作者们作为一个组织的使命的 完结。

大部分作者之后参加的一个主要活动是建立了 敏捷联盟(Agile Alliance)。这是一个非盈利性组织,其宗旨是推动与 研究敏捷方法。其他一些活动包括赞助在美国举行的年度大会。

XP(Extreme Programming -- 极限编程〕

在所有的1990年代末的早期敏捷型方法中,XP是最为引人瞩目的。从许多方面 看来,现在仍然如此。

XP根源于Smalltalk圈子,特别是Kent Beck和Ward Cunningham在(19)80年代末的 密切合作。90年代初,他们在一系列项目上的实践深化扩展了他们关于软件 开发应是适应性的、应以人为中心思想。

Kent在其后的项目咨询实践中继续发展了他的思想,特别是在1996年 春Chrysler C3 项目。该项目后来成了广为人知的XP的创生项目。他在 1997年左右开始使用“extreme programming”这个名称。 (C3也标志着我第一次接触XP,以及和Kent的友谊的开始。)

1990年代末,XP这个词被广为流传,最初是通过新闻组(newsgroups)和 Ward Cunningham的wiki来传播的。Kent和Ron Jeffries(C3项目中的同事) 在wiki上花了很多时间对XP的思想加以解释和辩论。最后在90年代 末00年代初出版了好几本书,对这种方法的种种方面加以了详细阐述。 最近的一些书大多是以Kent Beck的 白皮书(white book)为基础。该书的 第二版 在2004年出版,是对XP的再次阐述。

XP始于五条基本价值观(values):交流,反馈,简洁,勇气和尊重(Communication, Feedback, Simplicity, courage, and Respect)。在此基础上细化出了 十四条原则(principles)和二十四条实践法(practices)。其基本思想是: 实践是项目组的日常的具体活动,而价值观是根本性的知识和理念,其构成了 该方法基石。没有实践法的价值观是难于应用的,或失之于过于宽泛而不知从何 着手。没有价值观的实践法则是一堆杂乱无章的活动。价值观和实践法都是需要的, 但中间还有一个空档--而原则正是用来连接价值观和实践的。许多XP的实践法 都是以前就存在的并经过实践检验的,而常常被许多过程,包括那些计划型 过程,给忽略了。XP重新建立了这些准则,并把它们编织成了一个和谐的整体, 使得每一项准则都能在其他准则里得以强化。

XP有一个最具冲击力的,也是最初吸引我的特点,是它对测试的极端重视。 诚然,所有的过程都提到测试,但一般都不怎么强调。可是XP将测试作为 开发的基础,要求每个程序员写一段源码时都得写相应的测试码。这些测 试片段不断地积累并被整合到系统中。这样的过程会产生一个高度可靠的 建造平台,为进一步开发提供了良好的基础。这种方法常被描述成 Test Driven Development(TDD)(测试驱动开发),它对 许多不是完全采用XP的方法都有很大的影响。

关于XP有许多文献可读。不过,Kent Beck的白皮书从第一版到第二版的变化 可能会引起一些困惑。我上面说过,第二版是对XP的再次阐述,这里,XP 的方法是一样的,但第二版是用不同的风格来描述。第一版(四条价值观, 十二条实践法和一些很重要的却常被忽略的原则)已经对软件行业产生了 巨大的影响,许多对XP的介绍都是基于白皮书的第一版。你在阅读XP的资料时 你心里得清楚这一点,特别是那些2005前的资料。还有,许多网上关于XP 的介绍也是基于白皮书的第一版。

探求XP最合适的起点还是 白皮书的第二版。这本书阐述了 XP的背景以及实践,篇幅也很简短(160页)。Kent Beck在世纪之交还编辑了 一套用颜色标识的XP的书籍。如果一定要选一本的话,我推荐 紫色 的那本。不过,得记住象其他大多数资料一样,这本书也是基于白皮书的第一版。

网上大部分关于XP的介绍也是基于白皮书的第一版。我所知道的为数不多的基于 第二版的材料中,有一篇Michele Marchesi写的文章 “The New XP” ,作者曾在Sardinia主持过最初的一届XP大会。关于XP的讨论,可见 Yahoo上的 XP mail list

我对早期XP的参与以及和XP社群的友谊意味着我具有对XP特别的熟悉、喜爱和 偏好。我认为它的影响力来自于它把敏捷开发的原则和一套施行敏捷开发的 技术结合起来。许多关于敏捷的早期文章都忽略了后者,而质疑敏捷思想是否 可行。XP提供了一套工具使得敏捷性得以实现。

SCRUM

SCRUM是在1980和90年代从OO圈子里发展出来的一种高度迭代性的方法。 SCRUM的主要开发者有Ken Schwaber, Jeff Sutherland和Mike Beedle。

SCRUM的着重点是在软件开发的管理方面。它把一个项目分成若干个为期 三十天的迭代阶段,每一阶段称之为一“冲”(sprint〕。每天有一个短会, 称之为一个scrum,这样管理者能对项目有近距离的观察与控制。SCRUM对 工程实践方面强调少一些,许多人在开发中把SCRUM的项目管理和XP的工程 实践相结合。(其实XP的管理方法并非那么不同。)

Ken Schwaber是SCRUM的最为活跃的拥护者之一。你可从他的 网站得到更多的SCRUM 的资料。他的 著作可能是最好的入门参考材料。

水晶(Crystal)系列

Alistair Cockburn很长时间以来一直是敏捷开发界的主要代言人之一。 他发展出了一套水晶(Crystal)系列的的开发方法,它们可以在不同的项目中 加以裁剪。水晶之所以是个系列,是因为他相信不同类型的项目需要不同的方 法,这与两个因素有关:项目参与人数和出错的严重性。

所有水晶方法都有三个需考虑的优先因素(priorities):安全性(safety) (项目的结果),效率(efficiency),和习惯性(habitability)(即开发人员 多大程度上愿意使用水晶方法)。其他共同特征有:频繁发布,反思改进,紧密交流 (Frequent Delivery,Reflective Improvement, and Close Communication)。

习惯性(habitability)这个优先因素是水晶方法心理基础中的一个重要组成 部分。依我看来,Alistair是在寻找一个方法,它使用最少的过程(纪律性)而 依然能使项目成功,其基本假设是人的低纪律性是不可避免的。因此,Alistair 把水晶方法视为较XP的纪律性要低的方法,是用较低的效率以期获得更大的习惯性 而减少项目失败的可能。

尽管有Crystal网站,目前还没有对水晶系列完备的阐述。描述最详尽的一本书是 Crystal Clear (水晶般清晰)。另外,在Alistair网站的 wiki 上也可以找到水晶方法的若干材料。

 

相关环境驱动测试(Context Driven Testing)

敏捷开发运动最初是由软件开发人员来推动的。但是,参与软件开发的其他方面 的一些人士也受到这个运动的影响。一个明显的群体是测试人员,他们通常是生活 在由瀑布式开发所限定的世界里。一般来说,测试的作用是保证软件与开始的设计 相符合。而在敏捷世界里,测试人员的角色还很不清楚。

实际上,在测试圈内有好几位人士有相当一段时间一直在质疑这种主流的测试思维。 这导致了一个称之为“相关环境测试”(context driven testing)的群体。 对这个概念的最好的论述是“Lessons Learned in Software Testing这本书。 这个圈子在Web上也很活跃,你可以去看看这几位的网站, Brian Marick(他也是敏捷宣言的作者之一), Brett Pettichord, James Bach,和 Cem Kaner

Lean Development(精悍开发)

我记得几年前曾在软件开发大会(Software Development conference)上作过一个 关于敏捷方法的讲座,并与一为热心于此的女士比较了敏捷思想和制造业的lean运动 (lean movement)的相同点。Mary Poppendieck(和她的丈夫Tom)一直都是敏捷 的积极支持者,特别是一直在探讨lean production(精悍生产)和敏捷开发之间的重叠 之处和它们的相互启迪。

Lean movement(精悍生产运动)是由丰田公司(Toyta)Taiichi Ohno首创,并以 丰田生产系统(Toyota Production System)著称。精悍生产的理念对许多早期的 敏捷论者多有启发。Poppendiecks夫妇以探讨这两者如何互动而为人们所注意。 通常来说,我对这种类比持谨慎态度,因为正是工程领域中把设计和建造相分离这种 思想首先导致了软件开发中的混乱。但是,在精悍生产中还是有很多很有意思的思想。

更详细的信息可参见Poppendiecks夫妇的著作和他们的 网站

(Rational)Unified Process

另一个出自OO社群的广为人知的方法是 Rational Unified Process(有时也被称之为Unified Process)。提出RUP的最初 思路是要象UML统一建模语言那样,用UP来统一软件开发过程。因为RUP的出现几乎 是与敏捷方法同时,因此,关于它们是否兼容也有许多的讨论。

RUP是一个非常大的实践指引的集合。它实际上是个过程框架,而非一个 单一过程。它寻求的是提供一组软件开发共有的实践指引,让开发团队来从中 选择以为一个具体的项目所用。所以,使用RUP的第一步的结果就是定义出一个 具体的开发过程,用RUP的术语就是一个开发个例(development case)

RUP最主要的特征是用例驱动开发(Use Case Driven)(即,开发是以用户可见 的系统功能特征来驱动的),迭代,和以架构为中心(需要优先考虑的一点是, 尽早设计出一个架构以贯穿项目始终)。

我觉得RUP的问题是它的无限制的可变性。我曾看到RUP可以(从一个极端)被用成象 非常传统的“瀑布”式开发方式,到(另一个极端)被用得轻灵敏捷。我感到 特别忧虑的是有些人士把RUP推销成一个单一的过程,从而导致人们可以把使用的 任何一个过程都标成是RUP,这样RUP就变得毫无意义了。

尽管如此,在RUP社群内有些非常有影响力的人士极力主张用敏捷思维来使用RUP。 其中一位是Phillippe Kruchten,每次与他的会面都给我留下深刻印象,他的 著作是了解RUP的最好的一本入门书。另外, Craig Larman在关于OO开发的这本出色的 引论著作 中,阐述了用敏捷风格来使用RUP。

你是否应走向敏捷?

并非人人都能使用敏捷型方法。当你决定走这条路时,你得记住许多准则。 但是,我确切相信,这些新方法可被广泛的应用。只是考虑使用它们远远 不够,应该有更多的人来实践中运用它们。

在目前的软件开发中,多数方法仍是边写边改(code and fix〕,那么,引入 一些纪律约束肯定会比一片混乱要好。敏捷型途径的主要优点在于它比重型 方法的步骤要少得多。如果你已习惯于无过程,那么遵循简单过程应该比遵循 繁琐过程更容易一些。

对敏捷方法的初入门者而言,首要问题是从何着手。对任何新过程,你都需作 一番评价,这样你可看一看它是否适合你的环境。其实,我对采用任何新途径 的建议都是这样,这可回溯到我第一次讨论OO技术的时候。

第一步是要找到合适的项目来全面试验敏捷方法。因为敏捷方法的根本是 “面向人”(people-oriented)的,所以,你的团队应该是想要使用敏捷方法的。 这点很重要,因为一个勉勉强强的团队不仅很难在一起工作,更主要的是把一个 敏捷型方法强加给不愿意这样干的人是与敏捷方法的根本思想背道而驰的。

另外,让客户接受敏捷型方法也是非常有价值的。如果客户不合作,那你就不能 看到适应性过程的全面优势。尽管我这样说了,我们还是碰到一些客户,开始 不愿合作,但在开始后几个月中,随着他们对敏捷方法的理解而改变了他们的想法。

许多人声称敏捷方法不能用于大的项目。我们(ThoughtWorks)已成功地运行过 敏捷型项目,其项目组成员在100人左右,地域跨了几个洲。尽管这样,我还是 要建议从小的项目着手。不管怎样,大项目都要更复杂一些,所以最好是从一个 便于管理的小系统开始。

有人建议选择对业务影响小的项目开始,这样,如果出什么问题的话,造成的损失 也小一些。但是,一个不是那么重要的项目常常会使测试马马虎虎,因为大家对 测试结果不会太在意。我倒是建议人们选择一个项目,其重要性的压力在你能 轻松承受的基础上要大一些。

也许你能做的最重要的一件事是找到一位对敏捷方法有更多经验的人来帮助你学习 敏捷方法。任何人任何时候做任何一件新事情时都不可避免地会犯错误。找到一位 已经犯了很多错误的人能让你自己避免犯这些错误。一个优秀的指导者,其价值是 黄金等身的,对任何新技术来说,这种说法在某种程度上的确如此。当然,这种 说法有些自我推销之嫌,因为ThoughtWorks和我的许多朋友都从事敏捷方法的指导 服务。不过,我坚决认为找到一个良师是非常重要的,这个观点是不会改变的,

当你找到一位好的指导者之后,应该对他言听计从。要知道,浅尝辄止而又事后 诸葛是很容易的。我的经验表明,对于许多新技术,你一定要在付出了相当的 努力去试用了之后,你才能真正理解。有一个我听到的最好的例子,我们的一个 客户准备用两个月的时间来试验极限编程,他们明确表示,在此期间,他们会完全 按照指导者所说的去做,甚至他们认为很糟糕的做法。当试验期完成后,他们会停 下来再决定是否这样继续做下去,或是回到以前的老方法。(也许你会想知道他们 是否决定继续使用XP。)

关于敏捷方法还有个有待回答的问题,那就是它的边界条件在哪里。对于许多新技术 来说,一个普遍的问题是,你不知道它的边界条件在哪里,直到你越过了这些条件而 遭到失败。敏捷方法还是太年轻,我们还没有足够的积累以获得对边界条件的感觉。 另外,在软件开发中,一个项目是成功或是失败就不太好说,还有,当问题出现后, 由于有太多的可变因素,要找到问题的原因也非容易。所有这些因素都使确定边界 条件变的更加复杂。

那么,什么情况下你不应该用敏捷方法呢?我想,这主要是取决于人。如果有关人员 对敏捷方法所要求的密切的合作不感兴趣的话,那么,驱赶他们来做敏捷式开发会是 一场苦战。因此,我认为,你绝不能把敏捷方法强加给一个不想试用该方法的团队。

敏捷方法在过去十年中已积累了许多的经验,在ThoughWorks,我们总是会使用敏捷 方法,只要客户愿意,其实多数时候他们都是愿意的。我(和我的同事们)一直是 这种工作方式的热心者。

修改记录

  • 2005年12月:文章的全面修订,更新了敏捷方法的综述部分。
  • 2003年4月:更新了几个小节,增加了“测度的困难性”和“相关环境驱动测试(Context driven testing)”。
  • 2002年6月:更新参考材料。
  • 2001年11月:更新一些最近的参考材料。
  • 2001年3月: 加上关于“敏捷联盟”的内容。
  • 2000年12月:本文缩写发表于Software Development杂志。
  • 2000年11月:更新ASD部分并加上DSDM和RUP的章节。
  • 2000年7月: 初稿发于martinfowler.com。

译后注:

posted @ 2013-04-09 14:01  blockcipher  阅读(516)  评论(0编辑  收藏  举报