第1章 敏捷——高效软件开发之道

不管路走了多远,错了就要重新返回。——土耳其谚语

这句土耳其谚语的含义显而易见,你也会认同这是软件开发应该遵守的原则。但很多时候,开发人员(包括我们自己)发现自己走错路后,却不愿意立即回头,而是抱着迟早会步入正轨的侥幸心理,继续错下去。人们会想,或许差不多少吧,或许错误不像想象的那么严重。假使开发软件是个确定的、线性的过程,我们随时可以撤回来,如同谚语中所说的那样。然而,它却不是。相反,软件开发更像是在冲浪——一直处于动态、不断变化的环境中。大海本身无法预知,充满风险,并且海里还可能有鲨鱼出没。冲浪之所以如此有挑战性,是因为波浪各不相同。在冲浪现场,每次波浪都是独一无二的,冲浪的动作也会各不相同。例如,沙滩边的波浪和峭壁下的波浪就有很大的区别。

在软件开发领域里,在项目研发过程中出现的需求变化和挑战就是你在冲浪时要应对的海浪——它们从不停止并且永远变化,像波浪一样。在不同的业务领域和应用下,软件项目具有不同的形式,带来了不同的挑战。甚至还有鲨鱼以各种伪装出没。

软件项目的成败,依赖于整个项目团队中所有开发成员的技术水平,对他们的培训,以及他们各自的能力高低。就像成功的冲浪手一样,开发人员必须也是技术扎实、懂得掌握平衡和能够敏捷行事的人。不管是预料之外的波浪冲击,还是预想不到的设计失败,在这两种情况下敏捷都意味着可以快速地适应变化。

敏捷开发宣言

我们正通过亲身实践和帮助他人实践,揭示了一些更好的软件开发方法。通过这项工作,我们认为:

  • 个体和交互胜过过程和工具
  • 可工作的软件胜过面面俱到的文档
  • 客户协作胜过合同谈判
  • 响应变化胜过遵循计划

虽然右项也有价值,但我们认为左项具有更大的价值。

敏捷宣言作者,2001年版权所有。

更多详细信息可以访问agilemanifesto.org。

敏捷的精神

那么,到底什么是敏捷开发方法?整个敏捷开发方法的运动从何而来呢?

  • 2001年2月,17位志愿者(包括作者之一Andy在内)聚集在美国犹他州雪鸟度假胜地,讨论一个新的软件开发趋势,这个趋势被不严格地称为“轻量型软件开发过程”。
  • 我们都见过了因为开发过程的冗余、笨重、繁杂而失败的项目。世上应该有一种更好的软件开发方法——只关注真正重要的事情,少关注那些占用大量时间而无甚裨益的不重要的事情。
  • 这些志愿者们给这个方法学取名为敏捷。他们审视了这种新的软件开发方法,并且发布了敏捷开发宣言:一种把以人为本、团队合作、快速响应变化和可工作的软件作为宗旨的开发方法(本页最开始的方框里就是宣言的内容)。
  • 敏捷方法可以快速地响应变化,它强调团队合作,人们专注于具体可行的目标(实现真正可以工作的软件),这就是敏捷的精神。它打破了那种基于计划的瀑布式软件开发方法,将软件开发的实际重点转移到一种更加自然和可持续的开发方式上。
  • 它要求团队中的每一个人(包括与团队合作的人)都具备职业精神,并积极地期望项目能够获得成功。它并不要求所有人都是有经验的专业人员,但必须具有专业的工作态度——每个人都希望尽最大可能做好自己的工作。
  • 如果在团队中经常有人旷工、偷懒甚至直接怠工,那么这样的方法并不适合你,你需要的是一些重量级的、缓慢的、低生产率的开发方法。如果情况并非如此,你就可以用敏捷的方式进行开发。
  • 这意味着你不会在项目结束的时候才开始测试,不会在月底才进行一次系统集成,也不会在一开始编码的时候就停止收集需求和反馈。
  • 相反,这些活动会贯穿项目的整个生命周期。事实上,只要有人继续使用这个软件,开发就没有真正结束。我们进行的是持续开发、持续反馈。你不需要等到好几个月之后才发现问题:越早发现问题,就越容易修复问题,所以应该就在此时此刻把问题修复。

