# 译序 by 侯捷
见过铁路道班工人吗?提着手持式砸道机,机身带着钝钝扁扁的钻头,在铁道上、枕木间卖力地「砍劈钻凿」。他们在做什么?他们在使路基上的碎石块(道碴〉因持续剧烈的震动而翻转方向、滑动位置,甚至震碎为更小石块填满缝隙,以求道碴更紧密契合,提供铁道更安全更强固的体质。
当「重构」(refactoring〉映入眼帘,我的大脑牵动「道班工人+电动砸道机+枕木道碴」这样一幅联想画面。「重构」一词非常清楚地说明了它自身的意义和价值:在不破坏可察功能的前提下,借由搬移、提炼、打散、凝聚…,改善事物的体质。很多人认同这样一个信念:「非常的建设需要非常的破坏」,但是现役的应用软件、构筑过半的项目、运转中的系统,容不得推倒重来。这时候,在不破坏可察功能的前提下改善体质、强化当前的可读性、为将来的扩充性和维护性做准备、乃至于在过程中找出潜伏的「臭虫」,就成了大受欢迎的稳步前进的良方。
作为一个程序员,任谁都有看不顺眼手上代码的经验一代码来自你邻桌那个菜鸟,或三个月前的自己。面临此境,有人选择得过且过;然而根据我对「程序员」人格特质的了解,更多人盼望插手整顿。挽起袖子剑及履及,其勇可嘉,其虑未缜。过去或许不得不暴虎凭河,忍受风险。现在,有了严谨的重构准则和严密的重构手 法,「稳定中求发展」终于有了保障。
是的,把重构的概念和想法逐一落实在严谨的准则和严密的手法之中,正是这本《Refactoring》的最大贡献。重构?!呵呵,上进的程序员每天的进行式,从来不新鲜,但要强力保证「维持程序原有的可察功能,不带进新臭虫」,重构就不能是一项靠着天份挥洒的艺术,必须是一项工程。
**我对本书的看法**
初初阅读本书,屡屡感觉书中所列的许多重构目标过于平淡,重构步骤过于琐屑。这些我们平常也都做、习惯大气挥洒的动作,何必以近乎枯燥的过程小步前进?然后,渐渐我才体会,正是这样的小步与缓步前进,不过激,不躁进,再加上完整的测试配套〔是的,测试之于重构极其重要),才是「不带来破坏,不引入臭虫」的最佳保障。我个人其实不敢置信有谁能够乖乖地按步遵循实现本书所列诸多被我(从人的角度〉认为平淡而琐屑的重构步骤。我个人认为,本书的最大价值,除了呼吁对软件质量的追求态度,以及对重构「工程性」的认识,最终最重要的价值还在于:建立起吾人对于「目前和未来之自动化重构工具」的基本理论和实现技术上的认识与信赖。人类眼中平淡琐屑的步骤,正是自动化重构工具的基础。机器缺乏人类的「大局观」智慧,机器需要的正是切割为一个一个极小步骤的指令。一板一 眼,一次一点点,这正是机器所需要的,也正是机器的专长。
本书第14章提到,Smalltalk开发环境已含自动化重构工具。我并非Smalltalk guy,我没有用过这些工具。基于技术的飞快滚动(或我个人的孤陋寡闻),或许如今你已经可以在java,C++等面向对象编程环境中找到这一类自动化重构工具。
软件技术圈内,重构(refactoring)常常被拿来与设计模式(design patterns)并论。 书籍市场上,《Refactoring》也与《Design patterns》齐名。GoF曾经说『设计模式为重构提供了目标』,但本书作者Martin亦言『本书并没有提供助你完成所有知名模式的重构手法,甚至连GoF的23个知名模式都没有能够全部覆盖。』我们可以从这些话中理解技术的方向,以及书籍所反映的局限。我并不完全赞同Martin所言『哪怕你手上有一个糟糕的设计或甚至一团混乱,你也可以借由重构将它加工成设计良好的代码。』但我十分同意Martin说『你会发现所谓设计不再是一切动作的前提,而是在整个开发过程中逐渐浮现出来。』我比较担心,阅历不足的程序员在读过这本书后可能发酵出「先动手再说,死活可重构」的心态,轻忽了事前优秀设计的重要性。任何技术上的说法都必须有基本假设;虽然重构(或更向上说XP,eXtreme Programming)的精神的确是「不妨先动手」,但若草率行事,代价还是很高的。重型开发和轻型开发各有所长,各有应用,世间并无万应灵药,任何东西都不能极端。过犹不及,皆不可取!
当然,「重构工程」与「自动化重构工具」可为我们带来相当大幅度的软件质量提升,这一点我毫无异议,并且非常期待。
**关于本书制作**
此书在翻译与制作上保留了所有坏味道(bad smell)、重构(refactoring)、设计模式(design patterns)的英文名称,并表现以特殊字体;只在封面内页、目录、小节标题中相应地给出一个根据字面或技术意义而做的中文译名。各种「坏味道」名称尽量就其意义选用负面字眼,如泥团、夸夸、过长、过大、过多、情结、偏执、惊 悚、狎昵、纯稚、冗赘…。这些其实都是助忆之用,与茶余饭后的谈资(以及读者批评的根据)。
原书各小节并无序号。为参考、检索或讨论时的方便,我为译本加上了序号。
木书保留相当份量的英文术语,时而英中并陈(英文为主,中文为辅)。这么做的考量是,本书读者不可能不知道class, final, reference,public,package...这些简短的、与编程息息相关的用词。另-方面,我确实认为,中文书内保留经过挑选的某些英文术语,有利于整体阅读效果。
两个需要特别说明的用词是Java编程界惯用的"field"和"method"。它们相当于C++的"data member"和"member function"。由于出现次数实在频繁,为降低中英夹杂程度,我把它们分别译为「值域」和「函数」一如果将"method"译为「方法」,恐怕术语突出性不高。本书将"type"译为「型别」而非「类型」,亦是为 了中文术语之突出性;"instance"译为「实体」而非「实例」、"argument"译为「引数」而非「实参」,有意义上的考量。「static值域与reference值域」、「reference对象value对象」等等则保留部分英文,并选用如上的特殊字体。凡此种种,相信一进入书中您很快可以感受本书术语风格。
本书还有诸多地方采中英并陈(中文为主,英文为辅)方式,意在告诉读者,我们 (译者〕深知自己的不足与局限,惟恐造成您对中译名词的误解或不习惯,所以附上原文。
中文版(本书〕已将英文版截至2003/06/18为止之勘误,修正于纸本。
**一点点感想**
Martin Fowler表现于原书的写作风格是:简洁,爱用代名词和略称。这使得读者往往需要在字面上揣度推敲。我期盼(并相信)经过技术意义的反刍、中英术语的并陈、中文表述的努力,中文版(本书〕在阅读时间、理解时间和记忆深度上,较之英文版,能够为以华文为母语的读者提高10倍以上的成效。
本书由我和熊节先生合译。熊节负责第一个pass,我负责后继工作。中文版(本书〉为读者带来的阅读和理解上的效益,熊节居于首功一虽说做的是第一个pass,我从初稿质量便可看出他多次反复推敲和文字琢磨的刻痕。至于整体风格、中英术语的选定、版面的呈现、乃至于全盘技术内涵的表现,如果有任何差错,责任都是我的。
作为一个信息技术教育者,以及一个信息技术传播者,我在超过10年的写译历程中,观察了不同级别的技术书品在读书市场上的兴衰起伏。这些适可反映大环境下技术从业人员及学子们的某些面向和取向。我很高兴看到我们的中文技术书籍(著译皆含〗从早期盈盈满满的初阶语言用书,逐渐进化到中高阶语言用书、操作系统、技术内核、程序库/框架、再至设计/分析、软件工程。我很高兴看到这样的变化,我很高兴看到《Design Patterns》、《Refactoring》、《Agile...》、《UML...》、《XP…》之类的书在中文书籍市场中现身,并期盼它们有丰富的读者。
中文版(本书〕支援网站有一个「术语英中繁简」对照表。如果您有需要,欢迎访问,网址如下,并欢迎给我任何意见。谢谢。
侯捷2003/06/18于台湾.新竹
jjhou@jjhou.com(电子邮箱)
[http://www.jjhou.com(繁体)(术语对照表http://www.jjhou.com/terms.htm](http://www.jjhou.xn--com%28%29%28http-ob4zp97n8r4b5y3bzn4c7x5b95q//www.jjhou.com/terms.htm))
- 译序 by 侯捷
- 译序 by 熊节
- 序言
- 前言
- 章节一 重构,第一个案例
- 起点
- 重构的第一步
- 分解并重组statement()
- 运用多态(Polymorphism)取代与价格相关的条件逻辑
- 结语
- 章节二 重构原则
- 何谓重构
- 为何重构
- 「重构」助你找到臭虫(bugs)
- 何时重构
- 怎么对经理说?
- 重构的难题
- 重构与设计
- 重构与性能(Performance)
- 重构起源何处?
- 章节三 代码的坏味道
- Duplicated Code(重复的代码)
- Long Method(过长函数)
- Large Class(过大类)
- Long Parameter List(过长参数列)
- Divergent Change(发散式变化)
- Shotgun Surgery(散弹式修改)
- Feature Envy(依恋情结)
- Data Clumps(数据泥团)
- Primitive Obsession(基本型别偏执)
- Switch Statements(switch惊悚现身)
- Parallel Inheritance Hierarchies(平行继承体系)
- Lazy Class(冗赘类)
- Speculative Generality(夸夸其谈未来性)
- Temporary Field(令人迷惑的暂时值域)
- Message Chains(过度耦合的消息链)
- Middle Man(中间转手人)
- Inappropriate Intimacy(狎昵关系)
- Alternative Classes with Different Interfaces(异曲同工的类)
- Incomplete Library Class(不完美的程序库类)
- Data Class(纯稚的数据类)
- Refused Bequest(被拒绝的遗贈)
- Comments(过多的注释)
- 章节四 构筑测试体系
- 自我测试代码的价值
- JUnit测试框架
- 添加更多测试
- 章节五 重构名录
- 重构的记录格式
- 寻找引用点
- 这些重构准则有多成熟
- 章节六 重新组织你的函数
- Extract Method(提炼函数)
- Inline Method(将函数内联化)
- Inline Temp(将临时变量内联化)
- Replace Temp with Query(以查询取代临时变量)
- Introduce Explaining Variable(引入解释性变量)
- Split Temporary Variable(剖解临时变量)
- Remove Assignments to Parameters(移除对参数的赋值动作)
- Replace Method with Method Object(以函数对象取代函数)
- Substitute Algorithm(替换你的算法)
- 章节七 在对象之间搬移特性
- Move Method(搬移函数)
- Move Field(搬移值域)
- Extract Class(提炼类)
- Inline Class(将类内联化)
- Hide Delegate(隐藏「委托关系」)
- Remove Middle Man(移除中间人)
- Introduce Foreign Method(引入外加函数)
- Introduce Local Extension(引入本地扩展)
- 章节八 重新组织数据
- Self Encapsulate Field(自封装值域)
- Replace Data Value with Object(以对象取代数据值)
- Change Value to Reference(将实值对象改为引用对象)
- Replace Array with Object(以对象取代数组)
- Replace Array with Object(以对象取代数组)
- Duplicate Observed Data(复制「被监视数据」)
- Change Unidirectional Association to Bidirectional(将单向关联改为双向)
- Change Bidirectional Association to Unidirectional(将双向关联改为单向)
- Replace Magic Number with Symbolic Constant(以符号常量/字面常量取代魔法数)
- Encapsulate Field(封装值域)
- Encapsulate Collection(封装群集)
- Replace Record with Data Class(以数据类取代记录)
- Replace Type Code with Class(以类取代型别码)
- Replace Type Code with Subclasses(以子类取代型别码)
- Replace Type Code with State/Strategy(以State/strategy 取代型别码)
- Replace Subclass with Fields(以值域取代子类)
- 章节九 简化条件表达式
- Decompose Conditional(分解条件式)
- Consolidate Conditional Expression(合并条件式)
- Consolidate Duplicate Conditional Fragments(合并重复的条件片段)
- Remove Control Flag(移除控制标记)
- Replace Nested Conditional with Guard Clauses(以卫语句取代嵌套条件式)
- Replace Conditional with Polymorphism(以多态取代条件式)
- Introduce Null Object(引入Null 对象)
- Introduce Assertion(引入断言)
- 章节十一 处理概括关系
- Pull Up Field(值域上移)
- Pull Up Method(函数上移)
- Pull Up Constructor Body(构造函数本体上移)
- Push Down Method(函数下移)
- Push Down Field(值域下移)
- Extract Subclass(提炼子类)
- Extract Superclass(提炼超类)
- Extract Interface(提炼接口)
- Collapse Hierarchy(折叠继承关系)
- Form Template Method(塑造模板函数)
- Replace Inheritance with Delegation(以委托取代继承)
- Replace Delegation with Inheritance(以继承取代委托)
- 章节十二 大型重构
- 这场游戏的本质
- Tease Apart Inheritance(梳理并分解继承体系)
- Convert Procedural Design to Objects(将过程化设计转化为对象设计)
- Separate Domain from Presentation(将领域和表述/显示分离)
- Extract Hierarchy(提炼继承体系)
- 章节十三 重构,复用与现实
- 现实的检验
- 为什么开发者不愿意重构他们的程序?
- 现实的检验(再论)
- 重构的资源和参考资料
- 从重构联想到软件复用和技术传播
- 结语
- 参考文献
- 章节十四 重构工具
- 使用工具进行重构
- 重构工具的技术标准(Technical Criteria )
- 重构工具的实用标准(Practical Criteria )
- 小结
- 章节十五 集成
- 参考书目