重构之维——关于重构及《重构》的随想
我很少给自己参与其中的书籍做评论,因为这样的评论会同时失去公允和陌生感,而这两者恰好都是优秀书评的要素。对于这本即将出版的《重构》,我也有同样的尴尬。如果重新拿起这本书,在查找“重构细目”之前,我会想些什么呢?既然已经没有评论的可能,我就邀读者分享这些凌乱的思绪吧。 曾经多次与朋友谈起,翻译是一项有趣的工作,而以译本作为研究资料则是不负责任的态度。“重构”这个词就是在这项“有趣的工作”中遭到了广泛误解和滥用的词汇之一。印象中最早见到这个词,是在哈贝马斯的著作中。哈老更喜欢的“Nachkonstruktion”(后构)一词,在译成英文时无可避免地被替换成了更容易理解的“Reconstruction”——重构。这个带着陌生的异国风情、描述一种特定研究行为的词汇,很快地被中国的文化人们滥用了。 进入上世纪90年代之后,在对工业化、“现代化”的一片讨伐声中,在对文艺复兴精神的热切渴求中,一大串以“re”开头的词汇在产业界应运而生:re-organize、re-structure、re-engineer、re-design……颇有兴味的是,在单独使用时,这些明显带着华尔街气味的词汇或多或少都曾经被译为“重构”,也许是为了借哲学界一口仙气? 自Alexander以下,常常有人将软件与建筑类比。不幸的是,软件理论家们没有学到别的,倒是先学来了“现代性”——结构主义的话语方式。当“软件工程家”们热衷于科层制管理、追求完美的设计结构时,我们只能庆幸商场生存竞争的残酷性让他们没有机会继续自己的尝试。当结构主义的尝试陷入困境,解构主义的话语立即甚嚣尘上:RAD和“good enough”的思路让人们觉得就连写文档都是一件无谓的多余劳动。80年代到90年代,刀劈斧砍(crack)式的软件开发与个人英雄主义的程序员终于脱离了大型企业和大型主机的桎梏,游侠般的传奇如同西部故事一样诱人(并且一样虚幻)。直接促发这个后现代浪潮的无疑是PC的出现和微软的一系列成就,而共享软件(share software)的淘金梦则需要对程序员迅速向着过度解构方向的滑落承担责任。 幸而这个局面也没有维持太久。Java带来的不仅仅是一种新的语言和一个新的平台,还有对经院派软件结构主义的回归与重构。与C一脉相承的语法,以及来自Smalltalk的语意,使Java成为了价值重构的旗手。至此,我们的“重构”(refactoring)在Java社群中浮出水面,也就不足为奇了。 不论是德国哲学家爱用的rekonstruktion,还是美国企业家爱用的reengineering,都带着一种“破坏性”——全面解构之后的重构,这是后现代主义者常用的套路。沃尔夫冈·韦尔施的Undoing Aesthetics也被译为《重构美学》,可见“重构”这个词的确是有“推翻一个旧世界”的魄力。不过,《重构》中的refactoring并没有这样的破坏性。实际上,refactoring的第一要素就是语义保持,在不改变程序可观察行为的前提下再考虑改进内在结构。所以,虽然同样被译为“重构”,但refactoring是一个更加保守、更加谨慎的过程。 对于“重构”这个词,更重要的或许是“构”。当你重构的时候,你是在构建什么?我看到的答案有两种方向:Martin Fowler说,你构建的是自描述的程序,是能够让阅读者无须借助文档即可理解的代码;Joshua Kerievsky说,你构建的是设计模式(design patterns),是摆脱了过度工程(over-engineering)的优雅设计。在我看来,重构要求程序员构建一种责任感,对代码、对同事、对职业的责任感,这是软件工程和RAD都忽略了的东西。 记得有一篇书评把这本Refactoring与Design Patterns、Anti-Patterns和eXtreme Programming Explained并列为“Java行业的圣经”。对于这位评论者,纵使客气点不说他不学无术,我至少会认为他孤陋寡闻(四本“圣经”中竟然有两本来自Martin Fowler的才思)。或许有个人感情因素,我讨厌把《重构》奉为经典。在宣扬一种力求保持、渐进发展的技术手段时,《重构》不愿意给它的读者醍醐灌顶式的加持,而是更乐于让读者体味“吃饭穿衣即是人伦物理”的生活方式。是的,在我看来,重构更多的是一种生活方式,或许就像程序员们最初在代码中加上缩进一样平实。而经典,那是一个高山仰止的词,我害怕它会给读者预备下一种错误的阅读心态。 既然重构是一种重视保持现状的技术,那么我也希望读者不要因为这本书而让自己的生活方式发生翻天覆地的改变。可惜Martin Fowler写这本书的时间早了些,他只能告诉读者JUnit、手工重构,还有传说中的Refactoring Browser。为了弥补这一点点缺陷,我请你首先去下载一个Eclipse,学会在其中使用JUnit,学会它已经提供的几个简单重构(从最常用的Extract Method开始吧),然后再打开这本《重构》——另外,始终牢记懒惰是程序员的美德,不要因为一时兴奋就勤快地重构自己的代码。 《重构》是一本这样的书:也许你读完一遍之后将不会再读第二遍,但却会时时刻刻想起它,因为它已经潜移默化了你的习惯。如果你读完它之后觉得“我已经学会重构了”,很遗憾,你什么都没有学会。这时,也许你应该让自己平静下来,想一想“重构”这个词,再试着在自己的代码中做一点重构。直到有一天你已经完全忘掉这本书,却已经在随时对自己的代码进行重构,那时你才是真正“学会”了——不过那时你已经浑然不觉这回事了。这是在想象中重新捧起《重构》的一瞬间,我的脑海里闪现的一些念头。这样散乱的文字会对你有所帮助吗?我不知道,我只是自说自话而已。那么,对于这本书的评价在哪里?它只在你那里。如人饮水,冷暖自知。
《重构》究竟重构了什么?
不止一次地,我听到我们这个行业里的大师们对重构技术提出(至少是)置疑:“那是我们过去十五年里一直在做的事”、“我从(上世纪)70年代就已经开始这样做了”、“Unix上的黑客们一直都是这样做的” ……这些说辞让我很有兴趣探其究竟。在这本《重构》里,Martin Fowler到底给他的读者们提供了什么?《重构》,它是揭示新时代的福音书,还是换汤不换药的广告词? 重构(名词):对软件内部结构的一种调整,目的是在不改变软件可观察之行为的前提下提高其可理解性、降低其修改的成本。 重构(动词):使用一系列的重构动作,在不改变软件可观察之行为的前提下调整其结构。 这是一个平实得有点乏味的定义。而重构,也就是这样一种平实得近乎乏味的技术——或者套用我前面的话,生活方式。如同大多数习惯了C和C++的老程序员一样,Eric Raymond在读到这本《重构》时的第一反应是:“嘿,小伙子,不就是边写代码边修改吗?我们管这个叫‘hacking’ !”自然,顺理成章地,他的第二反应是:“Martin这家伙,装得他好象压根不知道‘hacking’这么回事似的。他到底真傻还是装傻?” 请容许我暂时打断Eric(抑或是你,我的读者)的思绪。和中国的大学不同,伊利诺斯大学计算机系的博士学位不是那么容易拿到的,尤其在当你的导师是Ralph Johnson时。William Opdyke用他的博士论文奠定了重构技术的理论基础,而这篇博士论文的核心则是对“行为保持”的研究。简言之,在这篇论文中,William用数学方法证明,在满足特定条件的情况下,以特定形式进行的程序修改将不影响程序的行为(也即“行为保持”),并且行为保持的修改之间的组合也将继续是行为保持的 。于是,从诞生的第一天起,重构技术的双脚就牢牢地站在大地母亲的怀抱中。 Eric Raymond之所以能成为自由软件的代言人,很大程度上得利于敏锐的技术嗅觉。他的第三反应是:“嘿,Martin介绍的这些东西的确比黑客们的办法要好。”黑客文化向来缺乏理论家。当然,有那么几位注重方法学的“理论派”黑客,例如Richard Stallman、Larry Wall,还有我们的Eric。但黑客们几乎总是通过口耳相授、耳濡目染的方式来传递最重要的经验,这也是不争的事实。而Martin Fowler的重构技术,它建立在完备的理论基础之上,并且有完善的方法学指导(包括小步迭代、频繁构建、测试优先等“敏捷联盟”倡导的实践),这使得它不再完全依赖于程序员的天赋。黑客的价值观是“你是笨蛋,所以你学不会hacking”,而重构的价值观是“如果你不去学重构,你才真是个笨蛋”——相比之下,你会更喜欢哪一种呢? 黑客们会对重构和敏捷方法感到熟悉和亲近。和hacking的传统相似,重构的文化强调人重于过程与工具、软件产品重于文档、与客户的协作重于对合同的谈判、积极回应变化重于遵循既有计划。不同的是,重构文化有坚实的理论根基和方法学保障,还有最先进的工具提供支持,使得工作重压之下的程序员能够更加轻松地学习、使用它,并从中受益。 如果说Unix和黑客是软件开发的古希腊,重构就是让古希腊的向往者们感到似曾相识的文艺复兴。《重构》,以及Martin Fowler致力的敏捷联盟,把程序员的心带向浪漫的奥林匹斯之巅,并用最新的理论和技术赋予他们自由飞翔的翼。这,就是《重构》对软件开发价值观的重构。