从根本上来说,所有的敏捷开发实践,诸如TDD(译注1)、结对编程(译注2)、持续集成(译注3)和重构(译注4),都有一个统一的观念--永远不被阻拦。这就好像是一个优秀的撞球选手总要确保他的每一次击球都能为下一击创造好机会,每个优秀的敏捷开发者每有一点进展也都要确保下一步。一个优秀的敏捷开发者决不会走出一步,然后就无法再有进展,或是让别人没办法再有进展。
那你怎么知道你的进度停下来了呢?如果你无法让系统运行,进度就是停下来了。如果你不能通过测试,进度就是停下来了。在敏捷世界里,进度只能由通过测试的可运行系统来衡量。如果系统无法运行或是测试失败,那么所有的进度都会停下来,因为反馈循环能告诉我们代码出了问题还是一切良好。当编写的代码无法执行的时候,就好像是驾驶着汽车却看不到挡风玻璃的外面。车轮或许还在转动,但你不知道正在驶往哪个方向,或许你正要驶落悬崖。保持系统随时可运行就像是保持挡风玻璃的清洁。除非我们能看见东西,否则我们无法取得进展。
仔细想想,例如,两个程序员正开发一个项目。Jack说他要写J模块,而Bob说他要写B模块。当Bob写代码写到一个程度就必须要去找J。可是J还没完成,Bob就不得不等。假如Bob那时是个优秀的敏捷开发者,他决不会让事情发展到那一步。他会给J创建一个接口,然后用假代码(stub code)实现它,这样他就可以使得自己那部分的测试能持续运行,因而可以继续开发下去。
设想一个四人团队工作在一个三层架构的管理信息系统上。他们已经通过架构的抽象层次来分好了工。Gerry和George工作在GUI上,Marvin在中间层,而Debeay在数据库。当增加新功能的时候,Debeay做的头一件事情就是去改变开发库的表结构。GUI要等中间层运行起来了才能运行。Debeay已将黑漆涂洒在了挡风玻璃上,整个团队就像是瞎子开车。假如Debeay那时是个优秀的敏捷开发者,她会发现一种能够循序渐进的修改数据结构的方法,增加新的列或是表而不用改变旧的。一直到迭代的最终完成,数据结构会达到成品的样子,而系统在此过程中绝不会中止运行。
保持系统能够持续运行是第一目标。你绝不会做出一些事情以至于会让系统被破坏超过几秒钟。如果你要做一个巨大的设计改变,你会找到一种方式,让每一步的改变都微小到可以确保系统能运行。如果你能找到一种方式能保持所有测试的可持续运行,就不会让系统中止超过几秒钟。
这可不是一个容易掌握的观念。开发者总是习惯于做出一些改变把整个系统搞乱,然后再试图去一块块的拼凑起来。很多人很热衷于这种体验。其实,我曾于一个开发者交谈,他说把系统撕得粉碎再把它拼凑起来是一个程序员所必需的本事。他为他有能力做这种事而感到自豪。因为这对他的自尊来说很重要,我不得不很礼貌的劝说他,他的这种自我成就感是建立在他所冒的风险和为雇主创造利润背道而驰的基础上的。实际上,他对这种赖以生存的能力感到欢喜雀跃。他是一个嗜险成性的人,而且他在拿雇主的财产冒险,这可不是专业行为。敏捷开发好像一场谨慎的象棋游戏,不是一个不计后果的code-chicken游戏(译注5)。优秀的敏捷开发者为他们的目标小心的策划了一条路线,那就是每走一小步都能保持系统的可运行和测试的通过。
一些开发者认为这样做效率低而且缓慢。他们觉得先把系统弄乱然后再重组为一个新的会来得更快些。也许有时候这样做更快些,然而,这样做就像是你想要开车去商店,于是就调整方向直指商店,把挡风玻璃漆成黑色,然后不管红灯和路况就径直的朝着商店开。如果碰巧能行,你就开得更快。但更多的时候这么开在路上就会出岔子。
这个目标可以延伸到团队和组织的各个层面。决不被阻拦意味着你设置好了你的开发环境以至于阻拦的事情不会发生。优秀的敏捷团队使用不被阻拦的源代码控制方法。如果Bill有个模块已经签出(check out),Bob也可以将其签出,但第一个拆入(check in)的人是成功的。假设核心团队正在为我们打造一个可复用的框架,而我们需要的一些功能还没就绪,我们会先自己写好它,等他们好了的时候再使用核心团队的功能。如果企业架构支持我们的这种迂回婉转的方式,那么我们就只需花上几天时间来学习它,然后就能忽略企业架构,而让功能的开发以一种简单的方式来进行。我们就不会被阻拦。
译注:
1,TDD,测试驱动开发,详情请参见“TDD的三条军规”。
2,结对编程,pair programming,又译作“配对编程”。代码由结对的程序员使用一台电脑共同完成。结对人员中的一位控制编码,另一位观察正输入的代码并寻找代码中的错误和可改进地方。两人频繁互换角色,而且结对的关系每天至少改变一次,以便每个程序员在一天中可以在两个不同的结对中工作。据Laurie Williams和Nosek的研究表明,结对非但不会降低开发团队的效率,而且会大大减少缺陷。
3,持续集成,continuous integration。程序员每天会多次拆入(check in)他们的代码并进行集成,规则很简单,第一个拆入的只要完成拆入就可以了,所有其他的人负责代码的合并(merge)工作。为了避免合并时间过长,团队的成员会非常频繁的拆入他们的模块。因此,XP团队每天会进行多次系统构建,并重新创建整个系统。
4,重构,refactoring。随着我们添加一个个特性或是处理一个个错误,代码的结构会逐渐退化,最终会导致纠结不清,难于维护。XP团队通过经常性的代码重构来扭转这种退化。重构就是在不改变代码行为的前提下,对其进行一系列小的改造,旨在改进系统结构的实践活动。
5,code-chicken,密码鸡,一种在北美颇为流行的益智类游戏。
(原文链接网址:http://www.butunclebob.com/ArticleS.UncleBob.ThePrimeDirectiveOfAgileDevelopment; Robert C. Martin的英文blog网址:http://www.butunclebob.com/ArticleS.UncleBob)
作者简介:Robert C. Martin(昵称Uncle Bob)是Object Mentor公司总裁,面向对象设计、模式、UML、敏捷方法学和极限编程领域内的资深顾问。他不仅是Jolt获奖图书《敏捷软件开发:原则、模式与实践》(中文版)(《敏捷软件开发》(英文影印版))的作者,还是畅销书Designing Object-Oriented C++ Applications Using the Booch Method的作者。Martin是Pattern Languages of Program Design 3和More C++ Gems的主编,并与James Newkirk合著了XP in Practice。他是国际程序员大会上著名的发言人,并在C++ Report杂志担任过4年的编辑。