重構:改善既有程式的設計
— Refactoring : improving the design of existing code 重構:改善既有程式的設計 — Refactoring : improving the design of existing code
———————————–
作者/Martin Fowler/等著
譯者/侯捷, 熊節/譯
出版社/碁峰 出版
ISBN/9867594061

內容簡介
當物件技術成為老生常談之後 — 尤其在 Java 編程語言之中,新的問題也在軟體開發社群中浮現了出來。缺乏經驗的開發人員完成了大量粗劣設計,獲得的程式不但缺乏效率,也難以維護和擴展。漸漸地,軟體系統專家發現,與這些沿襲下來的、品質不佳的程式共處,是多麼艱難。物件專家運用許多(而且日漸更多)技術來改善既有程式的結構完善性與性能,已有數年之久。但是這些被稱為「重構」(refactoring)的實踐技術,一直(只)流傳在專家領域內,因為沒有人願意將全部這些知識錄寫為所有開發人員可讀的形式。這種情況如今終於結束。在《Refactoring: Improving the Design of Existing Code》書中,知名的物件技術者 Martin Fowler 闖入新的領域,褪去那些名家實踐手法的神秘面紗,並展示軟體從業人員領悟這種新過程的重大意義。

只要受過適度訓練,一位技巧嫻熟的系統程式員可以在拿到一個糟糕的設計之後,把它翻新為設計良好、穩健強固的程式碼。本書之中,Martin Fowler 告訴你重構機會通常可以在哪裡找到,以及如何將一個糟糕的設計重新修訂為一個良好的設計。每個重構步驟都十分簡 — 簡單到了似乎不值得去做的程度。重構涉及將欄位(field)從一個 class 搬移到另一個class,或將某些程式碼拉出來獨立為另一個函式(method),或甚至將某些程式碼上下移動於繼承體系(hierarchy)之中。這些個別步驟雖然可能十分基本,積累下來的影響卻能夠徹底改善設計。重構已經被證明可以阻止軟體的腐朽與衰敗。

除了討論各式各樣的重構技術,作者還提供了一份詳細名錄(catalog),其中有超過 70個已被證明效果的重構手法,以饒富幫助的重點,教導你實施的時機,實施時的逐步指令。並各自攜帶一個例子,顯示重構的運轉。這些富有良好解說價值的實例都以 Java 寫就,其中的觀念適用於任何物件導向編程語言。

Martin Fowler 是一位獨立諮詢顧問,他運用物件技術解決企業問題已經超過 10 年。他的顧問領域包括健康管理、金融貿易,以及法人財務。他的客戶包括 Chrysler, Citibank,UK National Health Service, Andersen Consulting, Netscape Communications。此外Fowler 也是objects、UML、patterns 技術的一位合格講師。他是《Analysis Patterns》和《UML Distilled》的作者。

Kent Beck 是一位知名的程式員、測試員、重構員、作家、五弦琴專家。

John Brant 和 Don Roberts 是《Refactoring Browser for Smalltalk》的作者,此書可從http://st-www.cs.uiuc.edu/~brant/RefactoringBrowser 獲得。他們兩人也是諮詢顧問,研究重構的實踐與理論有六年之久。

William Opdyke 在伊利諾大學所做的 object-oriented frameworks(物件導向框架)博士研究,導出了重構領域的第一份重要出版品。他目前是 Lucent Technologies/Bell Laboratories 的一名卓越技術人員。

譯者 侯捷,致力計算機技術教育超過 10 年 — 以著作、翻譯、評論、專欄、授課等多重形式。對於各種層級、各種定位、各種技術領域之 Framework Libraries 有濃烈興趣和鑽研。

譯者 熊節,普通程式員,喜編程,樂此而不疲。酷愛讀書,好求新知。記性好忘性大,故凡有所得必記諸文字,有小得,無大成。胸有點墨,心無大志,惟願寧靜淡泊而已。夜闌人靜,一杯清水,幾本閑書,神交於各方名士,獻曝於天下同好,吾願足矣。

前言

本書我覺得可以說是軟體界兩大奇書之一 (另一本就是“Design Patterns”)。設計模式講究的是在程式碼之前 (常所說的系統分析與設計活動)的事先設計,而重構講究的則是程式寫碼後對結構的重整。

我們要先瞭解一件事,軟體設計不可能如建築業一般,只在藍圖上畫好設計圖就能建構出穩固的高樓大廈。軟體開發是要經過不斷地分析、設計、寫碼、測試與修正… 。漸增與反覆,才有可能建構出高品質與強固的系統。事先的設計能保障程式碼相當程度的品質,但不可能完美無瑕,事實上,即使如本書作者 Martin Fowler,也仍須透過程式碼的驗證回饋,再回頭來修整軟體的結構。可以說,運用在紙上藍圖的設計模式與在程式碼的重構本都是設計中的一環,“Top-down (SA/SDPG)”與“Bottom-up (PGSD/SA)”兩者本就不應該在軟體工程是被分開為兩種方法論,而是互補,缺一不可,才有可能建構出軟體設計開發的正回饋環路。

所以重構的對象為程式碼,目的在於對程式碼背後所隱含的結構作重整,提昇對軟體系統的彈性與穩定,同時也相對能讓程式人員容易維護與讓寫碼更有效率。因為設計不可能一開始就是正確,它會隨著設計者的經驗成長而進化;程式碼被閱讀和修改的次數遠多於它被編寫的次數。保持程式碼易讀、易修改的關鍵,就是重構。

