具体描述
世界级计算机专家Michael C. Feathers的经典之作,软件开发大师Robert C. Martin作序倾情推荐,修改遗留代码的权威指南。深入剖析修改遗留代码的各种方法和策略,从理解遗留代码、为其编码测试、重构及增加特性等方面给出大量实用建议,是所有程序开发人员必读之作。
修改代码时,你觉得容易吗?当你修改代码时,能否几乎即时地获得反馈?你理解那些代码吗?如果对于这些问题的答案是否定的,那么你面对的就是遗留代码,它们正在浪费你开发工作的时间和金钱。
在本书中,作者为更有效地处理大规模、缺少测试的遗留代码提供了自始至终的策略。本书内容来自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、敏捷之旅等活动上做过技术演讲
目录信息
译者序
序
前言
第一部分 修改机制
第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
· · · · · · (收起)
读后感
如果你想重构,重要的前提就是有强力的测试.哪怕你有自动化重构工具在手. 如果你想对既有代码进行测试,你就必须先重构,因为代码根本就没有办法在测试工具中实例化. …… 新写的代码大多是可以先进行测试,然后再挂接到原有代码中.而对付遗留的代码,我们则需要一点点地把代码抠出...
一两个月前看到了这本书,那时候正对编写高质量的代码很感兴趣,于是借来读。这一个月断断续续的读完,实际上读书的时间仅有10天左右的业余时间。读的很浅,但也有小小的收获。 这本书讲解如何在不漂亮的旧代码下写漂亮的新代码,依照先有测试后有功能的思想,作者全书都围绕...
买这本书的原因一是这本书确实是一本关于修改老代码的经典,二来翻译者是中国地区 InfoQ 的主编。 但是入手看了大概到100多页之后实在是忍不住要上来吐槽一下。 首先是翻译的通畅性,应该说是比较烂的水准<del>只能说是将将达到合格的水准,</del>这个可能是个人的偏见。但是...
如果你想重构,重要的前提就是有强力的测试.哪怕你有自动化重构工具在手. 如果你想对既有代码进行测试,你就必须先重构,因为代码根本就没有办法在测试工具中实例化. …… 新写的代码大多是可以先进行测试,然后再挂接到原有代码中.而对付遗留的代码,我们则需要一点点地把代码抠出...
用户评价
我一直觉得,编程就像是一场永无止境的“寻宝”之旅,而《修改代码的艺术》这本书,就是我的“藏宝图”。它带领我穿越代码的迷宫,发现那些隐藏在深处的“宝藏”——那些能够显著提升代码质量、性能和可维护性的修改策略。我非常赞赏作者在书中强调的“上下文意识”的重要性,他告诉我们,每一次的代码修改,都必须建立在对整个系统、对业务逻辑、对团队协作的深刻理解之上。书中关于“自动化测试”的讨论也让我茅塞顿开,我之前总觉得测试是额外的负担,但读了这本书才明白,它是代码修改的“安全网”,是保证修改质量的关键。作者通过一系列具体的例子,展示了如何利用自动化测试来支持代码的修改,如何让修改变得更加自信和高效。这本书不仅仅是关于“如何修改代码”,更是关于“如何进行一次有价值的代码修改”,它让我明白,每一次的修改,都是一次学习和成长的机会,都是在为软件的未来添砖加瓦。
《修改代码的艺术》这本书,与其说是一本技术手册,不如说是一本关于“软件生命周期管理”的哲学读物。它让我意识到,代码并非一成不变的“活化石”,而是在不断演变和成长的生命体。作者以一种令人耳目一新的视角,探讨了如何与代码“和平共处”,如何在不冒犯“老祖宗”留下来的设计原则的前提下,为代码注入新的活力。我特别喜欢书中关于“代码的演进”的论述,作者通过对几个著名开源项目的演进过程进行深入分析,揭示了代码是如何在时间和实践中不断迭代、优化的。这让我对“修改”有了更深刻的认识,它并非意味着“错误”或“不足”,而是“进步”和“适应”的代名词。书中关于“风险评估”的部分也做得非常出色,作者教会我们如何在修改代码时,预见潜在的风险,并采取相应的措施来规避,从而确保代码的稳定性和健壮性。这本书不仅仅是教你如何写出更好的代码,更是教你如何去“理解”和“尊重”代码,以及如何与你的代码一起成长。
我一直觉得,代码的优化和维护,就像是给房屋做装修。你可以直接推倒重来,也可以在不影响居住的前提下,一点一点地改进。而《修改代码的艺术》这本书,正是后一种“温和而有效”的装修指南。它没有提供那些“一键优化”的神奇药方,而是教会我们如何像一位精明的建筑师一样,去审视代码的结构,去理解其内在的逻辑,然后以最小的代价,实现最大的价值。书中对“代码审查”的论述尤其让我受益匪浅,不仅仅是检查语法错误,更重要的是去理解代码的意图,去发现潜在的设计缺陷,去引导作者思考更优的实现方式。我尤其喜欢作者在描述“渐进式改进”时的比喻,就像是在现有画布上添加新的色彩,而不是将整幅画作废。这让我意识到,很多时候,我们需要的不是推翻,而是巧妙的“点石成金”。这本书不仅仅是写给程序员看的,我认为任何参与软件开发过程的人,包括产品经理、项目经理,甚至是对软件产品感兴趣的普通读者,都能从中获得启发,理解那些“看不见”的代码是如何塑造我们日常使用的软件的。
这本《修改代码的艺术》真是一场令人惊叹的阅读体验!我本以为会看到一堆枯燥的技术指南,结果却发现自己沉浸在一系列引人入胜的案例研究中,作者用极其生动和富有洞察力的方式,剖析了那些看似微不足道的代码修改,是如何在复杂系统中引发涟漪效应,甚至彻底改变产品走向的。尤其令我印象深刻的是其中关于“遗留代码的重生”那一章,作者并没有简单地教你如何“重构”,而是深入探讨了在不破坏现有功能的前提下,如何逐步引入新的设计理念,如何与团队其他成员有效沟通,最终将一个陈旧、难以维护的代码库,变成一个充满活力、易于扩展的现代化系统。书中关于“技术债”的论述也并非空泛的理论,而是结合了大量的实际操作细节,从如何识别,到如何量化,再到如何制定切实可行的偿还计划,每一步都充满了智慧和实战经验。读到这里,我仿佛看到了自己曾经困扰过的那些项目,找到了解决问题的思路和方法。作者的语言风格非常流畅,即使是复杂的技术概念,也能被他解读得通俗易懂,并且充满了人文关怀,让我感觉这不是在学习代码,而是在学习如何成为一个更优秀、更负责任的软件工程师。
当我翻开《修改代码的艺术》这本书时,我脑海里浮现的画面是那些在深夜里,面对堆积如山的bug和模糊不清的需求,苦苦挣扎的程序员。而这本书,简直就是他们最好的伙伴,一本写满了智慧和同情心的指导手册。它没有那种高高在上的说教,也没有那些不切实际的理论,而是用一种非常接地气的方式,带你走进代码修改的真实世界。我特别欣赏书中关于“保持简单”的理念,作者反复强调,最优雅的代码修改,往往是最简单的那个。他通过一系列生动的例子,展示了如何避免过度设计,如何识别并移除冗余,如何让代码变得更容易理解和维护。读到那些关于“技术债务”的章节,我感觉自己被深深地理解了,作者深刻地剖析了技术债务的形成原因,以及它对项目长期发展带来的负面影响,并给出了一系列切实可行的解决方案。这本书让我明白,代码的修改,不仅仅是技术活,更是一种艺术,一种在不断变化的需求和约束下,追求卓越和可持续性的艺术。
经典之作,改bug的境界
深入,透彻,具体
1. 原书绝对是一本经典 2. 候伯薇翻译的这版简直太烂了,成吨的烂翻译和文字错误 3. 想看看刘未鹏翻译的版本。
这里再重复一遍重构的定义——在保持代码行为的基础上,提升代码的质量。重构专注于第二步,即如何提升代码的质量,而修改代码的艺术专注于第一步,即如何保持代码的行为。 提升代码质量并不困难,但保持代码行为就难多了,尤其是对没有测试的遗留代码(Legacy Code)而言——你需要首先引入测试,但遗留代码往往可测试性(Testability)很差,这时你就需要把代码变的可测试。修改代码的艺术包含大量的实用建议,用来把代码变的可测试(Testable),从而使重构变为可能,使提高代码质量变为可能。
1. 原书绝对是一本经典 2. 候伯薇翻译的这版简直太烂了,成吨的烂翻译和文字错误 3. 想看看刘未鹏翻译的版本。