开发要持续不断,切勿时续时断 Continuous development, not episodic

  • 这就是敏捷的重点所在。
  • 这种持续前进的开发思想根植于敏捷方法中。它不但应用于软件开发的生命周期,还应用于技术技能的学习、需求采集、产品部署、用户培训等方面。它包括了软件开发各个方面的所有活动。
  • 为什么要进行持续开发呢?因为软件开发是一项非常复杂的智力活动,你遗留下来的任何问题,要么侥幸不会发生意外,要么情况会变得更糟糕,慢慢恶化直到变得不可控制。当问题累积到一定程度的时候,事情就更难解决,最后无法扭转。面对这样的问题,唯一有效的解决办法就是持续地推进系统前进和完善(见《程序员修炼之道》一书中的“软件熵”[HT00])。

持续注入能量 Inject energy

  • 有些人对使用敏捷方法有顾忌,认为它只是另一种危机管理而已。事实并非如此。危机管理是指问题累积并且恶化,直到它们变得非常严重,以至于你不得不立即放下一切正在做的工作来解决危机。而这样又会带来其他的负面影响,你就会陷入危机和恐慌的恶性循环中。这些正是你要避免的问题。
  • 所以,你要防微杜渐,把问题解决在萌芽状态,你要探索未知领域,在大量成本投入之前先确定其可行性。你要知错能改,在事实面前主动承认自己的所有错误。你要能自我反省,经常编码实战,加强团队协作精神。一开始你可能会觉得不适应,因为这同以往有太多的不同,但是只要能真正地行动起来,习惯了,你就会得心应手。

敏捷的修炼之道

下面一句话是对敏捷的精辟概括。

敏捷开发就是在一个高度协作的环境中,不断地使用反馈进行自我调整和完善。

下面将扼要讲述它的具体含义,以及敏捷的团队应该采取什么样的工作和生活方式。

