采用XP方法使软件项目获得更大成功的方法

采用XP方法使软件项目获得更大成功的方法

采用XP方法使软件项目获得更大成功

原著:Roy W. Miller 、Christopher T. Collins
改编:xuyeli

(本文转载自软件工程专家网www.21cmm.com)

 

使用面向对象编程变得空前普及。它使软件开发发生了某种程度上的变革,但最近的研究表明,有半数的软件开发项目滞后,而三分之一的项目则超出预算。问题不在于技术,而是开发软件所使用的方法。所谓的“轻量型”或“灵活”方式,与面向对象语言的威力和灵活性结合起来,提供了一种很有意思的解决方案。最常见的灵活方式称为极端编程(Extreme Programming)或者 XP,但许多人并不真正了解它。对软件项目使用 XP 可以大大增加成功的机会。本文提供了 XP 的概述,并解释了它为什么很重要 -- 不是传言,也没有骗局。

在过去的十年中,CEO 们在产生稳步增加的收入方面面临巨大的压力。他们通过在许多方面采取一系列举措来解决这一问题,例如缩小公司规模、外包、再工程、企业资源规划 (ERP) 等等。这些对低效率的解决措施让 S&P 500 中的许多企业在 90 年代末能够连续几年保持两位数的收入增长。但这种方式也带来了一些负面影响。

在 Gary Hamel 所著的 Leading the Revolution(请参阅参考资料)一书中,他声称已有一些迹象证明传统企业模式的优势已不那么明显。我们必须找到一些替代方法来为收入的持续增长提供动力。他建议唯一能让公司继续增长的办法是进行一次彻底的创新。我们认为在软件开发领域中尤其需要这样。

企业问题
如果使用标准软件开发方法,那么即使在常用的平台上进行开发,也要做好失望的准备。如图 1 所示,最近的研究表明,有一半项目将滞后,而三分之一的项目将超过预算。这一推测比 1979 年由美国总审计局的研究结果好不了多少。


采用XP方法使软件项目获得更大成功的方法

图 1. 软件项目成功和失败,过去和现在


如果我们希望这些数字有显著提高,则需要彻底创新的方法来开发软件。有两个主要因素影响现有的方法: 惧怕失败、对软件本质的误解。

没有人打算失败。具有讽刺意味的是为使失败最小化而创建的方法是失败的。对软件的误解是问题的根源。恐惧实际上只是一种症状。现有的方法是由那些有良好愿望但忘记了软件中的“软”的那些聪明人所创建的。他们假定开发软件就象造桥。因此他们从各种设计规范中借鉴了一些适用于“硬”物体(例如桥梁)的最优方法。结果是基于 Big Design Up-front (BDUF) 思想的反映迟钝的开发方法,软件不堪一击,人们无法使用它们。

〈一〉一种解决方案:灵活方法

最近发生了一些转变,从所谓的“重量型”方法转向了“轻量型”或“灵活”方法,例如 Crystal 方法、适应性软件开发和(当前最流行的)XP。所有这些过程都有这样一个事实,即需要人们共同来开发软件。成功的软件过程必须将人们的长处最大化,将他们的缺点最小化,因为优点和缺点毋庸质疑都存在。在我们看来,XP 最出色的地方在于它能够解决所有影响参加人员的互补力量。

XP 提供了十年来最大的一次机会,给软件开发过程带来彻底变革。就象 Peopleware 作家 Tom DeMarco 所说,“XP 是当今我们所处领域中最重要的一项运动。预计它对于目前一代的重要性就象 SEI 及其能力成熟度模型对上一代的重要性一样。”

XP 规定了一组核心价值和方法,可以让软件开发人员发挥他们的专长:编写代码。XP 消除了大多数重量型过程的不必要产物,通过减慢开发速度、耗费开发人员的精力(例如干特图、状态报告,以及多卷需求文档)从目标偏离。我们认识到一个称为“极端编程”的东西可能很难作为正式的开发过程推荐给管理层,但如果您的公司从事软件行业,您应该帮助管理层绕过其名称认识到 XP 可以提供的竞争优势。

