首页>参考读物>计算机科学与技术>软件与程序设计

修改代码的艺术
作者 : (美)Michael C. Feathers 著
译者 : 侯伯薇 译
丛书名 : 名家经典系列
出版日期 : 2014-06-04
ISBN : 978-7-111-46625-3
定价 : 79.00元
扩展资源下载
扩展信息
语种 : 简体中文
页数 : 327
开本 : 16
原书名 : Working Effectively with Legacy Code
原出版社: Prentice Hall
属性分类: 店面
包含CD :
绝版 : 未绝版
图书简介

修改代码是每一位软件开发人员的日常工作。开发人员常常面对的现实是,即便是最训练有素的开发团队也会写出混乱的代码,而且系统的腐化程度也会日积月累。本书是一部里程碑式的著作,针对大型的、无测试的遗留代码基,提供了从头到尾的方案,让你能够更有效地应付它们,将你的遗留代码基改善得具有更高性能、更多功能、更好的可靠性和可控性。本书还包括了一组共24项解依赖技术,它们能帮助你单独对付代码中的问题片段,并实现更安全的修改。

图书特色

修改代码时,你觉得容易吗?当你修改代码时,能否几乎即时地获得反馈?你理解那些代码吗?如果对于这些问题的答案是否定的,那么你面对的就是遗留代码,它们正在浪费你开发工作的时间和金钱。
在本书中,作者为更有效地处理大规模、缺少测试的遗留代码提供了自始至终的策略。本书内容来自Michael创建的非常知名的Object Mentor公司的研习会,Michael使用那些技术来指导并帮助了成千上万位开发者、技术经理和测试人员,让他们的遗留系统处于可控状态。

本书主要内容:
理解修改软件的机制:添加特性、修正缺陷、改进设计、优化性能
把遗留代码放到测试用具之中
编写测试,防止引入新的问题
包含Java、C++、C和C#的示例,其中介绍的大多数技术适用于其他任何语言或平台
精确地确定要在哪些地方修改代码
处理非面向对象的遗留代码
处理看起来没有任何结构的应用程序

作者简介
Michael C. Feathers 世界级软件开发大师,就职于Object Mentor公司(这是一家世界领先的提供软件领域的指导、技能开发、知识传播和领导力服务的公司)。他是ACM和IEEE成员,也是CppUnit(从JUnit移植到C++上的单元测试框架)和FitCpp(FIT集成测试框架在C++上的实现)的最初作者,曾3次担任OOPSLA会议的CodeFest主席。目前他在世界范围内提供测试驱动开发、重构、面向对象设计、Java、C#、C++以及极限编程方面的培训和指导。

译者简介
侯伯薇 中荷人寿保险有限公司高级系统分析师,InfoQ中文站翻译团队主编,拥有十多年开发经验,目前致力于技术与业务的融合,让开发出来的程序能够真正提高业务人员的工作效率。热衷于通过翻译和演讲的方式与广大程序员分享和交流,曾翻译过多本技术书籍和几百篇技术短文,并在Scrumgathering、QClub、敏捷之旅等活动上做过技术演讲。


