敏捷开发的精神内涵 原文最终修订于2006-08-11 上午10:49:50

从根本上来说,所有的敏捷开发实践,诸如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的作者。MartinPattern Languages of Program Design 3More C++ Gems的主编,并与James Newkirk合著了XP in Practice。他是国际程序员大会上著名的发言人,并在C++ Report杂志担任过4年的编辑。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


迭代器模式(Iterator)迭代器模式(Iterator)[Cursor]意图:提供一种方法顺序访问一个聚合对象中的每个元素,而又不想暴露该对象的内部表示。应用:STL标准库迭代器实现、Java集合类型迭代器等模式结构:心得:迭代器模式的目的是在不获知集合对象内部细节的同时能对集合元素进行遍历操作
高性能IO模型浅析服务器端编程经常需要构造高性能的IO模型,常见的IO模型有四种:(1)同步阻塞IO(BlockingIO):即传统的IO模型。(2)同步非阻塞IO(Non-blockingIO):默认创建的socket都是阻塞的,非阻塞IO要求socket被设置为NONBLOCK。注意这里所说的N
策略模式(Strategy)策略模式(Strategy)[Policy]意图:定义一系列算法,把他们封装起来,并且使他们可以相互替换,使算法可以独立于使用它的客户而变化。应用:排序的比较方法、封装针对类的不同的算法、消除条件判断、寄存器分配算法等。模式结构:心得:对对象(Context)的处理操作可
访问者模式(Visitor)访问者模式(Visitor)意图:表示一个作用于某对象结构中的各元素的操作,它使你在不改变各元素的类的前提下定义作用于这些元素的新操作。应用:作用于编译器语法树的语义分析算法。模式结构:心得:访问者模式是要解决对对象添加新的操作和功能时候,如何尽可能不修改对象的类的一种方
命令模式(Command)命令模式(Command)[Action/Transaction]意图:将一个请求封装为一个对象,从而可用不同的请求对客户参数化。对请求排队或记录请求日志,以及支持可撤消的操作。应用:用户操作日志、撤销恢复操作。模式结构:心得:命令对象的抽象接口(Command)提供的两个
生成器模式(Builder)生成器模式(Builder)意图:将一个对象的构建和它的表示分离,使得同样的构建过程可以创建不同的表示。 应用:编译器词法分析器指导生成抽象语法树、构造迷宫等。模式结构:心得:和工厂模式不同的是,Builder模式需要详细的指导产品的生产。指导者(Director)使用C
设计模式学习心得《设计模式:可复用面向对象软件的基础》一书以更贴近读者思维的角度描述了GOF的23个设计模式。按照书中介绍的每个设计模式的内容,结合网上搜集的资料,我将对设计模式的学习心得总结出来。网络上关于设计模式的资料和文章汗牛充栋,有些文章对设计模式介绍生动形象。但是我相信“一千个读者,一千个
工厂方法模式(Factory Method)工厂方法模式(Factory Method)[Virtual Constructor]意图:定义一个用于创建对象的接口,让子类决定实例化哪一个类,使一个类的实力化延迟到子类。应用:多文档应用管理不同类型的文档。模式结构:心得:面对同一继承体系(Produc
单例模式(Singleton)单例模式(Singleton)意图:保证一个类只有一个实例,并提供一个访问它的全局访问点。应用:Session或者控件的唯一示例等。模式结构:心得:单例模式应该是设计模式中最简单的结构了,它的目的很简单,就是保证自身的实例只有一份。实现这种目的的方式有很多,在Java中
装饰者模式(Decorator)装饰者模式(Decorator)[Wrapper]意图:动态的给一个对象添加一些额外的职责,就增加功能来说,比生成子类更为灵活。应用:给GUI组件添加功能等。模式结构:心得:装饰器(Decorator)和被装饰的对象(ConcreteComponent)拥有统一的接口
抽象工厂模式(Abstract Factory)抽象工厂模式(Abstract Factory)[Kit]意图:提供一个创建一系列相关或相互依赖对象的接口,而无须指定他们具体的类。应用:用户界面工具包。模式结构:心得:工厂方法把生产产品的方式封装起来了,但是一个工厂只能生产一类对象,当一个工厂需要生
桥接模式(Bridge)桥接模式(Bridge)[Handle/Body]意图:将抽象部分与它的实现部分分离,使他们都可以独立的变化。应用:不同系统平台的Windows界面。模式结构:心得:用户所见类体系结构(Window派生)提供了一系列用户的高层操作的接口,但是这些接口的实现是基于具体的底层实现
适配器模式(Adapter)适配器模式(Adapter)[Wrapper]意图:将类的一个接口转换成用户希望的另一个接口,使得原本由于接口不兼容而不能一起工作的类可以一起工作。应用:将图形类接口适配到用户界面组件类中。模式结构:心得:适配器模式一般应用在具有相似接口可复用的条件下。目标接口(Targ
组合模式(Composition)组合模式(Composition)意图:将对象组合成树形结构以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。应用:组合图形、文件目录、GUI容器等。模式结构:心得: 用户(Client)通过抽象类(Component)提供的公用接口统一
原型模式(Prototype)原型模式(Prototype)意图:用原型实例制定创建对象的种类,并且通过拷贝这些原型创建新的对象。应用:Java/C#中的Clonable和IClonable接口等。模式结构:心得:原型模式本质上就是对象的拷贝,使用对象拷贝代替对象创建的原因有很多。比如对象的初始化构
什么是设计模式一套被反复使用、多数人知晓的、经过分类编目的、代码 设计经验 的总结;使用设计模式是为了 可重用 代码、让代码 更容易 被他人理解、保证代码 可靠性;设计模式使代码编制  真正工程化;设计模式使软件工程的 基石脉络, 如同大厦的结构一样;并不直接用来完成代码的编写,而是 描述 在各种不同情况下,要怎么解决问题的一种方案;能使不稳定依赖于相对稳定、具体依赖于相对抽象,避免引
单一职责原则定义(Single Responsibility Principle,SRP)一个对象应该只包含 单一的职责,并且该职责被完整地封装在一个类中。Every  Object should have  a single responsibility, and that responsibility should be entirely encapsulated by t
动态代理和CGLib代理分不清吗,看看这篇文章,写的非常好,强烈推荐。原文截图*************************************************************************************************************************原文文本************
适配器模式将一个类的接口转换成客户期望的另一个接口,使得原本接口不兼容的类可以相互合作。
策略模式定义了一系列算法族,并封装在类中,它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。