首先,它要整个团队一起努力。敏捷团队往往是一个小型团队,或者是大团队分成的若干小团队(10人左右)。团队的所有成员在一起工作,如果可能,最好有独立的工作空间(或者类似bull pen(1),一起共享代码和必要的开发任务,而且大部分时间都能在一起工作。同时和客户或者软件的用户紧密工作在一起,并且尽可能早且频繁地给他们演示最新的系统。

你要不断从自己写的代码中得到反馈,并且使用自动化工具不断地构建(持续集成)和测试系统。在前进过程中,你都会有意识地修改一些代码:在功能不变的情况下,重新设计部分代码,改善代码的质量。这就是所谓的重构,它是软件开发中不可或缺的一部分——编码永远没有真正意义上的“结束”。

要以迭代的方式进行工作:确定一小块时间(一周左右)的计划,然后按时完成它们。给客户演示每个迭代的工作成果,及时得到他们的反馈(这样可以保证方向正确),并且根据实际情况尽可能频繁地发布系统版本让用户使用。

对上述内容有了了解之后,我们会从下面几个方面更深入地走进敏捷开发的实践。

  • 第2章:态度决定一切。软件开发是一项智力劳动。在此章,我们会讲解如何用敏捷的心态开始工作,以及一些有效的个人习惯。这会为你使用敏捷方法打下扎实的基础。
  • 第3章:学无止境。敏捷项目不可能坐享其成。除了开发之外,我们还要在幕后进行其他的训练,虽然它不属于开发工作本身,但却对团队的发展极其重要。我们还将看到,如何通过培养习惯来帮助个人和团队成长并自我超越。
  • 第4章:交付用户想要的软件。如果软件不符合用户的需求,无论代码写得多么优美,它都是毫无用处的。这里将会介绍一些客户协作的习惯和技巧,让客户一直加入到团队的开发中,学习他们的业务经验,并且保证项目符合他们的真正需求。
  • 第5章:敏捷反馈。敏捷团队之所以能够顺利开展工作,而不会陷入泥潭挣扎导致项目失败,就是因为一直使用反馈来纠正软件和开发过程。最好的反馈源自代码本身。本章将研究如何获得反馈,以及如何更好地控制团队进程和性能。
  • 第6章:敏捷编码。为满足将来的需求而保持代码的灵活和可变性,这是敏捷方法成功的关键。本章给出了一些习惯,介绍如何让代码更加整洁,具有更好的扩展性,防止代码慢慢变坏,最后变得不可收拾。
  • 第7章:敏捷调试。调试错误会占用很多项目开发的时间——时间是经不起浪费的。这里将会学到一些提高调试效率的技巧,节省项目的开发时间。
  • 第8章:敏捷协作。最后,一个敏捷开发者已经能够独挡一面,除此之外,你需要一个敏捷团队。这里有一些最有效的实践有助于黏合整个团队,以及其他一些实践有助于团队日常事务和成长。

敏捷工具箱

全书中,我们会涉及一些敏捷项目常用的基本工具。也许一些工具你还很陌生,所以这里做了简单介绍。想要了解这些工具的详细信息,可以进一步去读附录中的有关参考文献。

Wiki:Wiki(2)是一个网站,用户通过浏览器,就可以编辑网页内容并创建链接到一个新的内容页面。Wiki是一种很好的支持协作的工具,因为团队中的每一个人都可以根据需要动态地新增和重新组织网页中的内容,实现知识共享。关于Wiki的更多详情,可查阅《Wiki之道》这篇文章。

版本控制:项目开发中所有的产物——全部的源代码、文档、图标、构建脚本等,都需要放入版本控制系统中,由版本控制系统来统一管理。令人惊讶的是,很多团队仍然喜欢把这些文件放到一个网络上共享的设备上,但这是一种很不专业的做法。如果需要一个安装和使用版本控制系统的详细说明,可以查阅《版本控制之道——使用CVS》[TH03]或者《版本控制之道——使用Subversion》[Mas05]。

单元测试:用代码来检查代码,这是开发者获得反馈的主要来源。在本书后面会更多地谈到它,但要真正知道框架可以处理大部分的繁琐工作,让你把精力放到业务代码的实现中。想要了解单元测试,可以看《单元测试之道Java版》[HT03]和《单元测试之道C#版》[HT04],你可以在《JUnit Recipes中文版》[Rai04]一书中找到很多写单元测试的实用技巧。

自动构建:不管是在自己的本地机器上实现构建,还是为整个团队实现构建,都是全自动化并可重复的。因为这些构建一直运行,所以又称为持续集成。和单元测试一样,有大量的免费开源产品和商业产品为你提供支持。《项目自动化之道》[Cla04]介绍了所有自动构建的技巧和诀窍(包括使用Java Lamps)。

最后,Ship It![RG05]一书很好地介绍了怎样将这些基本的开发环境实践方法结合到一起。

魔鬼和这些讨厌的细节

如果你翻翻这本书就会注意到,在每节的开头我们都会引入一段话,旁边配有一个魔鬼木刻像,诱使你养成不良习惯,如下所示。

  • “干吧,就走那个捷径。真的,它可以为你节省时间。没有人会知道是你干的,这样你就会加快自己的开发进度,并且能够完成这些任务了。这就是关键所在。”
  • 他的有些话听上去有点儿荒唐,就像是Scott Adams笔下呆伯特(Dilbert)漫画书中的魔王——“尖发老板”所说的话一样。但要记住Adams先生可是从他那些忠实的读者中得到很多回馈的。
  • 有些事情看上去就会让人觉得很怪异,但这全部是我们亲耳所闻、亲眼所见,或者是大家秘而不宣的事情,它们都是摆在我们面前的诱惑,不管怎样,只要试过就会知道,为了节省项目的时间而走愚蠢的捷径是会付出巨大代价的。
  • 与这些诱惑相对,在每个习惯最后,会出现一位守护天使,由她给出我们认为你应该遵循的一些良策。
  • 先难后易。我们首先要解决困难的问题,把简单的问题留到最后。
  • 现实中的事情很少是黑白分明的。我们将用一些段落描述一个习惯应该带给你什么样的切身感受,并介绍成功实施和保持平衡的技巧。如下所示。

切身感受

本段描述培养某个习惯应该有什么样的切身感受。如果在实践中没有这样的体会,你就要考虑改变一下实施的方法。

平衡的艺术

  • 一个习惯很可能会做得过火或者做得不够。我们会给出一些建议,帮你掌握平衡,并告诉你一些技巧,能使习惯真正为你所用。
  • 毕竟,一件好事做得过火或者被误用,都是非常危险的(我们见过很多所谓的敏捷项目最后失败,都是因为团队在实践的时候没有保持好自己的平衡)。所以,我们希望保证你能真正从这些习惯中获益。
  • 通过遵循这些习惯,把握好平衡的艺术,在真实世界中有效地应用它们,你将会看到你的项目和团队发生了积极的变化。

好了,你将步入敏捷开发者的修炼之路,更重要的是,你会理解其后的开发原则。

致谢

  • 每本书的出版都是一项艰巨的事业,本书也不例外。除了作者,还有很多幕后英雄。我们要感谢下面所有的人,正是他们的帮助,本书才得以问世。
  • 感谢Jim Moore为本书设计的封面插图,感谢Kim Wimpsett出色的文字编辑工作(如果还有错,那肯定是最后一刻的修改导致的)。
  • 最后感谢所有付出时间和精力让本书变得更好的审阅者:Marcus Ahnve、Eldon Alameda、Sergei Anikin、Matthew Bass、David Bock、A. Lester Buck III、Brandon Campbell、Forrest Chang、Mike Clark、John Cook、Ed Gibbs 、Dave Goodlad、Ramamurthy Gopalakrishnan、Marty Haught、Jack Herrington、Ron Jeffries、Matthew Johnson、Jason Hiltz Laforge、Todd Little、Ted Neward、James Newkirk、Jared Richardson、Frédérick Ros、Bill Rushmore、David Lázaro Saz、Nate Schutta、Matt Secoske、Guerry Semones、Brian Sletten、Mike Stok、Stephen Viles、Leif Wickland和Joe Winter。

Venkat Subramaniam 致谢

  • 我要感谢Dave Thomas,他是我的良师益友。如果没有他的指导、鼓励和建设性的意见,本书到现在还只是一个空想。
  • 我有幸与Andy Hunt合著本书,从他身上学到了太多的东西。他不仅是一位技术专家(任何注重实效的程序员都知道这一点),还具有令人难以置信的表达能力和优秀品质。我欣赏Pragmatic Programmers出版公司制作本书的每一个环节,他们精通很多有用的工具,具有解决问题的能力,而且最重要的是,他们有很好的工作态度,正因如此,本书才可以如此顺利地发布。
  • 感谢Marc Garbey的鼓励。他是一位伟大的朋友,他的幽默和敏捷感染了世界上的很多人。我特别感谢那些与我一路同行的俗人们(错了,是朋友们)——Ben Galbraith、Brian Sletten、Bruce Tate、Dave Thomas、David Geary、Dion Almaer、Eitan Suez、Erik Hatcher、Glenn Vanderburg、Howard Lewis Ship、Jason Hunter、Justin Gehtland、Mark Richards 、Neal Ford、Ramnivas Laddad、Scott Davis、Stu Halloway和Ted Neward——这些家伙棒极了!我感谢Jay Zimmerman(人称敏捷推动者),NFJS的主管,感谢他的鼓励,感谢他给我机会去向他的客户推广我的敏捷思想。
  • 感谢父亲教会我正确的人生价值观,还有母亲给予我创造的灵感。如果不是妻子Kavitha的耐心和鼓励,还有我的儿子们Karthik和Krupakar的支持,我就没有今天的一切。谢谢,我爱你们!

Andy Hunt致谢

  • 好的,我想现在每个人都被感谢过了。但是,我要特别感谢Venkat邀请我参与本书的写作。我不会接受任何其他人要我合作写这本书的邀请,但却接受了Venkat的邀请。他最清楚整件事情的经过。
  • 我要感谢当年在雪鸟聚会的那些敏捷精英们。虽然没有任何哪一个人发明了敏捷,但正是通过所有人的共同努力,才让敏捷在当今的软件开发行业中茁壮成长,成为一支重要的力量。
  • 当然,还要感谢我的家人,感谢他们的支持和理解。从最早的《程序员修炼之道》到现在这本书是一个漫长的征途,但也是一段开心的经历。现在,演出开始了。

【注释】

  1. bull pen原指在棒球比赛中,侯补投手的练习场。——译者注
  2. WiKi是WikiWikiWeb的简称,WikiWiki源自夏威夷语,本意是快点快点。
下一节:选定了要走的路,就是选定了它通往的目的地。——Harry Emerson Fosdick(美国基督教现代主义神学家)