随着时间流逝,系统规模不断增长,所有软件都不可避免地变得复杂、难以理解,甚至腐化、变质。因此,对软件开发人员来说,很多时候都需要在既有代码的基础上进行修改、扩展和重构,那么如何在既有的约束下实现我们想要的新功能?如何编写可持续交付的高质量代码?面对各种遗留代码问题,我们该如何应对?
本书是探讨修改代码技术的里程碑式著作,融合作者多年开发和指导软件项目所积累的丰富经验,深入剖析修改遗留代码的各种方法和策略,让你的遗留系统变得更高性能、更多功能、更可靠、更易于管理。书中不仅详细描述理解、测试、重构代码和增加特性的技术,而且包含多种不同编程语言(如Java、C++、C和C#)编写的示例,覆盖遗留代码中出现的大多数问题。此外,还详细讲解24种打破依赖的技术,帮助你编写独立的编程元素,让修改代码更安全。通过这部集大成之作,你不仅能掌握最顶尖的修改代码技术,还可以大大提高对代码和软件开发的领悟力。

图书前言

你还记得自己写过的第一个程序吗?我还记得。那是我在早期的PC上编写的一个很小的图形程序。我开始编程的时间比大多数朋友都要晚。当然,当我还是个孩子的时候就见过计算机。我还记得,当第一次在一个办公室里看到微型计算机的时候,我就被深深触动了,但很多年过去了,我甚至都没有机会坐在一台计算机前面。稍后,当我十几岁的时候,我的一些朋友买了一些最早期的TRS-80计算机。我非常感兴趣,但也非常不安。我知道一旦开始玩计算机,就会被它深深吸引。它看起来太酷了。我不知道为什么我对自己如此了解,但我还是把它延后了。之后,在大学中,我的一位室友有一台计算机,我买了一套C语言编译器,从而可以自学编程。就是从那一刻开始。我一夜又一夜地试着编写程序,使用编译器自带的emacs编辑器写出大量源代码。那让我非常上瘾,而且很有挑战性,我爱死它了!
我希望你也有过类似的经历——让代码能够在计算机上工作的那种最原始的快乐。几乎所有我问过的程序员都有。那种快乐是让我们从事这份工作的原因之一,但一天又一天,快乐在哪里呢?
多年前的一天晚上,在完成工作之后,我给朋友Erik Meade打了一个电话。我知道Erik刚刚开始为一个新团队提供咨询服务,于是我问他:“他们做得如何?”他说:“伙计,他们在编写遗留代码。”这让我心头一震,在我的生命中有过几次那样的情况,这就是一次。我从内心理解他的说法。Erik说的话非常准确地描述了我访问很多团队时所获得的第一感觉。他们非常努力,但在一天结束的时候,迫于时间的压力,繁重的历史包袱,或者缺少能够比较的更好代码,很多人都在编写遗留代码。
什么是遗留代码呢?这个词我使用了很长时间,但并没有准确的定义。让我们看一下严格的定义:遗留代码是我们从别人那里获得的代码,可能是我们公司从另一家公司获得的代码;也可能是最初某个团队迁移到另一个项目中的代码。遗留代码是别人的代码。但在程序员中,这个词有更丰富的含义。“遗留代码”随着时间推移拥有越来越多的含义。
当听到遗留代码这个词时,你会想到什么呢?如果你的情况和我类似,那么就会想到复杂、莫名其妙的结构,你需要修改但是无法真正理解的代码。你在思考中度过一个个不眠之夜,只为了增加特性,而那些特性本来应该很容易添加,然后你要考虑如何演示,团队中的每个人都非常讨厌那些代码,它们看起来根本没人管,你死都不愿意去碰那些代码。你们其中有些人只要想想要让它变好就难受。看起来你们的努力没有任何价值。代码会以多种方式变差,很多方式都和代码是否来自另一个团队没有关系。
在业界,遗留代码这个词通常代表的是我们根本就不理解的难以修改的代码。但是经过和团队一起工作多年,帮助他们解决严重的代码问题,我得到了不同的定义。
对我来说,遗留代码是缺少测试的简单代码。我为这个定义而感到有些悲哀。测试和代码的好坏有什么关系?对我来说,答案很简单,那也是我在本书始终详细阐述的一个观点。
缺少测试的代码就是很差的代码。不管它编写得有多好;也不管它的面向对象以及封装做得有多好。有了测试,我们可以快速且有保证地修改代码的行为。相反,没有测试,我们就不知道代码是变得更好还是更糟糕。
你可能认为这有些过分。那么整洁的代码呢?如果代码非常整洁、结构良好,那就足够了吗?好吧,不要错怪我。我喜欢整洁的代码,甚至比大多数我认识的人还要喜欢,但是尽管整洁的代码非常棒,那还不够。当团队试图做重大的修改,而缺少测试的时候,就会冒很大的风险。就像是在做空中体操而没有保护网一样。那需要非常优秀的技能,以及对每步会发生什么都有非常清晰的了解。精确地知道如果你修改一系列变量会发生什么,就像是你翻跟斗翻出去的时候,有另一个人会抓住你的胳膊。如果你所在的团队代码非常清晰,你的形势要比其他程序员更好一些。在我的工作中,我发现很少有团队的代码能够达到那种整洁程度。它们看起来是统计上的不正常现象。并且,你知道吗?如果你没有起支持作用的测试,那么修改那样的代码会比拥有测试的团队慢。
是的,团队会变得更好,并开始编写更加清晰的代码,但是想要让旧代码变得清晰,需要花费很长时间。在很多情况下,那永远都不会有根本性的改变。因此,我把遗留代码定义为缺少测试的代码,这是没有问题的。它是很有效的定义,并且指出了解决方案。
到现在为止,我说了很多关于测试的事情,但本书并不是关于测试的一本书。本书是帮助大家有信心修改任何代码的书。在接下来的章节中,我会描述可以用来理解代码、为其编写测试、重构以及增加特性的技术。
当阅读这本书的时候,你会注意到的一点是,这并不是一本关于完美代码的书。我在书中使用的代码都是虚构的,因为我的工作需要和客户签订保密协议。但在很多例子中,我试图保持在那个领域所见到的代码的内在品质。我不想说例子总是很有代表性。肯定会有更好的代码,但坦白说,也总是会有一些代码,比我在本书使用的例子要差得多。除了需要为客户保密之外,我之所以不能把那样的代码放到本书中,也是为了不让你厌烦,而忽略隐藏在繁冗的细节中的重要问题。因此,很多例子都相对比较简洁。如果你看到一段代码,想:“不,他根本不知道,我的方法要比那大得多,也差得多”请看一下我给出的建议,看它是否适用,即便例子看起来更简单一些。
本书中所讲述的技术已经在大型代码中经过检验,只是由于篇幅所限,例子才都比较小。特别是当你在代码片段中看到这样的省略号(…)的时候,你可以把它读作“在此插入500行丑陋的代码”:

本书不是关于完美代码的,甚至也不是关于完美设计的。好的设计应该是我们所有人的目标,但在遗留代码中,那是我们无法完全达到的。在某些章节中,我描述了向现有代码中增加新代码的方式,并展示了如何在添加的时候在头脑中想着好的设计原则。你可以先在遗留代码库中开辟出优秀代码区域,但是,如果你想要采取的变更步骤让代码更加丑陋,也不要感到惊奇。这项工作就像是外科手术。我们需要切开皮肤,穿过内脏,这时可能暂时不要考虑美观的问题。这位病人的主要器官和内脏能更好一些吗?是的。那么我们能不管最直接的问题,把他的伤口缝合,然后告诉他正确饮食,然后就训练他开始跑马拉松吗?我们可能可以,但我们真正需要做的就是正视病人的情况,治好有问题的部分,让他更加健康。他可能永远都无法成为奥运会运动员,但是我们不能让“最好”成为“更好”的敌人。代码库可以变得更健康,更容易在其中工作。当病人感觉好一些之后,就到了你可以帮助他进入更健康的生命循环中的时候了。那正是我们对遗留代码所应该做的事情。我们试图回到让我们感觉舒服的那个点;我们期望那样,并试图让修改代码更容易。当我们可以在团队中保持那种感觉的时候,设计就会变得更好。
我在本书中所描述的技术,都是多年以来和客户一起协作试图对无规则的代码加以控制的过程中发现和学到的。我偶尔还会强调遗留代码。当我最初开始在Object Mentor公司工作的时候,我的工作包括帮助团队解决严重的问题,改善他们的技能和交互,帮助他们达到能够持续交付高质量代码的程度。我通常会使用极限编程实践来帮助团队掌控他们的工作,紧密协作,然后交付。我常常觉得极限编程不仅仅是开发软件的一种方式,更应该是创造出好的团队形式的方式,只是恰好以每两周一次的频率交付了优秀的软件。
但是,从最开始就有一个问题。很多最初的XP项目都是从头开始的项目。我见到的客户都拥有非常庞大的代码库,正处于麻烦之中。他们需要某种方式来掌控他们的工作并开始交付。随着时间推移,我发现自己总是和客户一次又一次做着同样的事情。这种感觉在我和一个开发金融项目的团队协作时达到了顶峰。在我参与之前,他们就已经意识到,单元测试是非常好的东西,但是他们所执行的测试是完整场景的测试,会与数据库做多次交互,并执行大量代码。因此非常难以编写测试,而且团队不会经常运行它,因为运行一次要花费太长时间。当我和他们坐在一起打破依赖关系,并为小段代码编写测试的时候,我有一种似曾相识的可怕感觉。看起来我和所有见过的团队都是在做这种工作,而那是一种没有人想要考虑的东西。那是一种乏味的工作,当你想要以可控的方式来处理代码而且知道如何做的时候,才会去做。然后,我决定总结一下我们会如何解决这些问题,并把它们写下来,从而帮助团队让他们的代码更容易处理,那会很有价值。
关于例子还要说明一下:我使用了多种不同编程语言编写的示例。那些例子是由Java、C++和C语言编写的。我选择Java是因为它是一种非常常见的语言,包含了C++的例子是因为它在遗留环境中代表了某些特殊的挑战,而选择C语言是因为它凸显了很多在过程化遗留代码中所存在的问题。通过这三种语言,我覆盖了在遗留代码中出现的大多数问题。然而,如果你所使用的语言并没有出现在示例代码中,那么也要阅读那些代码。我讲述的很多技术都可以用在其他语言中,如Delphi、Visual Basic、COBOL以及FORTRAN。
我希望你会发现本书中的技术很有帮助,让你可以找回编程的乐趣。编程可以是一种回报丰厚并且让人享受的工作。如果你在日常的工作中没有感觉到那一点,我希望我在本书中提供给你的技术能够让你找到那种感觉,并在团队中传播。
如何使用本书
我试过用多种不同的形式来写这本书,直到最后确定为现在的这个样子。当处理遗留代码的时候,很多不同的技术和实践都非常有用,很难独立开来说明。如果你能够找到接缝、创建伪对象、使用一些技术打破依赖关系,那么最简单的修改会变得更加容易。为了让本书更易于理解,随时可用,我决定把很大一部分内容(第二部分)以FAQ(经常问到的问题)的形式来组织。因为特定的技术通常需要使用其他技术,FAQ章节相互之间的关联性很强。在几乎每章中,你都会看到带有章节号的引用,你可以查看其他章节和部分,其中会描述特定的技术和重构。如果这让你在试图寻找问题答案的时候,不得不大范围翻阅本书,那么我非常抱歉,但我认为你最好那么做,而不是一页接一页地阅读,试图理解所有技术是怎么做的。
在第二部分,我试图回答在处理遗留代码的过程中所遇到的常见问题。每章的标题都是一个特定的问题。这让章节的名称很长,但希望那可以让你快速找到帮助你解决特定问题的部分。
在修改软件部分的前面,是一系列介绍性章节(第一部分),后面是一系列重构列表(第三部分),那在处理遗留代码的工作中非常有用。请阅读介绍性章节,特别是第4章。这些章为之后的技术提供了具体情境和命名法。此外,如果你发现没有在上下文中描述的术语,那么就可以在术语表中查找。
第三部分中的重构比较特殊,因为它们是故意在没有测试的情况下完成的,目的是为了编写测试。我建议你阅读所有内容,从而可以在开始驯服遗留代码的时候看到更多的可能性。
致谢
首先,非常感谢我的妻子Ann以及孩子Deborah和Ryan。他们的爱和支持让这本书以及所有的学习成为现实。我还要感谢“Bob大叔”Martin,他是Object Mentor公司的主席和创始人。他严密而有效的开发和设计方法能够把重要内容从无关紧要的内容中分离出来。大概十年前,我快要被大量不切实际的建议所淹没,正是他带领我走出了那段困境。还要感谢Bob给了我机会看到更多代码,并在过去五年间和更多人一起工作,我从来没有想象过能够那样。
我还要感谢Kent Beck、Martin Fowler、Ron Jeffries和Ward Cunningham,他们经常会给我提出建议,并且教给我很多关于团队工作、设计和编程方面的知识。特别要感谢所有审阅了初稿的人。正式审稿人有Sven Gorts、Robert C. Martin、Erik Meade和Bill Wake;非正式审稿人有 Robert Koss博士、James Grenning、Lowell Lindstrom、Micah Martin、Russ Rufer和硅谷伙伴小组以及James Newkirk。
还要感谢审阅了我早期放在网上的书稿的人们,他们的反馈在我重新组织了形式之后,对书的方向产生了很大影响。我先要说声抱歉,因为名单可能会有所遗漏,他们是:Darren Hobbs、Martin Lippert、Keith Nicholas、PhlipPlumlee、C. Keith Ray、Rober Blum、Bill Burris、William Caputo、Brian Marick、Steve Freeman、David Putman、Emily Bache、Dave Astels、Russel Hill、Christian Sepulveda和Brian Christopher Robinson。
还要感谢Joshua Kerievsky,他做了非常关键的早期审阅工作;感谢Jeff Langr,他在我写这本书的整个过程中给出了很多建议,并做了大量审阅工作。
审稿人让我的草稿变得更加合理,但如果还有错误的话,那都是我自己的问题。
感谢Martin Fowler、Ralph Johnson、Bill Opdyke、Don Roberts和John Brant在重构领域做出的卓越工作。那给了我很大启发。
特别要感谢Jay Packlick、Jacques Morel、Sabre Holdings的Kelly Mower、Workshare Technology的Graham Wright,他们都提供了很多支持和反馈。
还要特别感谢Paul Petralia、Michelle Vincenti、Lori Lyons、Krista Hansing,以及Prentice-Hall团队中的所有人。谢谢Paul,你给了我这个第一次写书的人太多帮助和鼓励。
特别感谢Gary和Joan Feathers、April Roberts、 RaimundEge博士、David Lopez de Quintana、Carlos Perez、Carlos M. Rodriguez、John C. Comfort博士,多年来你们给了我大量帮助和鼓励。我还要感谢Brian Button帮忙提供了第21章中的示例,当我们一起开发重构课程的时候,他花费了一个小时来编写那段代码,那是我最喜欢的一段课程用代码。
另外,还要特别感谢Janik Top,他的乐曲De Futura在写这本书的最后几个星期中一直陪伴着我。
最后,我还要感谢过去多年间一起工作的所有同事,他们的深刻见解和挑战让书中的内容更加充实。

Michael Feathers
mfeathers@objectmentor.com
www.objectmentor.com
www.michaelfeathers.com

上架指导

计算机\程序设计

封底文字

修改代码时,你觉得容易吗?当你修改代码时,能否几乎即时地获得反馈?你理解那些代码吗?如果对于这些问题的答案是否定的,那么你面对的就是遗留代码,它们正在浪费你开发工作的时间和金钱。

在本书中,作者为更有效地处理大规模、缺少测试的遗留代码提供了自始至终的策略。本书内容来自Michael创建的非常知名的Object Mentor公司的研习会,Michael使用那些技术来指导并帮助了成千上万位开发者、技术经理和测试人员,让他们的遗留系统处于可控状态。

本书主要内容:
 理解修改软件的机制:添加特性、修正缺陷、改进设计、优化性能
 把遗留代码放到测试用具之中
 编写测试,防止引入新的问题
 包含Java、C++、C和C#的示例,其中介绍的大多数技术适用于其他任何语言或平台
 精确地确定要在哪些地方修改代码
 处理非面向对象的遗留代码
 处理看起来没有任何结构的应用程序

作者简介

(美)Michael C. Feathers 著:暂无简介

译者简介

侯伯薇 译:暂无简介

译者序

翻译完这一本经典的计算机软件著作,不由得想起了自己程序员生涯中多个重要的时刻。
第一次见到传说中的计算机还是在高中时期,听说学校组建了计算机房,就跑到门口去膜拜了一下,当时最好的一台机器是386,令我惊叹不已。可惜的是,当时自己已经高三,而计算机的课程是为高一、高二的同学们准备的,结果就这样和计算机失之交臂。
上大学之后,我终于接触到了计算机,并且开始学习DOS系统,还学会了中英文打字。最神奇的就是,我把从《电脑报》上抄下来的程序键入计算机,用Basic编译执行之后,竟然成功地让计算机上的喇叭发出了音乐声。
大学期间我不仅学习了各种编程技术,还自学了不少其他领域的应用技术,如图像处理、视频编辑、三维动画制作、网页制作等。结果在毕业的时候,阴差阳错,我并没有直接加入程序员的队伍中。然而,似乎是冥冥中有个声音在督促我,所以我一直没有放弃编程技术的学习。
命中注定我会成为一名程序员。两年之后,我加入了一家软件公司,终于继续自己喜欢的程序员生涯,开始用代码来实现自己的价值,编写出各种各样的管理系统。之后多年,直到现在,我很庆幸自己仍然可以每天用编写代码的方式来帮助他人。
我的目标就是成为一名快乐的程序员,所以,在生涯之中会有一些独特的时刻,比方说:
2007年,我第一次和朋友合作,将一本计算机图书从英文翻译成中文,并从此一发而不可收拾。
2008年,我加入了现在这家公司,和业务人员的合作更加紧密,开始不断思考自己编写程序的目的和价值。
2009年,我加入了InfoQ中文站,不仅翻译新闻和文章,还写了不少原创的内容,直到现在还乐此不疲。
2010年,我开始在大连组织程序员社区活动,希望通过自己的努力,建立起一个程序员交流的平台,坚持到现在,已经组织了20多场各种主题的聚会。
2012年,我和CSDN一起做高校巡讲,把自己的一些感悟分享给同学们,虽然各地奔波,但乐在其中。
……
无数个时刻,就像是链条的一个个环节,串在一起,织就了我自己的程序员生涯。
能够翻译这样优秀的一本图书,也是非常重要的一个时刻。当我敲入第一个字母,就和这本书联系在了一起;当完成最后一段的翻译,也并不是和这本书的关系完结,而是联系得更加紧密。
在翻译的过程中,有苦有乐,多亏了家人和朋友的支持,才能够最终完成这项任务,能够让自己几个月的辛苦画上一个还算圆满的句号。千言万语化成一句,感谢!
希望读者朋友在阅读这本书的时候,也能够发现属于自己的那个时刻。阅读完之后,对软件开发会有新的认识,能够在面对大量遗留代码的时候不再手足无措,而是可以耐心地采用各种各样的手段,不断改进,驯服那些原本看起来像怪兽一样的代码,让它们可以更好地发挥作用。
当我们在多年后的某个时刻回顾过往的各个时刻时,相信一定会发现,其实每个时刻都是那么重要。
所以,请大家开始享受阅读这本书的这个时刻吧。

图书目录

译者序

前言
第一部分 修改机制
第1章 修改软件  2
1.1 修改软件的四大原因  2
1.1.1 增加特性和修正缺陷  2
1.1.2 改善设计  4
1.1.3 优化  4
1.2 组合在一起  4
第2章 利用反馈  7
2.1 什么是单元测试  9
2.2 高层次测试  11
2.3 测试覆盖  11
2.4 遗留代码修改方法  14
2.4.1 确定变更点  14
2.4.2 找到测试点  14
2.4.3 打破依赖关系  14
2.4.4 编写测试  15
2.4.5 做出修改并重构  15
2.5 本书其他部分  15
第3章 感知和分离  16
3.1 伪协作程序  17
3.1.1 伪对象  17
3.1.2 伪对象的两面  20
3.1.3 伪对象总结  20
3.1.4 模拟对象  21
第4章 接缝模型  22
4.1 大片的文本  22
4.2 接缝  23
4.3 接缝类型  25
4.3.1 预处理接缝  26
4.3.2 链接接缝  28
4.3.3 对象接缝  31
第5章 工具  36
5.1 自动化重构工具  36
5.2 模拟对象  38
5.3 单元测试用具  38
5.3.1 JUnit  39
5.3.2 CppUnitLite  40
5.3.3 NUnit  41
5.3.4 其他xUnit框架  42
5.4 一般测试用具  42
5.4.1 集成测试框架(Framework for Integrated Test,FIT)  42
5.4.2 Fitnesse  43
第二部分 修改软件
第6章 时间很紧张,但还需要修改  46
6.1 新生方法(Sprout Method)  48
6.2 新生类(Sprout Class)  50
6.3 包装方法  54
6.4 包装类  57
6.5 小结  61
第7章 永远都无法完成的修改  62
7.1 理解  62
7.2 延迟时间  63
7.3 打破依赖关系  63
7.4 构建依赖关系  64
7.5 小结  67
第8章 如何添加新特性  68
8.1 测试驱动开发  68
8.1.1 编写失败的测试案例  69
8.1.2 对其进行编译  69
8.1.3 使其通过  69
8.1.4 去除重复的内容  70
8.1.5 编写失败的测试案例  70
8.1.6 对其进行编译  70
8.1.7 使其通过  71
8.1.8 去除重复的内容  71
8.1.9 编写失败的测试案例  71
8.1.10 对其进行编译  71
8.1.11 使其通过  72
8.1.12 去除重复的内容  73
8.2 根据差异编程  74
8.3 小结  81
第9章 无法把类放到测试用具中  82
9.1 恼人的参数  82
9.2 具有隐藏依赖的情况  88
9.3 构造Blob的情况  90
9.4 恼人的全局依赖  92
9.5 可怕的Include依赖  99
9.6 洋葱皮参数  102
9.7 别名参数  104
第10章 无法在测试用具中运行方法  107
10.1 隐藏方法的情况  107
10.2 “有帮助的”语言特性  110
10.3 检测不到的副作用  112
第11章 我需要修改代码,应该测试哪些方法  119
11.1 推断影响  119
11.2 正向推理  124
11.3 影响传播  128
11.4 推理影响的工具  129
11.5 从影响分析中学习  131
11.6 简化影响草图  132
第12章 我需要在一个地方做多处变更,需要为所有涉及的类打破依赖关系吗  134
12.1 拦截点  135
12.1.1 简单的情况  135
12.1.2 更高层次的拦截点  137
12.2 使用夹点来判断设计  140
12.3 夹点陷阱  141
第13章 我需要修改代码,但不知道要编写哪些测试  142
13.1 鉴定测试  142
13.2 鉴定类  145
13.3 定向测试(Targeted Testing)  146
13.4 编写鉴定测试的启示  150
第14章 对库的依赖让我快要崩溃了  151
第15章 应用全是API调用  153
第16章 对代码理解不够,所以无法修改  160
16.1 做笔记,画草图  160
16.2 列表标记  161
16.2.1 分离职责  162
16.2.2 理解方法结构  162
16.2.3 提取方法  162
16.2.4 理解变更的影响  162
16.3 临时重构  162
16.4 删除没有用的代码  163
第17章 应用没有结构  164
17.1 讲述系统的故事  165
17.2 裸CRC  167
17.3 对话审查(Conversation Scrutiny)  170
第18章 测试代码挡路了  171
18.1 类命名规范  171
18.2 测试位置  172
第19章 项目并非面向对象,如何才能够安全地修改  174
19.1 简单的案例  174
19.2 困难的案例  175
19.3 增加新行为  178
19.4 充分利用面向对象  180
19.5 完全面向对象  183
第20章 类太大了,我不想让它继续膨胀  186
20.1 查看职责  188
20.2 其他技术  199
20.3 继续前进  199
20.3.1 策略  199
20.3.2 战术  200
20.4 提取类之后  201
第21章 在各个地方修改的都是同样的代码  202
第22章 我需要修改一个巨兽方法,但无法为其编写测试  218
22.1 巨兽的种类  218
22.1.1 无序方法  218
22.1.2 缠结的方法  219
22.2 使用自动重构支持来对付巨兽  221
22.3 手动重构挑战  224
22.3.1 引入检测变量  224
22.3.2 提取你所知道的内容  227
22.3.3 收集依赖  228
22.3.4 打破方法对象  229
22.4 策略  229
22.4.1 记下方法的概要  230
22.4.2 找到序列  230
22.4.3 首先提取到当前类  231
22.4.4 提取小段代码  231
22.4.5 准备好重做提取  231
第23章 如何知道没有造成任何破坏  232
23.1 超感编辑(Hyperaware Editing)  232
23.2 单一目标编辑  233
23.3 保留签名  234
23.4 依赖于编译器  236
23.5 结对编程  238
第24章 我要崩溃了,它不会再有任何改进  239
第三部分 打破依赖的技术
第25章 打破依赖的技术  242
25.1 调整参数  242
25.2 分解方法对象  245
25.3 完善定义  251
25.4 封装全局引用  252
25.5 暴露静态方法  257
25.6 提取并重写调用  259
25.7 提取并重写工厂方法  261
25.8 提取并重写getter方法  262
25.9 提取实现器  265
25.10 提取接口  269
25.11 引入实例委托器  274
25.12 引入静态设置器  275
25.13 链接替换  280
25.14 参数化构造函数  280
25.15 参数化方法  284
25.16 原始化参数(Primitivize Parameter)  285
25.17 上推特性  287
25.18 下推依赖  290
25.19 使用函数指针替换函数  293
25.20 使用getter方法替换全局引用  295
25.21 创建子类并重写方法  297
25.22 替代实例变量  299
25.23 模板重定义  302
25.24 文本重定义  305
附录 重构  307
术语表  311

教学资源推荐
作者: 郑阿奇,梁敬东 主编
作者: Y. Daniel Liang
参考读物推荐
作者: Ivor Horton
作者: (美)Stephen Ritchie 著
作者: (印度)波哈维·荻西特(Bharvi Dixit)著