# 譯序 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 )
- 小結
- 章節十五 集成
- 參考書目