《重构(Ruby版)》前言
差不多十年前,我(Martin)曾经和Kent Beck一起做过一个项目。这个项目的名字叫C3,它后来成为极限编程诞生的标志性项目,并帮助我们看清了敏捷软件运动的方向。
我们从那个项目里学到了很多东西,不过真正震撼到我的是Kent那种有条不紊、持续不断改进系统设计的风格。一直以来我对编写干净的代码都抱有极大的热情,坚信花时间去清理有问题的代码,以便让团队能更快捷地开发功能是非常有价值的事情。而Kent向我介绍了一种很多顶尖Smalltalk程序员使用的技术,它能让我的工作效率成倍提升。这是一种他们称之为重构的技术,我很快就变得想要在任何场合下都把它介绍给别人。但是市面上没有任何出版物或是类似的资源可以让我指引人们去自己学习这项技术。既然Kent和其他Smalltalk程序员都没意愿要写一本,所以我就决定自己动手了。
结果我的那本《重构》大受欢迎,在重构成为主流技术的过程中看起来还扮演了相当重要的角色。随着近年来Ruby的兴起,给这本书写一本Ruby版是很有意义的,为此我拉来了Jay和Shane。
什么是重构
重构是改变软件系统的过程,它不会改变代码的外部行为,但是可以改善其内部结构。它清理代码的严谨方式能把引入bug的风险降至最低。基本上当你进行重构的时候,就意味着代码的设计在完成时会得到改善。
很多人觉得“代码的设计在完成时会得到改善”这种说法相当古怪。多年来大多数人都相信设计第一、编码第二的原则。而随着时间的推移,不断修改代码以及系统的完整性后,原本设计的结构也会慢慢变得模糊。代码逐渐从一项工程活动沦落为敲敲打打的修补工作。
重构与此正好相反。有了重构,你可以把一个糟糕甚至混乱的设计,逐渐转变成设计良好的代码。每一个步骤都非常简单,甚至有点过分简单了。比如把一个实例变量从一个类移到另一个类,从一个方法里抽出一些代码单独放到一个方法里去,以及在层次体系之间移动一些代码等。但是这些小改动累积起来却能够彻底改进设计。这和通常认为的软件衰败论的观念是完全相反的。
在重构的时候你会发现工作的重心发生了变化。设计不再是最先进行,而是在开发过程中不断进行的。你会从构建系统中学习到如何改进设计。这种交互能让程序的设计随着开发工作的进行一直保持在较好的水准上。
本书的内容
本书是一本专门为职业Ruby程序员编写的重构指导。我们的目标是要向你展示怎样以一种受到严格控制同时又高效的方式来进行重构。你会学习到不在代码里引入bug并能按部就班地改进结构的重构方式。
通常一本书都是以介绍来开头的。虽然我对此并无异议,但是我发现要用泛泛而谈或是抽象的定义来介绍重构并不容易。所以我们还是先举个例子吧。第1章会给出一个包含了常见设计错误的小程序,然后将它重构成一个比较能让人接受的面向对象程序。我们会看到重构过程以及好几种重构技术的应用。如果你想要理解重构究竟是什么,那就绝对不能错过这一章。
在第2章里,我们讨论了重构中一些普遍的原则、定义,以及进行重构的理由。我们还会讲到重构里存在的一些问题。在第3章里,Kent Beck会讲解如何在代码里寻找坏味道,以及如何通过重构来清理它们。测试在重构中扮演着非常重要的角色,因此第4章会讨论如何通过一个简单的测试框架将测试织入代码中去。
第5章~第12章覆盖了重构的花名册,这也是本书的精华所在。这并非一份完整的花名册,只能说是花名册的一部分。它包含了我们在重构这个领域里到目前为止的成果。当我们需要进行某项任务,比如说用多态替换条件逻辑的时候,这份花名册可以手把手地提醒我们安全的做法。我们希望你经常回来翻阅这些章节。
Ruby中的重构
在编写《重构》第1版的时候,我选择了Java来展示这项技术,这主要是因为当时Java是一门非常热门的语言。其实绝大多数重构技术并不局限于任何语言,所以很多人读过第1版以后将重构带到了Java以外的世界。
不过使用最顺手的语言来学习重构显然是非常有帮助的。现在有很多人都在学习Ruby语言,而重构又是Ruby文化中的一个核心部分,所以我们觉得有必要为Ruby爱好者提供一种学习重构的方法——特别是对那些没有使用大括号语言背景的人。
Jay和Shane承担了这项工作,从头到尾审阅本书的第1版,并把它改成Ruby的风格。他们仔细阅读了原文,去掉所有Java风格的东西,然后用Ruby的方式重新组织上下文。他们都是资深的Ruby程序员,同时又有深厚的Java和C#背景,因此这项工作由他们来做真是再适合不过了。
他们还添加了一些Ruby特有的重构技术。虽然我们在前面说过:绝大多数情况下,重构对任何面向对象语言来说都是一样的,但是仍然会有一些特别的东西是某些语言专有的情况。
谁该阅读本书
本书的目标读者是专业程序员,也就是那些靠写软件吃饭的人。书中的例子和讨论包含了大量需要阅读和理解的代码。
虽然重构的焦点是代码,但是它对系统的设计也会产生巨大的影响。因此资深设计师和架构师也有必要理解重构的理念并且在项目中使用它们。重构最好是由有威望的资深开发人员来进行。这样的开发人员能够更好地理解重构背后的思想,并将它们应用于具体的工作场景。
如果不想通读,这里列出了本书的大纲。
如果你想知道什么是重构,请阅读第1章;其中的例子应该能让你了解它的流程。
如果你想知道为什么要进行重构,请阅读前两章。它们会告诉你什么是重构,以及为什么应该进行重构。
如果你想知道应该在哪里进行重构,请阅读第3章。它会告诉你哪些是提示你需要进行重构的标志。
如果你想要实际进行重构,请完整地阅读前4章。然后浏览花名册,只要了解它的大概内容即可,你不用理解所有的细节。当你真的需要进行重构的时候,再去仔细阅读相关的内容也不迟。花名册是一份参考目录,所以用不着一口气读完。
我们在编写本书时假设你从来没有遇到过重构,也没有读过本书的第1版,因此你可以把本书当做是对这个主题的完整介绍。你可以凭自己的语言喜好,选择本书或是原书第1版。
我有第1版——还需要再买这本吗
大概用不着。如果你对第1版很熟悉,那么本书不会给你提供多少新内容。虽然在使用这些重构技术的时候需要转换到Ruby语言上来,但要是你和我们一样,这应该不算什么太困难的事情。
但是基于以下两点原因,我们觉得第1版的拥有者可以考虑买下这本Ruby版。第一个原因是你不太熟悉Java语言,而又觉得这种陌生让你在阅读第1版的时候觉得很吃力。如果这样,我们希望这本Ruby版会稍微简单一点。其次就是如果你正在领导一个Ruby团队,而团队里有人不适应第1版里的Java,在这种情况下,这本专为Ruby编写的书可能更能帮助你们理解重构。
站在前人的肩膀上
有时候别人会称我(Martin)为“重构之父”。这时我总是会婉拒这个称谓,虽然我的书确实帮助重构流行了起来,但是它绝对不是我的发明创造。我的工作主要都是构建在那些来自Smalltalk社区的顶尖高手之上的。
重构社区里的两位顶尖程序员是Ward Cunningham和Kent Beck。他们很早就将重构视为开发过程中的一个核心组成部分,并将它们运用到自己的工作中。特别是和Kent的合作真正让我领略到了重构的重要性,这也直接激发了我编写本书的灵感。
Ralph Johnson在伊利诺伊大学香槟分校领导的一支团队以其对对象技术做出的一系列实际贡献而久负盛名。Ralph很早就是重构的拥护者,他的几个学生也一直致力于研究这个课题。Bill Opdyke在他的博士论文里第一次详细论述了重构技术。John Brant和Don Roberts则开发出了全世界第一款自动化重构工具:Smalltalk重构浏览器。
自从我的书出版以来,很多人发展出了各种重构技术。工具领域更是出现了爆炸性的成长。任何专业的IDE现在都得有一个“重构”菜单才像样,而很多人现在也已经把重构当成是他们开发工具里必不可少的一个部分了。这里我们要着重说明的是,虽然工具会让重构变得更简单,但是就算没有工具你也一样可以有效地进行重构。
Ruby版制作花絮
人们总是想知道一本书是怎么制作出来的,特别是多人合著的时候。
Martin在1997年初就开始了《重构》第1版的编写工作。他记录下编程时进行重构的情况,这样一来这些笔记就可以提醒他如何高效地进行某种重构(这也是本书的主干)。这本书自1999年出版以来,销售成绩一直都很稳定——每年都能卖出一万五千多本。
2006年的时候Jay找到了Martin,说是想写一本Ruby版。Jay找了不少人来帮忙,其中Shane的贡献最大,并很快就成为了主要作者之一。Martin的写作重心当时在别的项目上,因此他在这一版里没有太多地参与,不过我们还是把他的名字留在了封面上,毕竟第一稿是由他提供的,其中很多内容都在这一版里保留了下来。
作者简介
Jay Fields是DRW Trading的一名软件程序员,也是一位研讨会的常客。Jay对发现和成熟化创新式解决方案总是抱有激情。Jay的个人网站是www.jayfields.com。
Shane Harvie在美国、印度和澳大利亚等地的敏捷环境里开发了很多软件。他现在位于芝加哥的DRW Trading公司工作,博客网址是www.shaneharvie.com。
Martin Fowler是ThoughtWorks的首席科学家,他是一位作家、演说家和咨询师,在软件开发活动中经常发表演讲。他关注的是企业软件设计——诸如什么能产生良好的设计,而良好的设计又需要哪些实践等。他是面向对象技术、重构、模式、敏捷方法论、领域建模、统一建模语言(UML)和极限编程的先行者。过去十年来他一直在为ThoughtWorks工作,这是一家非常出色的系统开发和咨询公司。