Kent Beck 在他所著的 Extreme Programming Explained: Embrace Change 一书中概括了 XP 的核心价值(请参阅参考资料)。我们对它们进行了总结:

1)交流
项目的问题往往可以追溯到某人在某个时刻没有和其他人一起商量某些重要问题上。使用 XP,不交流是不可能的事。

2)简单
XP 建议您总是尽可能围绕过程和编写代码做最简单的事情。按照 Beck 的说法,“XP 就是打赌。它打赌今天最好做些简单的事...而不是做更复杂但可能永远也不会用到的事。”

3)反馈
更早和经常来自客户、团队和实际最终用户的具体反馈意见为您提供更多的机会来调整您的力量。反馈可以让您把握住正确的方向,少走弯路。

4)勇气
勇气存在于其它三个价值的环境中。它们相互支持。需要勇气来相信一路上具体反馈比预先知道每样事物来得更好。需要勇气来在可能暴露您的无知时与团队中其他人交流。需要勇气来使系统尽可能简单,将明天的决定推到明天做。而如果没有简单的系统、没有不断的交流来扩展知识、没有掌握方向所依赖的反馈,勇气也就失去了依靠。

XP 的方法将这些价值转换成开发人员每天应做的事情。这里没什么新鲜内容。多年以来,行业认识到 XP 方法是“最优方法”。实际上,XP 中的“极端”来自两方面:

XP 采取经过证明的业界最优方法并将其发挥到极致。

XP 将这些方法以某种方式进行结合,使它们产生的结果大于各部分的总和。

这是怎样的情景呢?代码复查是个好的做法,因此始终通过成对地编写代码来做到。测试也是个好的做法,因此总是通过在编写代码之前编写测试来做到。文档很少与代码保持一致,因此只做那些最需要的事,余下的部分则取决于明确编写的代码和测试。XP 不保证人们总做正确的事,但它允许人们这样做。它将这些“极端”方法以一种相互支持的方式结合起来,显著提高了速度和有效性。

〈二〉XP 的十二种方法

XP 的十二种方法(如图 2 所示)将其定义为规则。让我们仔细研究每一个方法来对“执行 XP”表示什么有个更全面的理解。

采用XP方法使软件项目获得更大成功的方法

图 2. XP 的十二种方法


1)规划策略
有些人会指责 XP 是一种美其名的剽窃,只是一群牛仔在没有任何规则的情况下将一个系统拼凑在一起。错。XP 是为数不多的几种承认您在开始时不可能事事通晓的方法之一。无论是用户还是开发人员都是随着项目的进展过程才逐步了解事物的。只有鼓励和信奉这种更改的方法才是有效方法。状态限定方法忽视更改。而 XP 则留心更改。它倾听所用的方法就是“规划策略”,一个由 Kent Beck 创造的概念。

这一方法背后的主要思想是迅速地制定粗略计划,然后随着事物的不断清晰来逐步完善。规划策略的产物包括:一堆索引卡,每一张都包含一个客户素材,这些素材驱动项目的迭代;以及对下一两个发行版的粗略计划,如 Kent Beck 和 Martin Fowler 在他们的 Planning Extreme Programming 中描述的那样(请参阅参考资料)。让这种形式的计划得以发挥作用的关键因素是让用户做企业决策,让开发小组做技术决策。如果没有这一前提,整个过程就会土崩瓦解。

开发小组要决定:估计开发一个素材要花多长时间 、使用各种技术选项所花费的成本 、团队组织 、每个素材的“风险” 、迭代中素材开发的顺序(先开发风险最大的那一个可以减轻风险)。
客户需要决定: 范围(一个发行版的素材和每一次迭代的素材) 、发行日期 、优先级(根据企业价值先开发哪些特性)规划经常发生。这样,在客户或开发人员学习新事物的同时,就为他们调整计划提供了频繁机会。

