UML软件工程组织
|
新方法学 |
Martin
Fowler Chief Scientist, ThoughtWorks |
最近一次主要修改: 2003年4月 过去几年中兴起的敏捷型(agile〕(也被称之为“轻量型”,lightweight) 的软件开发方法,以矫正官僚繁琐过程、许可对过程进行自主调整为特征, 在软件业引起了极大的兴趣。在这篇文章里,我将探索敏捷型方法的合理性, 着重点并不是放在其“轻重”上,而是于它们的适应性(adaptive〕性质 和以人优先的理念。我在本文也简要介绍了一些敏捷型方法并给出了进一 步的参考材料。另外,我还提出了一些你在决定是否要走这条刚踏出来的 敏捷之路时需考虑的因素。 从无、到繁重、再到敏捷多数软件开发仍然是一个显得混乱的活动,即典型的“边写边改” (code and fix〕。设计过程充斥着短期的、即时的决定,而无完整的规划。 这种模式对小系统开发其实很管用,但是当系统变得越大越复杂时,要想加 入新的功能就越来越困难。同时错误故障越来越多,越来越难于排除。一个典 型的标志就是当系统功能完成后有一个很长的测试阶段,有时甚至有遥遥无期 之感,从而对项目的完成产生严重的影响。 我们使用这种开发模式已有很长时间了,不过我们实际上也有另外一种选择, 那就是“正规方法”(methodology〕。这些方法对开发过程有着严格而详 尽的规定,以期使软件开发更有可预设性并提高效率,这种思路是借鉴了其他 工程领域的实践 - 因此我把它们称为工程方法(engineering methodologies)。 工程方法已存在了很长时间了,但是没有取得令人瞩目的成功,甚至就 没怎么引起人们的注意。对这些方法最常听见的批评就是它们的官僚繁琐, 要是按照它的要求来,那有做太多的事情需要做,而延缓整个开发进程。 作为对这些方法的反叛,在过去几年中出现了一类新方法。它们在一段时间里 被称为“轻量型”(lightweight)方法,但现在有了一个广为接受的的名称, 敏捷型方法(agile methodologies)。对许多人来说,这类方法 的吸引之处在于对繁文缛节的官僚过程的反叛。它们在无过程和过于繁琐的过程 中达到了一种平衡,使得能以不多的步骤过程获取较满意的结果。 敏捷型与工程型方法有一些显著的区别。其中一个显而易见的不同反映在文档 上。敏捷型不是很面向文档,对于一项任务,它们通常只要求尽可能少的文档。 从许多方面来看,它们更象是“面向源码”(code-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)。通常一个敏捷方法是固定时间和价格,而让范围能够 可控制地变化。 在适应性过程中,客户实际上能够对软件开发过程进行很深入细微的控制。在 每一个迭代阶段中,他们都能检查开发进度,也能变更软件开发方向。这导致 了与软件开发者更密切的关系,或曰真正的商业伙伴关系。但并不是每一个客户, 也并不是每一个开发商都准备接受这种程度的介入,不过如要让适应性过程能 很好工作,这种合作程度是基本的要求。 这种开发方式可以给客户带来很多的益处。首先,这种开发的“回应性” (responsive)很好的。一个可用的,尽管是很小的系统能够尽早投入使用。 客户可以根据实际使用情况,以及变更了的需求,来及时改变一些系统功能。 这样一种方式能够更真实地反映出项目的实际状态。可预见性过程的问题是: 项目的质量是根据与计划的一致性来衡量的。当实际情况与计划脱节时,人们 很难提出来。一般的结果是在项目的后期出现进度上的大滑坡。 在敏捷型的项目中,每一个周期都对计划进行评审。如果有什么糟糕的事情 的话,它也会早点被发现,因此仍然会有时间来解决。的确,这种风险控制 是迭代式开发的一个关键优点。而敏捷型开发更进了一步,因为它的周期很 短,同时它也把这些变化看作是机会。 这点对于定义什么是成功项目有重要的意义。预见性项目是否成功是由它是否 很好地按计划执行来衡量的。一个项目如果在规定的时间和预算内完成,那 就是成功的。对于敏捷型环境而言,这种衡量是没有意义的。对于敏捷型 项目实践者来说,最重要的是商业价值(business value)- 客户得到的 软件的价值是否大于他们的投入。一个好的预见性项目是依计划而行,而一个 好的敏捷型项目会建造出一个与最初计划不太一样却是更好的软件。 把人放在第一位实施一个适应性过程并不容易,特别是它要求一组高效的开发人员。高效既 体现在高素质的个体,也体现在有能让团队协调一致的工作方式。这里有一 个有趣的和谐:并非只是适应性过程需要强的团队,多数优秀的开发人 员也愿意采用适应性过程。 可兼容性程序插件传统正规方法的目标之一是发展出这样一种过程,使得一个项目的参与人员 成为可替代的部件。这样的一种过程将人看成是一种资源,他们具有不同的 角色,如一个分析员,一些程序员,测试员及一个管理人员。个体是不重要的, 只有角色才是重要的。这样一来,在你计划一个项目时,你并不在乎你能得到哪个分 析员,哪些测试员,你只需关心你可得到多少,知道资源数量会如何影响你 的计划。 但这有一个关键问题:参与软件开发的人员是可替代的部件吗?敏捷型方法 的一个重要特征就是拒绝这种观点。 也许最明确地反对这种观点的当数Alistair Cockburn. 在他的论文 “软件开发中人是非线性,一阶的部件”中,他指出可预见性软件开发过程要求 “部件”的行为也是可预见性的。 但是,人并非可预见性的部件。更进一步,他对软件项目的研究导致了如下结论: 人是软件开发中最重要的因素。 在本文的标题里,我将人称为“部件”。(传统〕过程/方法就是这样看待 人的。这种观点的错误在于没有看到“人”是非常可变的和非线性的, 不同的个体具备特有的成功或失败模式。那些因素是一阶的,不可忽略的。 一种过程或方法的设计者如不能充分考虑到这些因素,那麽其后果就是项目 的无计划轨迹。就象我们经常看到的那样。 Cockburn是最鲜明地主张在软件开发中应以人为中心,其实这种概念在许多软 件行业的有识人士中已是共识。问题在于所使用的方法是与这种理念背道 而驰的。 这造成了一个很强的正反馈机制。如果你期望你的开发人员是可互替 的编程插件,则你不会去试着把他们看成是不同的个体。这会降低士气(和生 产率〕,并使优秀的人才跳到一个能发挥其个性特长的地方,最后你倒是得到 你所需要的:可互替的编程插件。 作出使人优先的决定是件大事,它需要很大的决心来推行。把人作为资源的思想 在工商界是根深蒂固的,其根源可追溯到 泰勒的“科学管理”方法。当管理一个 工厂时,这种泰勒主义途径是有效的。但是对有着高度创造性和专业性的工作, 我相信软件开发当属此类,泰勒主义并不适用(事实上现代制造业也在脱离 泰勒主义模式〕。 程序员是负责任的专业人员泰勒主义的一个关键的理念是认为干活的人并非是那些 知道怎样才能把这件活干的好的人。在工厂中可能是这样,原因是许多工厂里 的普通工人并非是最具聪明才智和最富创造力的人员。另一个原因也许是由于 管理层和工人的的工资悬殊太大而导致的关系紧张。 历史证明这种情形在软件开发中是不存在的。不断有优秀人才被吸引到软件行 业中,吸引他们的既有耀眼的光芒也有丰厚的回报(正是这两样诱使我离开电子 工程〕。其他一些福利如对公司的股份持有使得程序员的利益与公司紧联在一 起。 〔可能还有一个“产生”(generational)效应。一些所见所闻让我想 到是否在过去十来年中有很多的优秀人才转入软件行业。如果是这样,这可能 是当今年轻人崇尚IT业的原因,就象其他时尚一样,其后总有一些实在 的理由。〕 如果你想聘到并留住优秀人才,你得认识到他们是有能力的专业人员。因此, 他们最有资格决定如何干好他们的技术工作。泰勒主义让计划部门来决定如 何干好一件工作的作法只有当计划者比实际操作者更能知道怎样作时才有效。 如果你拥有优秀的、自觉自励的员工,那么这点并不成立。 面向人的过程的管理敏捷型过程中“以人为本”的理念可以有不同的表现,这会导致不同的效果, 而并非所有结果都是完全一致的。 实施敏捷型过程的一个关键之处是让大家接受一个过程而非强加一个过程。 通常软件开发的的过程是由 管理人员决定的,因此这样的过程经常受到抵制,特别是如果管理人员已脱离 实际的开发活动很长时间了。而接受一个过程需要一种“自愿致力” (commitment),这样大家就能以积极的态度参与进来。 这样导致了一个有趣的结果,即只有开发人员他们自己才能选择并遵循一个适 应性过程。这一点在XP中特别明显,因为这需要很强的自律性来运行这个过程。 作为一个互补,Crystal(水晶系列〕过程则只要求最少的自律。 另一点是开发人员必须有权作技术方面的所有决定。XP非常强调这一点。 在前期计划中,它就说明只有开发人员才能估算干一件工作所需的时间。 对许多管理人员来说,这样形式的技术领导是一个极大的转变。这种途径要求 分担责任,即开发人员和管理人员在一个软件项目的领导方面有同等的地位。 注意我说的同等。管理人员仍然扮演着他们的角色,但需认识并尊重开发 人员的专业知识。 之所以强调开发人员的作用,一个重要的原因是IT行业的技术变化速度非常之快。 今天的新技术可能几 年后就过时了。这种情况完全不同于其他行业。即使管理层里的以前干技术的人 都要认识到进入管理层意味着他们的技术技能会很快消失。因此必须信任和依靠 当前的开发人员。 测度的困难性如果有一个过程,规定工作应该如何来做的人不是具体去干的人,那么你需要一些 方法来测度干工作的人是否工作有效。在“科学管理”中,有种强烈的力量驱使着 发展出客观性方法来测度人们的工作输出。 这与软件特别有关,但是要测度软件是非常困难的。尽管人们已经尽了很大的努力, 我们仍然不能对软件的一些很简单方面进行测度,如生产率。如果没有一套有效的 测度方法,任何外部的控制都会是困难的(doomed)。 不存在一套有效的测度方法而要在管理中引入测度将会导致管理本身出问题。关于这点, Robert Austin有段出色的讨论。他指出,当进行测度时,你必须要获取影响这种 测度的所有重要因素。任何缺失都将不可避免地使得具体干工作的人改变 他们的工作方式以获得最好的测度成绩,甚至于那样会明显地降低他们真正的工作 有效性。这种测度的“失效”(dynsfunction)正是基于测度的管理方法的 致命之处(Achilles heel,即阿其里斯的脚踝)。 Austin的结论是你得在这两种方法中作选择:基于测度的管理,或是“委托式” (delegatory)管理(干工作的人决定该怎么干)。基于测度的管理是非常适合 简单的、重复性的工作,知识要求低并且易于测度输出 -- 这恰恰与软件开发 相反。 关键之处是传统方法假设的前提是基于测度的管理是最有效的管理方式。而 敏捷开发者则认为软件开发的特性会使得基于测度的管理导致非常高度的测度 “失效”(dysfunction)。实际上使用委托式的管理方式要有效得 多,这正是敏捷论者所持观点的中心所在。 业务专家的引领作用(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在(19)80年代末的 密切合作。90年代初,他们在一系列项目上的实践深化扩展了他们关于软件 开发应是适应性的、应以人为中心思想。 从非正式的、探索性的实践到形成系统化的正规方法的关键一步是在1996年 春。Kent被邀对Chrysler的一个工资管理项目(C3〕的开发进度进行审核。 该项目由一个签约公司用Smalltalk开发,正处于困境之中。由于源码质量 低劣,Kent建议推倒重来。该项目然后在他的领导下从头开始并成了早期 XP的旗舰和培训基地。 C3的第一期系统在1997年初投入运行。项目继续进行了一段时间后,遇到 了麻烦,导致了在1999年开发计划被撤销。(这也证明了XP并不是成功的保证) XP的四条基本价值原则是:交流,反馈,简洁和勇气。在此基础上建立了 十多条XP项目应遵循的实践准则。其实,许多准则是以前就存在的并经过实 践检验的,而常常被忽略了的。XP重新建立了这些准则,并把它们编织成 了一个和谐的整体,使得每一项准则都能在其他准则里得以强化。 XP有一个最具冲击力的,也是最初吸引我的特点,是它对测试的极端重视。 诚然,所有的过程都提到测试,但一般都不怎么强调。可是XP将测试作为 开发的基础,要求每个程序员写一段源码时都得写相应的测试码。这些测 试片段不断地积累并被整合到系统中。这样的过程会产生一个高度可靠的 建造平台,为进一步开发提供了良好的基础。 在此基础上XP建立了一个渐进型的开发过程,它依赖于每次迭代时对源码 的重整(refactoring〕。所有的设计都是围绕着当前这次迭代,而不管将 来的需求。这种设计过程的结果是“纪律性”与“适应性”的高度统一, 使得XP在适应性方法中成为发展的最好的一种方法。 XP产生了一批领军人物,许多是从C3项目中出来的。关于XP有许多文献可 读。Kent Beck写的 Extreme Programming Explained, 是一篇XP的宣言,它阐述了隐藏在XP后面的理念。此书对有心于XP并致 力于将其发扬光大者提供了充足的说明和解释。过去两年里也出版了一 批“多姿多彩”的XP书籍,但多数都很相似,主要是从一些XP早期的实 践者们的角度上描述了XP的整个过程。 除了书之外,还有不少网上资源。如果你想找到更有结构性的材 料,你最好访问两位C3成员的网站:Ron Jefferies的 xProgramming.com 和Don Wells的 extremeProgramming.org。 许多XP早期的倡导和发展可在Ward Cunningham的 wiki web (合作写作〕中找到。wiki是个令人着迷的地方,尽 管它的漫游性质常令人身不由己地陷入其中。 XP讨论组〔xp discussion egroup〕也很有意思。 还有一篇很有意思的文章从(XP圈)“外面”来审视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也费了不少笔墨强调每次迭代后的总结回顾,因而鼓励过程本身的 自我完善。他的理由是迭代式开发是用来尽早发现问题并解决之。这样就更 加强调了开发人员要随时观察他们所用的过程,并随着项目的进行而调整。 开放式源码看到这个标题你可能会有些意外。毕竟,开放式源码(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把他的工作集中放在适应性开发的难点上, 特别是如何在一个项目中增强合作和学习。基本上说,他的这本书 是侧重于“软”方法,这样对那些从开发实践中提炼出来的方法如XP,FDD 和水晶系列来说,这本书将是一个很有益的互补。 SCRUMSCRUM在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的很好的综述。 Scrum也有一个 Yahoo讨论组. 功用驱动开发方法(FDD--Feature Driven Development〕FDD是由Jeff De Luca和OO大师Peter Coad提出来的。象其他方法一样, 它致力于短时的迭代阶段和可见可用的功能。在FDD中,一个迭代周期 一般是两周。 FDD有以下五项任务:
头三项在项目开始时完成,后两项在每一次迭代周期时都要做。每一项 任务又可进一步分解并制订出相应的检验准则。 在FDD中,编程开发人员分成两类:首席程序员和“类”程序员(class owner〕。首席程序员是最富有经验的开发人员,他们负责开发实现 系统的各项功能。对每一项功能,首席程序员要定出需要哪些类(class〕 来实现这项功能,并召集“类”程序员们组成一个针对这项功能的开发 组。首席程序员作为协调者,设计者和指导者,而“类”程序员则主要 作源码编写。 关于FDD的文档资料比较少。直到最近终于有了一本全面 论述FDD的著作。FDD 的主要提出者Jeff De Luca现已建立了一个 FDD门户网站, 收录了一些文章、笔记和讨论。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〔软件开发杂志〕有一篇关于 宣言的评注与解释的文章。 当然,宣言只是一份发表的文件,是一个让有着共同理念的人们的聚集点。这个 努力的另一个成果是建立了一个 敏捷联盟。敏捷联盟是个 非盈利性组织,其宗旨是推广敏捷型方法的知识和促进这方面的讨论。许多 我已提到的敏捷方法的领军人物也都是这个联盟的成员和领导者。 相关环境驱动测试(Context Driven Testing)敏捷开发运动最初是由软件开发人员来推动的。但是,参与软件开发的其他方面 的一些人士也受到这个运动的影响。一个明显的群体是测试人员,他们通常是生活 在由瀑布式开发所限定的世界里。一般来说,测试的作用是保证软件与开始的设计 相符合。而在敏捷世界里,测试人员的角色还很不清楚。 实际上,在测试圈内有好几位人士有相当一段时间一直在质疑这种主流的测试思维。 这导致了一个称之为“相关环境测试”(context driven testing)的群体。 对这个概念的最好的论述是 “Lessons Learned in Software Testing这本书。 这个圈子在Web上也很活跃,你可以去看看这几位的网站, Brian Marick(他也是敏捷宣言的作者之一), Brett Pettichord, James Bach,和 Cem Kaner。 RUP是一种敏捷型方法吗?当我们开始讨论OO领域的方法时,不可避免地会碰到 RUP(Rational Unified Process〕。该过程由Philippe Kruchten, Ivar Jacobson以及Rational公司 的其他一些人士开发,主要是作为一个与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的工作,将对软件开发有着重要的影响和作用。 其他参考材料最近,有两本好书出版,分别由 Alistair Cockburn 和 Jim Highsmith所著,他们在书中广泛地讨论了敏捷开发的方方面面。 关于敏捷型方法有不少文章和讨论组,它们可能不会提供完整的方法,但可以 给你一个窗口以观察这个正兴起的领域在如何发展。 程序设计的模式语言(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〕,那么,引入 一些纪律约束肯定会比一片混乱要好。敏捷型途径的主要优点在于它比重型 方法的步骤要少得多。如果你已习惯于无过程,那么遵循简单过程应该比遵循 繁琐过程更容易一些。 这些新方法的一个主要局限是如何对付较大的项目组。象其他许多新方法一样, 这些敏捷型方法也是愿意先在小规模上使用,而通常它们被提出来时的重心 也是放在小规模的项目组上。XP明确说明它适合于最多20人的项目组。这里 值得一提的是,许多软件项目组可以减少人数而不会减少总体的生产率。 其他敏捷型方法试图能用在大一些的团队。FDD最初是为50人左右的项目设计 的。ThoughtWorks曾在三个大陆(洲)上使用过类似XP的方法,项目组成员 是100人左右。Scrum也在类似规模的项目中使用过。 这篇文章至少清楚地传递了这样一个信息,就是适应性方法对需求不确定或常 常变更的情形是有效的。如果你没有稳定的需求,那么你就不可能进行稳定的 设计并遵循一个计划好了的过程。这种情况下,适应性过程可能感觉上不太舒 服,但实践上会更有效。通常来说,使用适应性方法最大的障碍来自客户。我认 为,重要的一点是让客户理解在一个需求不断变更的环境中,遵循可预设性过程 对他们是有风险的,同样对开发方也是有风险的。 如果你要采用适应性方法,你需要信任你的开发人员,并让他们参与(技术〕 决策。适配性过程的成功依赖于你对你的开发人员的信任。如果你认为你的开 发人员素质不够,那么你应采用可预设性途径。 总结一下,如下的因素建议你采用适应性过程:
而如下这些因素则建议你使用可预见性过程:
鸣谢本文得益于许多朋友的意见,恕难一一列出。但是,我要特别感谢Marc Balcer, Kent Beck,Alistair Cockburn,Ward Cunningham,Bill Kimmel 和Frank Westphal。 请记住这是一篇不断改进的网络文章。我将附上主要修改记录,而小改动将不作记录。 修改记录
译后注:我在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〕的沟通特别 频繁。读了这篇文章后,我觉得它能够让人从一个比较广阔而系统的角度来 考察一个迭代式项目的运作。 原文初期是以“lightweight”来指称新方法的,主要是针对传统的 “重型”方法。Agile Alliance决定用agile来指称这些新方法后,原文中的 “lightweight”改成了“agile”。agile本意“敏捷”、“灵动”、“快 速”。译文中原译为“轻灵”,而现在“敏捷”似乎已成标准译法,因此也 改成“敏捷”。 诚如作者所言,这是一篇不断改进的网络文章。我将尽力随原文的更新而及时 更新译文。此译文中如有所译不当之处,望诸位同行不吝赐教。 |
版权所有:UML软件工程组织 |