敏捷方法论有一个共同的特点,那就是都将矛头指向了“文档”,它们认为传统的软件工程方法文档量太“重”了,称为“重量级”方法,而相应的敏捷方法则是“轻量级”方法。正是因为“轻量级”感觉没有什么力量,不但不能够有效体现灵活性,反而显得是不解决问题的方法论似的。因此,就有了一次划时代的会议,创建了敏捷联盟。
在敏捷方法论领域中,比较知名的、有影响力的,是拥有与 Microsoft 的操作系统相同缩写语——XP的极限编程(eXtreme Programming)。极限编程方法论可以说是敏捷联盟中最鲜艳的一面旗帜,也是被研究、尝试、应用、赞扬、批判最多的一种方法论,也是相对来说最成熟的一种。
这一被誉为“黑客文化”的方法论的雏形最初形成于1996—1999年间,Kent Beck、Ward Cunninggham、Ron Jeffrey 在开发 C3 项目(Chrysler Comprehensive Compensation)的实践中总结出了 XP 的基本元素。在此之后,Kent Beck 和他的一些好朋友们一起在实践中完善提高,终于形成了极限编程方法论。
那么什么是 XP 呢?XP 是一种轻量(敏捷)、高效、低风险、柔性、可预测、科学而且充满乐趣的软件开发方式。与其他方法论相比,其最大的不同在于:
Kent Beck 曾经说过“开车”就是一个 XP 的范例,即使看上去进行得很顺利,也不要把视线从公路上移开,因为路况的变化,将使得你必须随时做出一些这样那样的调整。而在软件项目中,客户就是司机,他们也没有办法确切地知道软件应该做什么,因此程序员就需要向客户提供方向盘,并且告知我们现在的位置。
XP 包括写什么呢?如图,XP 由价值观、原则、实践和行为四个部分组成,它们彼此相互依赖、关联, 并通过行为贯穿于整个生命期。
XP 的核心是其总结的沟通(Communication)、简单(Simplicity)、反馈(Feedback)、勇气(Courage)四大价值观,它们是XP的基础,也是XP的灵魂。
此外还扩展了第五个价值观:谦逊(Modesty)。 XP用“沟通、简单、反馈、勇气和谦逊”来减轻开发压力和包袱;XP 精神可以启发我们如何学习和对待快速变化、多样的开发技术。成功学习 XP 的关键,是用“沟通、简单、反馈、勇气和谦逊”的态度来对待 XP;轻松愉快地来感受 XP 的实践思想;自己认真实践后,通过对真实反馈的分析,来决定 XP 对自己的价值;有勇气接受它,或改进它。
通常程序员给人留下的印象就是“内向、不善言谈”,然后项目中的许多问题就出在这些缺乏沟通的开发人员身上。经常由于某个程序员做出了一个设计决定,但是却不能及时地通知大家,结果使得大家在协作与配合上出现了很多的麻烦,而在传统的方法论中,并不在意这种口头沟通不畅的问题,而是希望借助于完善的流程和面面俱到的文档、报表、计划来替代,但是这同时又引入了效率不高的新问题。
XP 方法论认为,如果小组成员之间无法做到持续的、无间断的交流,那么协作就无从谈起,从这个角度能够发现,通过文档、报表等人工制品进行交流面临巨大的局限性。因此,XP 组合了诸如对编程这样的最佳实践,鼓励大家进行口头交流,通过交流解决问题,提高效率。
XP 方法论提倡在工作中秉承“够用就好”的思路,也就是尽量地简单化,只要今天够用就行,不考虑明天会发现的新问题。这一点看上去十分容易,但是要真正做到保持简单的工作其实很难的。因为在传统的开发方法中,都要求大家对未来做一些预先规划,以便对今后可能发生的变化预留一些扩展的空间。
正如对传统开发方法的认识一样,许多开发人员也会质疑 XP,保持系统的扩展性很重要,如果都保持简单,那么如何使得系统能够有良好的扩展性呢?其实不然,保持简单的理由有两个:
而且简单和沟通之间还有一种相对微妙的相互支持关系。当一个团队之间,沟通的越多,那么就越容易明白哪些工作需要做,哪些工作不需要做。另一方面,系统越简单,需要沟通的内容也就越少,沟通也将更加全面。
是什么原因使得我们的客户、管理层这么不理解开发团队?为什么客户、管理层总是喜欢给我们一个死亡之旅?究其症结,就是开发的过程中缺乏必要的反馈。在许许多多项目中,当开发团队经历过了需求分析阶段之后,在相当长的一段时间内,是没有任何反馈信息的。整个开发过程对于客户和管理层而言就像一个黑盒子,进度完全是不可见的。
而且在项目的过程中,这样的现象不仅出现在开发团队与客户、管理层之间,还包括在开发团队内部。这一切问题都需要我们更加注重反馈。,反馈对于任何软件项目的成功都是至关重要的,而在 XP 方法论中则更进一步,通过持续、明确的反馈来暴露软件状态的问题。具体而言就是:
同时,我们也会发现反馈与沟通也有着良好的配合,及时和良好的反馈有助于沟通。而简单的系统更有利于测试和反馈。
在应用 XP 方法论时,我们每时每刻都在应对变化:由于沟通良好,因此会有更多需求变更的机会;由于时刻保持系统的简单,因此新的变化会带来一些重新开发的需要;由于反馈及时,因此会有更多中间打断你的思路的新需求。
总之这一切,使得你立刻处于变化之中,因此这时就需要你有勇气来面对快速开发,面对可能的重新开发。也许你会觉得,为什么要让我们的开发变得如此零乱,但是其实这些变化若你不让它早暴露,那么它就会迟一些出现,并不会因此消亡,因此,XP 方法论让它们早出现、早解决,是实现“小步快走”开发节奏的好办法。
也就是 XP 方法论要求开发人员穿上强大、自动测试的盔甲,勇往直前,在重构、编码规范的支持下,有目的地快速开发。
勇气可以来源于沟通,因为它使得高风险、高回报的试验成为可能;勇气可以来源于简单,因为面对简单的系统,更容易鼓起勇气;勇气可以来源于反馈,因为你可以及时获得每一步前进的状态(自动测试),会使得你更勇于重构代码。
在这四大价值观之下,隐藏着一个更深刻的东西,那就是尊重。因为这一切都建立在团队成员之间的相互关心、相互理解的基础之上。
及时地、快速地获取反馈,并将所学到的知识尽快地投入到系统中去。也就是指开发人员应该通过较短的反馈循环迅速地了解现在的产品是否满足了客户的需求。这也是对反馈这一价值观的进一步补充。
类似地,简单性假设原则是对简单这一价值观的进一步补充。这一原则要求开发人员将每个问题都看得十分容易解决,也就是说只为本次迭代考虑,不去想未来可能需要什么,相信具有将来必要时增加系统复杂性的能力,也就是号召大家出色地完成今天的任务。
就像开车打方向盘一样,不要一次做出很大的改变,那样将会使得可控性变差,更适合的方法是进行微调。而在软件开发中,这样的道理同样适用,任何问题都应该通过一系列能够带来差异的微小改动来解决。
在软件开发过程中,最好的办法是在解决最重要问题时,保留最多选项的那个。也就是说,尽量为下一次修改做好准备。
在实践中,经常看到许多开发人员喜欢将一些细小的问题留待后面解决。例如,界面的按钮有一些不平整,由于不影响使用就先不管;某一两个成员函数暂时没用就不先写等。这就是一种工作拖泥带水的现象,这样的坏习惯一旦养成,必然使得代码质量大打折扣。
而在 XP 方法论中,贯彻的是“小步快走”的开发原则,因此工作质量决不可打折扣,通常采用测试先行的编码方式来提供支持。
在 XP 中,集成了 13 个最佳实践,有趣的是,它们没有一个是创新的概念,大多数概念和编程一样老。其主要创新点在于提供一种良好的思路,将这些最佳实践结合在一起,并且确保尽可能彻底地执行它们,使得它们能够在最大程度上相互支持,紧接下来,我们就对每一种最佳实践进行一番了解。
计划游戏的主要思想就是先快速地制定一份概要的计划,然后随着项目细节的不断清晰,再逐步完善这份计划。计划游戏产生的结果是一套用户故事及后续的一两次迭代的概要计划。
“客户负责业务决策,开发团队负责技术决策”是计划游戏获得成功的前提条件。也就是说,系统的范围、下一次迭代的发布时间、用户故事的优先级应该由客户决定;而每个用户故事所需的开发时间、不同技术的成本、如何组建团队、每个用户故事的风险,以及具体的开发顺序应该由开发团队决定。
好了,明白这些就可以进行计划游戏了。首先客户和开发人员坐在同一间屋子里,每个人都准备一支笔、一些用于记录用户故事的纸片,最好再准备一个白板,就可以开始了。
XP 方法论秉承的是“持续集成,小步快走”的哲学,也就是说每一次发布的版本应该尽可能的小,当然前提条件是每个版本有足够的商业价值,值得发布。
由于小型发布可以使得集成更频繁,客户获得的中间结果也越频繁,反馈也就越频繁,客户就能够实时地了解项目的进展情况,从而提出更多的意见,以便在下一次迭代中计划进去。以实现更高的客户满意度。
相对而言,隐喻这一个最佳实践是最令人费解的。什么是隐喻呢?根据词典中的解释是:“一种语言的表达手段,它用来暗示字面意义不相似的事物之间的相似之处”。那么这在软件开发中又有什么用呢?总结而言,常常用于四个方面。
当然,如果能够找到合适的隐喻是十分快乐的,但并不是每种情况都可以找到恰当的隐喻,你也没有必要强求
强调简单设计的价值观,引出了简单性假设原则,落到实处就是“简单设计”实践。这个实践看上去似乎很容易理解,但却又经常被误解,许多批评者就指责 XP 忽略设计是不正确的。其实,XP 的简单设计实践并不是要忽略设计,而且认为设计不应该在编码之前一次性完成,因为那样只能建立在“情况不会发生变化”或者“我们可以预见所有的变化”之类的谎言的基础上的。
Kent Beck 概念中简单设计是这样的:
当我第一次看到“测试先行”这个概念的时候,我的第一感觉就是不解,陷入了“程序都还没有写出来,测试什么呀?”的迷思。我开始天马行空地寻求相关的隐喻,终于找到了能够启发我的工匠,首先,我们来看看两个不同的工匠是如何工作的吧。
你会选择哪种工作方法呢?你一定会骂工匠二笨吧!这样多浪费时间呀!然而你自己想想,你平时在编写程序的时候又是怎么做的呢?我们就是按工匠二的方法在工作呀!甚至有时候比工匠二还笨,是整面墙都砌完了,直接进行“集成测试”,经常让整面的墙倒塌。看到这里,你还会觉得自己的方法高明吗?这个连工匠都明白的道理,自己却画地为牢呀。
不仅我们没有采用工匠一的工作方法,甚至有的时候程序员会以“开发工作太紧张”为理由,而忽略测试工作。但这样却导致了一个恶性循环,越是没有空编写测试程序,代码的效率与质量越差,花在找 Bug、解决 Bug 的时间也越来越多,实际产能大打降低。由于产能降低了,因此时间更紧张,压力更大。你想想,为什么不拉上一根水平线呢?难道,我们不能够将后面浪费的时间花在单元测试上,使得我们的程序一开始就更健壮,更加易于修改吗?不过,编写测试程序当然要比拉一条水平线难道多,所以我们需要引入“自动化测试工具”,免费的 xUnit 测试框架就是你最佳的选择。
为了鼓励程序员原意甚至喜欢在编写程序之前编写测试代码,XP 方法论还提供了许多有说服力的理由。
测试先行是 XP 方法论中一个十分重要的最佳实践,并且其中所蕴含的知识与方法也十分丰富。
重构时一种对代码进行改进而不影响功能实现的技术,XP 需要开发人员在闻到代码的坏味道时,有重构代码的勇气。重构的目的是降低变化引发的风险,使得代码优化更加容易。通常重构发生在两种情况之下。
在《重构》一书中,作者 Martin Fowler 提示我们:在考虑重构时,应该要养成编写并经常运行测试代码的习惯;要先编写代码,再进行重构;把每一次增加功能都当做一次重构的好时机;将每一个纠正错误当做一次重构的重要时机。同时,该书中也列出大量需要重构的情况和重构方法。
最后类似地,给还没有足够勇气进行重构的程序员打几剂强心针:
重构技术是对简单性设计的一个良好的补充,也是 XP 中重视“优质工作”的体现,这也是优秀的程序员必备的一项技能。
“什么!两个人坐在一起写程序?那岂不是对人力的巨大浪费吗?而且我在工作时可不喜欢有一个人坐在边上当检察官。”是的,正如这里列举出来的问题一样,结对编程技术还是被很多人质疑的。
不过,自从 20 世纪 60 年代,就有类似的实践在进行,长期以来的研究结果却给出了另外一番景象,那就是结对编程的效率反而比单独编程更高。一开始虽然会牺牲一些速度,但慢慢的,开发速度会逐渐加快,究其原因,主要是结对编程大打降低了沟通的成本,提供了工作的质量,具体表现在:
结对编程技术被誉为 XP 保持工作质量、强调人文主义的一个典型的实践,应用得当还能够使得开发团队之前的协作更加流畅、知识交流与共享更加频繁,团队的稳定性也会更加稳固。
由于 XP 方法论鼓励团队进行结对编程,而且认为结对编程的组合应该动态地搭配,根据任务的不同、专业技能的不同进行最优组合。由于每个人都肯定会遇到不同的代码,所以代码的所有制就不再适合于私有,因为那样会给修改工作带来巨大的不便。
也就是说,团队中的每个成员都拥有对代码进行改进的权利,每个人都拥有全部代码,也都需要对全部代码负责。同时,XP 强调代码是谁破坏的(也就是修改后发生问题),就应该由谁来修复。
由于在 XP 中,有一些与之匹配的最佳实践,因此你并无须担心采用集体代码所有制会让你的代码变得越来越乱:
集成代码所有制是 XP 与其他敏捷方法的一个较大不同,也是从另一个侧面体现了 XP 中蕴含的很深厚的编码情节。
在前面谈到小型发布、重构、结对编程、集体代码所有制等最佳实践的时候,我们多次看到“持续集成”的身影,可以说持续集成是对这些最佳实践的基本支撑条件。
可能大家会对持续集成与小型发布代表的意思混淆不清,其实小型发布是指在开发周期经常发布中间版本,而持续集成的含义则是要求 XP 团队每天尽可能多次地做代码集成,每次都在确保系统运行的单元测试通过之后进行。
这样,就可以及早地暴露、消除由于重构、集体代码所有制所引入的错误,从而减少解决问题的痛苦
要在开发过程中做到持续集成并不容易,首先需要养成这个习惯。而且集成工作往往是十分枯燥、烦琐的,因此适当地引入每日集成工具是十分必要的。XP 建议大家首先使用配置管理服务器将代码管理起来,然后使用 Ant 或 Nant 等 XP 工具,编写集成脚本,调用 xUint 等测试框架,这样就可以实现每当程序员将代码 Check in 到配置服务器上时,Ant 就会自动完成编译和集成,并调用测试代码完成相应的测试工作。
这是最让开发人员开心的、管理者反对的一个最佳实践了,加班、再加班早已成为开发人员的家常便饭,也是管理者最常使用的一种策略,而 XP 方法论认为,加班最终会扼杀团队的积极性,最终导致项目失败,这也充分体现了 XP 方法关注人的因素比关注过程的因素更多一些。
Kent Beck 认为开发人员即使能够工作更长的时间,他们也不该这样做,因为这样做会使他们更容易厌倦编程工作,从而产生一些影响他们效能的其他问题。因此,每周工作 40 小时是一种顺势行为,是一种规律。其实对于开发人员和管理者来说,违反这种规律是不值得的。
不过有一点是需要解释的,“每周工作 40 小时”中的 40 不是一个绝对数,它所代表的意思是团队应该保证按照“正常的时间”进行工作。那么如何做到这一点呢?
正如米卢说过的“享受足球”一样,同样地,每一个开发人员应该做到“享受编程”,那么“每周工作 40 小时”就是你的起点。
团队只有持久才有获胜的希望。他们以能够长期维持的速度努力工作,他们保存精力,他们把项目看作是马拉松长跑,而不是全速短跑。
为了保证开发出来的结果与客户的预想接近,XP 方法论认为最重要的需要将客户请到开发现场。就像计划游戏中提到过的,在 XP 项目中,应该时刻保证客户负责业务决策,开发团队负责技术决策。因此,在项目中有客户在现场明确用户故事,并做出相应的业务决策,对于 XP 项目而言有着十分重要的意义。
也许有人会问,客户提交了用户故事之后不就完成工作了吗?其实很多尝试过用户故事的团队都会发现其太过简单,包含的信息量极少,XP方法论不会不了解,因此,不会把用户故事当做开发人员交付代码的唯一指示。用户故事只是一个起点,后面的细节还需要开发人员与客户之间建立起来的良好沟通来补充。
作为一名有经验的开发人员,绝对不会对现场客户的价值产生任何怀疑,但是都会觉得想要实现现场客户十分困难。要实现这一点,需要对客户进行沟通,让其明白,想对于开发团队,项目成功对于客户而言更为重要。而现场客户则是保障项目成功的一个重要措施,想想在你装修房子的时候,你是不是常常在充当现场客户的角色呢?其实这隐喻就是让客户理解现场客户重要性最好的突破口。
其实现场客户在具体实施时,也不是一定需要客户一直和开发团队在一起,而是在开发团队应该和客户能够随时沟通,可以是面谈,可以是在线聊天,可以是电话,当然面谈是必不可少的。其中的关键是当开发人员需要客户做出业务决策是,需要进一步了解业务细节时能够随时找到相应的客户。
不过,也有一些项目是可以不要现场客户参与的:
去尝试吧,现场客户不仅可以争取得到,而且还能使得团队焕然一新,与客户建立起良好的合作与信任。
编码标准是一个“雅俗共享”的最佳实践,不管是代表重型方法论的 RUP,PSP,还是代表敏捷方法论的 XP,都认为开发团队应该拥有一个编码标准。XP 方法论认为拥有编码标准可以避免团队在一些与开发进度无关的细节问题上发生争论,而且会给重构、结对编程带来很大麻烦。试想如果有人将你上次写的代码的变量命名法做了修改,下次你需要再改这部分代码时,会是一种什么感觉呢?
不过,XP 方法论的编码标准的目的不是创建一个事无巨细的规则表,而是只要能够提供一个确保代码清晰,便于交流的指导方针。
如果你的团队已经拥有编码标准,就可以直接使用它,并在过程中进行完善。如果还没有,那么大家可以先进行编码,然后在过程中逐步总结出编码规则,边做边形成。当然除了这种文字规范以外,还可以采用一些如自动格式化代码工具之类的方法进行代码规范。,事实上,你只需要很好地贯彻执行其他的实践并且进行沟通,编码标准会很容易地浮现出来。
有句经典名言“1+1 > 2 ”最适合表达 XP 的观点,Kent Beck 认为 XP 方法论的最大价值在于在项目中融会贯通地运用12个最佳实践,而非单独地使用。你当然可以使用其中的一些实践,但这并不意味着你就运用了 XP 方法论。XP 方法论真正能够发挥其效能,就必须完整地运用12个实践。