2)成对编程
使用 XP,成对的开发人员编写所有产品代码。这种方式听上去好象缺乏效率。Martin Fowler 说,“当人们说成对编程降低生产力时,我回答,‘那是因为大多数耗费时间的编程部分是靠输入来完成的。’”实际上,成对编程无论在经济还是其它方面都提供了许多好处: 所有设计决策都牵涉到至少两个人、至少有两个人熟悉系统的每一部分、几乎不可能出现两个人同时疏忽测试或其它任务、改变各对的组合在可以在团队范围内传播知识、代码总是由至少一人复查。

研究还显示成对的编程实际上比单独编程更有效(有关详细信息,请参阅参考资料中 Alistair Cockburn 和 Laurie Williams 所著的 The Costs and Benefits of Pair Programming)。

3)测试
在 XP 中有两种测试: 单元测试 、验收测试 。

开发人员在他们编写代码的同时编写单元测试。客户在他们定义了素材后编写验收测试。单元测试及时告诉开发人员系统在某一点上是否“工作”。验收测试告诉团队系统是否执行用户希望它执行的操作。

假设团队使用的是如 Java 这样的面向对象语言,开发人员在为一些方法编写代码之前为每种有可能失败的方法编写单元测试。然后他们编写足够的代码使之能通过测试。有时人们会发现这有点奇怪。答案很简单。编写测试首先为您提供:一组可能最完整的测试 、可能能工作的最简单的代码 、代码意图的明确景象 。

开发人员只有在通过所有单元测试后才可以将代码检入到源代码资源库中。单元测试使开发人员有信心相信他们的代码能够工作。这为其他开发人员留下线索,可以帮助他们理解最早的开发人员的意图(实际上,这是我们看到过的最好的文档)。单元测试还给了开发人员勇气重新划分代码,因为测试失败可以立刻告诉开发人员存在错误。应该将单元测试自动化,并提供明确的通过/失败结果。xUnit 框架(请参阅参考资料)做到的远不止这些,因此大多数 XP 小组都使用它们。

用户负责确保每个素材都有验收测试来确认它们。用户可以自己编写测试、可以征募组织中的其他成员(例如 QA 人员或业务分析员)编写它们,也可以将这两种方法结合起来。测试告诉他们系统是否具有应该具有的那些特性,以及是否可以正确工作。理想情况下,用户在迭代完成之前就应该写好迭代中那些素材的验收测试了。应该将验收测试自动化,并要经常运行来确保开发人员在实现新特性时没有破坏任何现有的特性。通常情况下,客户需要来自开发团队的某些帮助来编写验收测试。我们对一个项目开发一个可重用的自动验收测试框架,可以让用户在简单编辑器中输入他们的输入和所期望的输出。框架将输入转换成 XML 文件、运行文件中的测试,然后为每个测试显示“通过”或“失败”。客户喜欢这一做法。

不是所有验收测试都必须在所有情况下通过。问题是验收测试帮助客户衡量项目“完成”的情况如何。它们还可以让客户获悉有关某些事物是否可以发行的决定。

4)重新划分
重新划分是在不更改功能性的前提下对代码加以改进。XP 小组在进行重新划分时毫不手软。

开发人员重新划分有两个重要时机:实现特性之前和之后。开发人员尝试确定更改现有代码是否可以让新特性的开发更容易。他们查看刚刚写好的代码,看是否有方法可以对它进行简化。例如,如果他们认为有抽象的机会,就会进行重新划分来从具体实现中除去重复的代码。

XP 建议您应该编写可能运行的最简单的代码,但同时也建议您应该不断学习。重新划分让您将学到的知识加入到代码中,同时又不会破坏测试。它使您的代码简练。这意味着它可以存在相当长的时间、为以后的开发人员引入更少问题,并为他们指引正确的方向。

