作者:Amr Elssamadisy 著,simaetin 译
本文选自:UMLCHINA
2002年05月13日
我们在ThoughtWorks这样的大型项目中应用XP方法的时间超过了15个月。这个项目开始于三年前,那时它有大量的需求文档和几个独立的功能小组。从2000年1月起,我们决定应用XP,虽然当时我们已经知道XP并不适用于大型项目。那时,我们需要向客户提交功能演示,并要通过提交一个工作子集而不仅仅是原型来赢得他们的信心(我们在团队中有超过25名开发人员和大约15名分析员)。但我们并未准备好功能,各个组都使用自己的代码框架,一个完整的应用无从谈起。简短地说,就是客户想要看到点什么,但我们还没有真正的功能。应该说开发的第一迭代期是成功的:我们给客户提交了一个真正的应用子集。成功的首要原因是我们让来自Asset,
AR 和GUI组从事不同工作的开发者融合在一起。当然,其间也有"成长的烦恼":在分析员和开发者之间发生某些个人冲突,但我们成功跨越了这些障碍。那时一切都很美好:我们以飞快的速度成功地提交了功能演示,但随着时间的流逝和项目的继续,有些事情却不如我们所愿。这就是这篇文章要讲述的内容:我们真正的收获在"蜜月"期后,关于我们如何在一年半中管理一个50人的项目开发并及时完成阶段性的提交(尽管有时并不成功),关于我们经历的痛苦,我们后续的工作,我们最终学到的以及作为改进要用到下一个项目中的经验。
首先,我们给出我们开始的状况:15个月前我们是如何应用XP的,然后展示我们现在的XP应用情况。也就是说,下面将讨论我们改变技术的原因。这是一个自然选择的过程,它剔除了许多不好的想法,或把它们改造成更有效的方法,使之更适于大型项目。最后我们将总结并给出在大型项目中使用XP的谨慎建议。
大型项目中XP的元素
好吧,让我们来进入正题。我们开发和分析的队伍由大约35名开发人员、15名分析人员和10名QA组成。开发人员依赖分析人员作为项目的客户。尽管有实际的客户,分析人员还是要协同工作以便有选择地做出客户决策。下表演示了[1]所讨论的XP基本元素并简要介绍了这些方面如何应用到项目的各个阶段。我们用这个表来分析我们团队自然选择的实践,以及书本上的XP如何应用到一个超过50人的大型项目中。
计划 | 提交周期 | 比喻 | 设计的简单性 | 测试 | 重构 | |
1/2000 | 大跨度的迭代计划会议。开发和分析组的全部成员整天在一起讨论新的故事卡片和预估。大多数开发者签入(sign up)新的功能。 | 1个月 | 无 | 转变已有的代码基准。已有的代码依然复杂,但新的代码要尽可能简单。这个阶段包括抛弃老的代码和重写那些"今后可能会被用到"的功能代码。 | 单元测试开始于一些新的代码。推动建立一个大的测试基准。QA做所有的功能测试并有权留弃故事卡片。 | 对于旧有代码,如有必要就进行重构。 |
7/2000 | 基本同1/2000,但确实感觉十分低效。多数与会者没能很好地参与。拖沓的讨论,50人的会议是无法忍受的。 | 1个月 | 无 | 以尽可能简单的原则继续设计。完成对已有设计的重构。完成代码会审,旨在全体范围中讨论新设计以便整个团队了解代码和设计的发展趋势。 | 更好的单元测试覆盖更大的范围,尽管没有完全覆盖。代码功能测试帮助覆盖测试范围。 | 多数开发人员埋头于新功能的开发,很少会去做重构。代码基准在迭代期末向QA组提交卡片时变得糟糕起来。 |
1/2001 | 希望能尽快做出每个迭代期间的计划-我们的办法是在正式会议前以小组为单位进行更多的准备工作。 | 2 周 | 无 | 多数的设计基于已有的设计:保留标准,代码会审逐渐停止,因为新的设计和重构尚未完成。 | 试图去掉代码功能测试而代之以屏幕搜刮(Screen Scraper),若失败就回到代码功能测试 。加入新的单元测试但仍然没有全部覆盖。QA组开始结合界面测试使用自动功能测试。 | 重构开始更频繁,因为部分代码开始变得凌乱不堪。需要清理的原因主要是实现简单和迭代期限使得代码在没有重要重构的情况下增长。 |
6/2001 | 举行一些讨论卡片或相关卡片组的会议,参加者包括对这些功能感兴趣或有经验的开发者和负责这些卡片的分析人员。 | 2 周 | 无 | 队伍中的大多数人及整个QA组准备提交1.0版本给客户。代码的基准分离以便加入没有测试的新功能。对单元测试有更多的依赖。 | 尽管仍有遗漏,测试范围已经基本稳定。QA组不再测试新功能,因为焦点是1.0版本的提交。 | 在发布版上做的重构很少,而在继续开发的版本上,开发人员会很尽责地进行重构,特别是在年初被迫做了更大更痛苦的重构以后. |
结对编程 | 集体所有 | 持续集成 | 40小时周 | 在场客户 | 代码规范 | |
1/2000 | 由于我们决定采用XP,整个团队读了[1]。每个人都做了尝试,多数人被吸引。 | 由于最初阶段的分组是面向功能,因此此时我们并未意识到集体所有 (collective ownership) ,也没有意识到代码的保护。 | 从第一迭代期开始,进行在线集成,参见[2] | 这是一个概念工作时间:因为我们希望客户在场。于是我们会花另外的时间来满足最后期限。 | 事务分析人员是在场的客户,他们15人一组。真正的客户是不在的,由分析人员同他们沟通。 基本上是JAVA的一般语法。 | |
7/2000 | 结对编程依旧盛行:开发者对新功能进行结对编程,但改错和维护工作由单个人来做。也有一些开发者停止了结对编程。 | 当开发者越来越多地接触系统不同的部分的时候,代码的所有者逐渐显现出来。成员间通过闲谈,代码互审和短小的站立会议(Stand up meeting)进行很好的沟通。 | 代码功能测试加入构造过程。 | 为了通过故事卡片,在每个迭代期的最后工作时间达到50至60小时。 | 同上 | 两周一次的代码互审给开发人员一个机会讨论不同子系统的实现方式。我们可以接受某些子系统代码的非正式方式。 |
1/2001 | 结对编程更少了,因为这一阶段编码更直接,而有些人在进行重构。 | 因为效率低,站立会议被弃用,但代码的所有显现得更加清晰。开发人员开始专职负责系统的某部分。 | 稳定_同上。 | 以2周为迭代期,开发人员的工作时间更接近于40小时… | 同上 | 代码互审逐渐减少,设计及编码规范趋于饱和。 |
6/2001 | 定下了规则:所有新功能要应用结对编程,而改错和维护则由一人完成。 | 随着专业化分工的继续,不同的开发小组人员拥有不同部分代码的知识,于是我们将使他们在接下来相应模块的设计中起更活跃的作用,但代码仍是集体共有。 | 稳定同上。 | 同上 | 同上 | 同上 |