本書的作者為 Martin Fowler,不過其實考究起來,“重構 (Refactoring)”一詞是由 Kent-beck在 Smalltalk 專案中率先所提出的概念,並用在實務的顧問輔導。Fowler 是集眾多有經驗的軟體開發先驅們之大成,而把他們所經常用在程式碼重整的技巧整理編寫成重構名錄 (catalog of refactoring),模仿如設計模式一般,對每一個重構給予命名與應用時機等,讓程式人員之間方便利用這些詞彙作為溝通,而成為日常開發實務上的習慣。

瞭解為何重構、為誰重構、何時重構


我問過許多位程式人員,大多數手頭上都有此本的中譯本 (候捷大師所翻譯的,品質沒話說)。但是好像看不太懂? 我在想可能是與不瞭解重構的目的以及對物件導向的基礎功夫有關。雖然對象是程式碼,但是重構的本質其實就是對軟體結構的重整,講更白一點,就是對物件給於明確的責任分派 (responsibility asssign),使得物件之間能具高內聚力 (high-cohesion)與低耦合性 (low-coupling),而展現在程式碼最直接的呈現就會變得簡潔、易讀、不容易有多餘、重覆的程式碼分散在各處而難以維護了。

本書第一章一定要先看,它可以說是整本書的濃縮。若能確實看得懂,才有可能往後續的章節看下去。而閱讀本書所具備的基礎功夫應該需要對如 java 語法的瞭解、UML 類別與循序圖、物件與類別的關係 (尤其是 整體—局部、一般化—特殊化)、多型、介面、封裝、委派 (delegate)等物件導向觀念… 難怪乎看得懂好像真的不多。但是,若是作為以軟體為職志的設計/開發人員,一定要持續把它看完,即使花兩、三年也是值得的!

第一章就是以三個類別 (class)的案例 (影片出租),來帶出如何在 Java 程式碼的寫作與修正,藉以解釋什麼是重構。Fowler 說他這一章很難寫,很不好表達,不過我覺得寫得真是太好了! 竟然只用三個類別,也就是三個 Java Class (當然,重構後有衍生出子類別,但根本上還是只有三個),就能從頭到尾表達出重構的方法,以及在各個修正的階段時,他為何是這麼做,理由何在等。Fowler 在本章也特別利用了循序圖與程式碼的對照,來表達出動態物件之間的訊息傳遞;也理所會使用類別圖,來呈現類別之間的關係。在看這些程式碼時,一定要隨時對照這些圖,才不致落入細節而忘掉重構的標的。

第二章才揭露出為何要重構。我好喜歡這一段句子:
任何一個傻瓜都能寫出計算機可以理解的程式碼。唯有寫出人類容易理解的程式碼,才是優秀的程式員。

所以寫出讓別人看不懂的程式,可不是要自豪,而是要反省,為何無法能寫出簡潔易讀的程式碼呢?
所以為何重構? 本章提出了多項理由,但我引用其中這一段就足以說明 Why:
如果沒有重構,程式的設計會逐漸腐敗變質。當人們只為短期目的,或是在完全理解整體設計之前,就貿然修改程式碼,程式將逐漸失去自己的結構,程式員愈來愈難透過閱讀源碼而理解設計。重構就像是在整理程式碼,你所做的就是讓所有東西回到應該的位置上。

第四章則是介紹如何建構測試體系。請記得,重構與測試可以說是一體的,透過測試,你才能知道重構並沒有變動系統外部的行為,卻仍可以維繫正常的運作。如何利用 JUnit 進行自動化的功能與單元測試,是本章的重點。對程式員而言,你要先認知到:編寫這些測試的目的是為了提高身為一個程式員的生產效率,可不是為了別人。

第五章以後,就是開始揭露出各種重構的手法了。要先充分瞭解每一個重構命名的意涵與其目的,再來才是看實做的細節與步驟。例如“Extract Method”,顧名思義,就是對在函式內部冗長的程式碼抽離出來,放進一個獨立函式中,從而使程式碼更清晰。

本書後三章則是收錄了包括 Kent-beck 的論文與重構的工具。對目前 java 程式員幸運的是,包括 Eclipse 等免費開放的 IDE 工具,都可以協助做自動化的重構工作。Kent beck 的論文,建議真的要看一下,他提及了整合時的編程工作與角色的協調。特別是,當一個人同時擔任多個角色,不要忘記你戴的是哪一頂帽子。

嗅出程式碼的壞味道

何時要重構呢?這是第三章主要的內容。我把它獨立出來介紹,是因為本章的標題太有意思了:程式碼的壞味道。 哈,程式碼的壞味道,是用聞的喔,就如同當你聞到小嬰兒的尿酸味時,就知道該換尿布;同樣地,當你 ”嗅出程式碼的壞味道”時,就知道該要進行重構了。而這裡就有列出了「臭味條款」,來協助你如何檢測不好的程式碼。

最後,我想提一下,重構是為誰呢? 為了專案的品質? 別太天真了,太多老闆與專案經理嘴巴上常說自己是「品質驅動」,而其實他們更多是要求「進度驅動」。所以,不要期望他們能為重構給納入開發排程內,重構就是為了你自己! 它可以讓你的開發更有效率,讓你更少犯錯。一開始的重構可能會停留在枝末細節上,但隨著程式碼漸趨簡潔,你就會發現到,自己開始可以看到一些以前所看不到的設計層面的東西。如果不對這些程式碼做這些修改,你可能無法想像出來。重構可以幫你提昇到更高設計的理解層次上,它可以協助你:擦掉窗戶上的污垢,使你看得更遠!