5)简单的设计
XP 的诽谤者说该过程忽略了设计。事实不是这样。问题是重量型方法建议您做的不过是提前完成大部分琐碎的设计任务。这就象是拍一张静态的地平线的照片,静止不动,然后尝试画一张如何到达那里的完美的地图。XP 说设计不应该在事物将保持不变的前提下预先仓促进行。XP 认为设计非常重要,因此应该是一个持续的事务。我们总是先尝试使用能够工作的最简单的设计,然后随着现实的不断显现来更改它。

什么是可能工作的最简单的设计?它是符合以下条件的设计(感谢 Kent Beck 为我们一一列出): 运行所有测试 、不包含重复代码 、明确陈述程序员对所有代码的意图 、包含尽可能最少的类和方法 。

对简单设计的需求并不是说所有设计都很小,也不表示它们是无足轻重的。它们只不过需要尽可能简单,但是仍能工作。不要包括不使用的额外特性。我们称这样的事物为 YAGNI,表示“您将不需要它(You Aren't Going to Need It)。”不要让 YAGNI 破坏您成功的机会。

6)集合体代码所有权
小组中的任何人都应该有权对代码进行更改来改进它。每个人都拥有全部代码,这意味着每个人都对它负责。这种技术可以让人们对部分代码进行必要的更改而不用经过代码拥有者个人的瓶颈。每个人都负责这一事实消除了无代码所有权所带来的混乱。

“每人拥有所有代码”与“没人拥有代码”的说法并不一样。没人拥有代码时,人们可以随处进行破坏而不必负任何责任。而 XP 说,“如果是您破坏的,应该您来弥补。”我们有一些必须在每次集成之前和之后运行的单元测试。如果您破坏了某些事物,您要负责进行修补,无论它位于代码的哪一部分。这需要极端规则。可能这是名称中带有“极端”的另一个原因。

7)持续的集成
经常进行代码集成可以帮助您避免集成梦魇。XP 团队在一天中集成了代码几次,每次都在所有单元测试对系统运行后执行。

传统方法工作方式如下:编写大量代码后执行一次大爆炸式的集成,然后花费相当长的时间来改正问题。这种笨拙的形式的确使项目速度减缓。大爆炸式的集成给团队立即带来大量问题,并且这些问题通常都有几百种可能的原因。如果经常进行集成,任何特定集成失败的原因都会非常明显(以前运行过测试,因此错误一定是新事物犯下的)。使用这种方法,当遇到问题时,可能的原因就相当有限。修改起来更容易,花的时间少得多,使团队保持最快速度前进。

8)现场客户
要使功能最理想,XP 小组需要在现场有一位客户来明确素材,并做出重要的企业决策。开发人员是不允许单独做这些事情的。让客户随时在场可以消除开发人员等待决策时出现的瓶颈。

XP 不会假装素材卡是开发人员交付必要代码所需的唯一指示。素材是对以后在客户和开发人员之间填写细节的对话的一项承诺。与将所有要求写在一个静态文档中不同,其思想是进行面对面的交流,减少产生误解的机会。

我们发现让客户在现场是可能最好的一种情形,但这不是解决问题的唯一方案。底线是客户必须随时在需要回答问题和根据企业价值为团队提供指示时有空。如果客户并非在现场专职陪伴团队的情况下就能做到这些,那很好。如果能和团队待在一起,这会更方便,但只是建议而已。

9)小发行版
发行版应该尽可能地小,同时仍然提供足够的企业价值以证明它们值得。

只要觉得有意义就可以发布系统。这样就尽可能早为用户提供了价值(请记住,今天的钱比明天的钱来得值钱)。小发行版将为开发人员提供具体的反馈意见,告诉他们哪些符合客户需要,哪些不符合客户需要。然后,小组可以将这些经验教训包括在其下一发行版的规划中。

10)一周 40 小时
Kent Beck 说他希望“...每天早晨都感到有活力有激情,每天晚上都感到疲惫而满足。”一周 40 小时工作可以让您做到这一点。确切的小时数并不重要,重要的是原则。长时间地持续工作会扼杀工作绩效。疲劳的开发人员会犯更多错误,从长期来说,将比按“正常”时间表进行的开发慢得多。

即使开发人员可以在长时间很好工作,这也不意味着他们应该这样。最终他们会厌倦,会离开他们的工作,或者产生影响他们工作绩效的非工作问题。如果您打乱了人们的生活,将会尝到它所带来的恶果。加班并不是解决项目问题的答案。实际上,它是更大问题的症状。如果您要走向灭亡,就无药可救了。

11)编码标准
拥有编码标准有两个目的:a.防止团队被一些例如事物没有以最大速度发展这种无关紧要的愚蠢争论搞得不知所措;b.它支持其它方法。

如果没有编码标准,重新划分代码会更加困难,按应当的频度交换对更困难,快速前进也更困难。目标应该是团队中没有人辨认得出是谁写的哪一部分代码。以团队为单位对某一标准达成协议,然后遵守这一标准。目标不是创建一个事无巨细的规则列表,而是提供将确保您的代码可以清晰交流的指导方针。编码标准开始时应该很简单,然后根据团队经验逐步进化。不要预先花费太多时间。创建能够工作的最简单标准,然后逐步发展。

12)系统比喻
体系结构是做什么用的?它提供了系统各种组件以及它们是如何交互的画面 -- 一种映射,可以让开发人员了解新的代码部分适合放在哪里。

XP 中的系统比喻与大多数方法称作的体系结构差不多。比喻为团队提供了一致的画面,他们可以用它来描述现有系统的工作方式、新部件适合的位置,以及它们应该采取的形式。

重要的是要记住,关键要让每个人理解系统是如何组合在一起的,而不是美丽的比喻。有时您就是无法想到一个好的比喻。想到时就太好了。

〈三〉一起工作的方法

整体大于各个部分之和。您可以实现单一方法或一小部分方法,比不使用任何方法得到更大收益。但您只能在实现所有方法的情况下获得最大收益,因为它们的力量来自它们之间的交互。

最初时按照书籍来执行 XP,作为基准。一旦理解了如何进行交互,就拥有了将它们适应于自身环境所需的知识。请记住,“进行 XP”不是目的,而是到达终点的一种手段。目标是快速地开发高级软件。如果您的过程有一些变异,已称不上是在进行 XP,但结果仍能让您战胜所有竞争对手,您已经成功了。

〈四〉为什么 XP 很重要

坦率地说,XP(或者任何其它灵活方法)根本就不重要。它能够产生的结果才是关键。如果如 XP 这样的灵活方式可以帮助您更快地开发更好的软件而少受痛苦,那么它值得考虑。

还记得我们在这篇文章开始时提到的那些令人生畏的数字吗?我们相信使用 XP 开发面向对象软件可以有机会将它们变得更好。目前我们的经验已经证实了这一信念。

〈五〉参考资料

在 RoleModel Software 的 XP Portal 中了解有关 XP 的详细信息。
可以在 Alistair Cockburn 和 Laurie Williams (XP2000 submission, 2000) 所著的 The Costs and Benefits of Pair Programming 中了解到有关成对编程所具有的经济方面的意义。
在 Pairprogramming.com 上可以知道成对编程的常规详细信息。
下载 xUnit 测试工具。
如果您希望了解有关 XP 的详细信息,请务必选取一本本书中引用的书籍:
Planning Extreme Programming,由 Kent Beck 和 Martin Fowler 著 (Addison-Wesley, 2000)
Extreme Programming Explained: Embrace Change,由 Kent Beck 著 (Addison-Wesley, 1999)
Leading the Revolution 由 Gary Hamel 著 (Harvard Business School, 2000)
Jeff Canna 有关单元和功能测试的文章 (developerWorks,2001 年 3 月)将 XP 哲学用在测试上。