每週一薦:重構三板斧

來自:http://game-lab.org/?p=207

書籍:《重構:改善既有代碼的設計》

簡介

Martin Fowler和《重構:改善既有代碼的設計》(中文版)另幾位作者清楚揭示了重構過程,他們爲面向對象軟件開發所做的貢獻,難以衡量。《重構:改善既有代碼的設計》(中文版)解釋重構的原理(principles)和最佳實踐方式(best practices),並指出何時何地你應該開始挖掘你的代碼以求改善。《重構:改善既有代碼的設計》(中文版)的核心是一份完整的重構名錄(catalog of refactoring),其中每一項都介紹一種經過實證的代碼變換手法(code transformation)的動機和技術。某些項目如Extract Method和Move Field看起來可能很淺顯,但不要掉以輕心,因爲理解這類技術正是有條不紊地進行重構的關鍵。

筆記

Composing Methods
  1. Extract Method: 你有一段代碼可以被組織在一起並獨立起來,將其放入一個獨立的函數,並讓函數名稱解釋該函數的用途
  2. Inline Method: 一個函數,其本體和名稱同樣清楚易懂,在函數調用點插入函數本體,然後移除該函數
  3. Inline Temp: 你有一個臨時變量,只被一個簡單表達式賦值一次,將所有對該變量的引用,替換爲對它賦值的那個表達式自身
  4. Replace Temp With Query: 你的程序以一個臨時變量保存某一個表達式的運算結果,將這個表達式提煉到一個獨立的函數中,將這個臨時變量的所有被引用點替換爲對新函數的調用。新函數也可以被其它函數使用。
  5. Introduce Explaining Variable: 你有個複雜的表達式,將該複雜的表達式或其中的一部分的結果放進一個臨時變量,以此變量名稱來解釋表達式的用途
  6. Split Temporary Variable: 你的程序有某個臨時變量被賦值超過一次,它既不是循環變量,也不是一個集用臨時變量。針對每次賦值,創造一個獨立的、對應的臨時變量。
  7. Remove Assignments to Parameters: 你的代碼對一個參數進行賦值動作,以一個臨時變量取代該參數的位置
  8. Replace Method With Method Object: 你有一個大型函數,其中對局部變量的使用,使你無法使用Extract Method。將這個函數放入一個單獨的對象,如此一來局部變量就變成了對象內的值域,然後你尅在同一個對象中將這個大型函數分解爲數個小型函數。
  9. Substitute Algorithm: 你想要把某個算法替換爲另一個更清楚的算法,將函數本體替換爲另外一個算法。
Moving  Feature Between Object
  1. Move Method: 你的程序中,有個函數與其所駐class之外的另外一個class進行更多交流(調用或者,或被後者調用)。在該函數最長引用的class中建立一個有着類似行爲的新函數。將舊函數變成一個單純的委託函數,或是將舊函數完全刪除。
  2. Move Field: 你的程序中,某個值域被其所駐class之外的另一個classs更多的用到。在target class建立一個new field,修改source field的所有用戶,令它們改用 new field。
  3. Extract Class: 某個class做了應該由兩個classes做的事。建立一個新class,將相關的值域和函數從舊class搬移到新class。
  4. Inline Class: 你的某個class沒有做太多事情(沒有承擔足夠責任)。將class的所有特性搬移到另外一個class中,然後移除原class。
  5. Hide Delgate: 客戶直接調用server object(服務對象)的delegate class。在server端(某個class)建立客戶所需的所有函數,用以隱藏委託關係。
  6. Remove Middle Man: 某個class做了過多的簡單委託動作。讓客戶端直接調用delegate(受託類)。
  7. Introduce Foreign Method: 你所使用的server class 需要一個額外的函數,但你無法修改這個class。在client class中建立一個函數,並以一個server class實體作爲第一個參數。
  8. Introduce Local Extension: 你所使用的server class需要一些額外的函數,但你無法修改這個class。建立一個新class,使它包含這些額外函數。讓這個擴展品成爲source class的subclass(子類)或 wrapper(外覆類)。
Organizing Data
  1. Self Encapsluate: 你直接訪問一個值域,但與值域直接的耦合關係逐漸變得笨拙。爲這個值域建getting/setting methods,並且以這些函數來訪問值域。
  2. Replace Data Value with Object: 你有一比數據項,需要額外的數據和行爲。你將這筆數據變成一個對象。
  3. Change Value to Reference: 你有一個class,衍生出許多相等實體,你希望將它們替換爲單一對象。將這個value object變成一個reference object。
  4. Change Reference to Value: 你有個reference object,很小且不可變,而且不易管理。將它鞭策一個value object。
  5. Replace Array with Object: 你有一個數組,其中的元素各自代表不同的東西。以對象替換數組,對於數組中的每個元素,以一個值域表示。
  6. Duplicate Observed Object: 你有一些domain data置於GUI控件中,而domain Method 需要訪問之。將該數據copy 到一個domain object中,建立一個Observer模式,用以對domain object和GUI object內的重複數據進行同步控制。
  7. Change Unidirectional Association to Bidirectional : 兩個classes都需要對方的特性,但期間只有一條單向連接。添加一個反向指針,並使修改函數能夠同時更新兩條連接。
  8. Change Bidirectional Association to Unidirectional: 兩個classes直接有雙向關聯,但其中一個class如今不再需要另一個class的特性。去除不必要的關聯。
  9. Replace Magic Number with Symbolic Constant: 你有一個字面數值,帶有特別的含義。創造一個常量,根據其意義爲它命名,並將上述的字符數值替換爲這個常量。
  10. Encapsulate Filed: 你在class中一個public值域,將它聲明爲private,並提供相應得分訪問函數。
  11. Encapsulate Collection: 有個函數返回一個羣集,讓這個函數返回該羣集的一個只讀映像,並在這個class中提供添加/刪除羣集元素的函數。
  12. Replace Record with Data class: 你需要面對傳統編程環境中的record struct。爲該record創建一個啞數據對象。
  13. Replace Type Code with Class : class之中有一個數值型別碼,但它並不影響class的行爲。以一個新class替換該數值型別碼。
  14. Replace Type Code with Subclass: 你有一個不可變的type code,它會影響class的行爲。以一個subclass取代這個type code。
  15. Replace Type Code with State/Stratgery: 你有 一個type code,它會影響class的行爲,但你無法使用subclassing。以state object取代type code。
  16. Replace Subclass with Fields: 你的各個subclass的唯一差別只在返回常量數據的函數身上。修改這些函數,使它們返回superclass中的某個值域,然後銷燬subclass。
Simplifing Conditional Expression
  1. Decompose Condtional: 你有一個複雜的條件語句,從if、then、else三個段落中分別提取出獨立函數。
  2. Consolidate Condtional Expression: 你有一系列條件測試,都得到相同的結果。將這些測試合併爲一個條件式,並將這個條件式提煉成爲一個獨立函數。
  3. Consolidate Duplicate Condtional Fragment: 在條件式的每個分支上有着相同的一段代碼。將這段代碼搬移到條件式之外。
  4. Remove Control Flag: 在一系列布爾表達式中,某個變量帶有控制標記的作用。以break語句或return語句取代控制標記。
  5. Replace Nested Condtional wiht Guard Clauses: 函數中的條件邏輯使人難以看清楚正常的執行路徑。使用衛語句表現所以特殊情況。
  6. Replace Conditional with Polymorphism: 你手上有個條件式,它根據對象型別的不同而選擇不同的行爲。將這個條件表達式的每個分支放進一個subclass內的覆寫函數中,然後將原函數聲明爲抽象函數。
  7. Introduce Null Object: 你需要再三檢查某物是否爲null value,將null value替換爲null object。
  8. Introduce Assertion: 某一段代碼需要對程序狀態作出某種假設,以斷言明確表現這種假設。
Making Method Calls Simpler
  1. Rename Method: 函數的名稱未能揭示函數的用途,修改函數的名稱。
  2. Add Parameter : 某個函數需要從調用端得到更多信息,爲此函數添加一個對象參數,讓該對象帶進函數所需信息。
  3. Remove Parameter: 函數本體不再需要某個參數,將該參數刪除。
  4. Seperate Query from Modifier: 某個函數既返回對象狀態值,又修改對象狀態,建立兩個不同的函數,其中一個負責查下,另一個負責修改。
  5. Parameterize Method: 若干函數做了類似的工作,但在函數本體中卻包含了不同的值,建立一個單一函數,以參數表達那些不同的值。
  6. Replace Parameter with Explict Methods: 你有一個函數,其內完全取決於參數採取不同的反應。針對該參數的每一個可能值,建立一個對立函數。
  7. Preserver Whole Object :你從某個對象中取出若干值,將他們昨晚某一次函數調用時的參數。改使用傳遞整個對象。
  8. Replace Parameter with Methods: 對象調用某個函數,並將所得結果作爲參數,傳遞給另一個函數。而接收該參數的函數也可以調用前一個函數。讓參數接受者去除該項參數,並直接調用前一個函數。
  9. Introduce Parameter Object :  某些參數總是很自然的同時出現,以一個對象取代這些參數。
  10. Remove Setting Method: 你的clas中的某個值域,應該在對象初始時被設值,然後就不再改變。去掉該值域的設值函數。
  11. Hide Method: 有一個函數,從來沒有被其它任何class用到。將這個函數修改爲private。
  12. Replace Constructor with Factory Method: 你希望在創建對象時不僅僅是對它做簡單的建構動作。將構造函數替換爲工廠函數。
  13. Encapsulate Downcast: 某個函數返回的對象,需要由函數調用者執行向下轉型動作。將down-cast動作移動到函數中。
  14. Replace Error Code with Exception: 某一個函數返回一個特定的代碼,用以表示某種錯誤情況。改用異常。
  15. Replace Exception with Test: 面對一個調用者可預先加以檢查的條件,你拋出了一個異常。修改調用者,使它在調用函數之前先做檢查。
Dealing with Generalization
  1. Pull Up Field: 兩個subclass擁有相同的值域,將此一值域移至superclass
  2. Pull Up Method: 有些函數,在各個subclass中產生完全相同的結果,將該函數移至superclass
  3. Pull Up Constructor Body: 你在各個subclass中擁有一些構造函數,他們的本體代碼幾乎完全一致。在superclass中新建一個構造函數,並在subclass構造函數中調用它
  4. Push Down Method: superclass中的某個函數只與部分而非全部subclass有關。將這個函數移到相關的那些subclass去
  5. Push Down Field: superclass中的某個值域只被部分而非全部subclass用到。將這個值域移到需要它的那些subclass去
  6. Extract Subclass: class中的某些特性只被某些而非全部實體用到。新建一個subclass,將上面所說的那一部分特性移到subclass中
  7. Extract Superclass: 兩個class有些相似特性。爲這兩個classes建立一個superclass,將相同特性移到superclass
  8. Extract Interface: 若干客戶使用class接口中的同一子集;或者,兩個classes的接口有部分相同。將相同的子集提煉到一個獨立的接口中。
  9. Collapse Hierarchy: superclass和subclass直接無太大區別,將它們合爲一體。
  10. Form Template Method: 你有一些subclasses,其中相應的某些函數以相同的順序執行類似的措施,但各措施實際上有所不同。將各個措施分別放進獨立函數中,並保持它們都有相同的簽名式,於是原函數也就變得相同了。然後將原函數移到superclass。
  11. Replace Inheritence with Delegation: 某個subclass只使用superclass接口中的一部分,或是根本不需要繼承而來的數據。在subclass中新建一個值域用以保存superclass;調整subclass函數,令他改而委託superclass;然後去掉兩者直接的繼承關係。
  12. Replace Delegation with Inheritence: 你在兩個classes之間使用委託關係,並經常爲整個接口編寫許多及其簡單的請託函數(delegating method),讓請託class繼承受託class。
Big Refactoring
  1. Tease Apart Inheritance: 某個繼承體系同時承擔兩項責任。建立兩個繼承體系,並通過委託關係讓其中一個可以調用另一個。
  2. Convert Procedural Design to Objects: 你手上有一些代碼,以傳統的過程化風格寫就。將數據記錄變成對象,將行爲分開,並將行爲移入對象之中。
  3. Seperate Domain from Presentation: 某些GUI class之中包含了domain logic。將domain logic分離出來,爲它們建立獨立的domain classes。
  4. Extract Hierarchy: 你有某些class做了太多工作,其中一部分工作是以大量條件式完成的。建立繼承體系,以一個subclass表示一種特殊情況。

書籍:《重構手冊》

簡介

利用這本通過示例“說話”的實例手冊,可以充分發揮重構的強大功能,改善現有的軟件。

身爲程序員,你必須具備的一個基本功就是能夠找出並改善有問題的代碼,使程序能夠在軟件的整個生命週期中正常運轉。重構可謂是安全地改善既有代碼設計的一門藝術,由此可以提供高效而可靠的系統,使紛雜凌亂歸於平穩有序,並能最大限度地抑制異常的出現!重構可能很難掌握,但是在專業顧問William C.Wake所撰寫的這本書中,經由作者娓娓道來,有關內容得以通過一種易於學習的方式展現出來,不僅使學習之旅頗具實效,而且充滿樂趣。

對於許多人來說,學習重構的最大障礙是如何找出代碼的“壞味道(smell)”,即可能存在問題之處。本書並非讓你流水帳式地通讀這些壞味道,而是確保你對這些壞味道有切實的理解。在此奉上了一系列精心組織的問題,通過這些問題的解決,你將會茅塞頓開,不僅會在更深層次上了解重構,而且還將獲得你自己的一些心得體會。Wake採用了實例手冊的方式來組織全書,以幫助你瞭解最爲重要的重構技術並將其應用於代碼之中。這是一種強調學習的方法,要求你必須充分應用本書所提供的諸多技術。除此之外,這種方法還有一個附帶的好處,即儘管當前你所作的工作也許並非重構,利用本書也將有助於你更多地考慮如何創建優質的代碼。

書籍:《重構與模式》

簡介

本書開創性地深入揭示了重構與模式這兩種軟件開發關鍵技術之間的聯繫,說明了通過重構實現模式改善既有的設計,往往優於在新的設計早期使用模式。本書不僅展示了一種應用模式和重構的創新方法,而且有助於讀者結合實戰深入理解重構和模式。書中講述了27種重構方式。

2012/03/09 09:07 於上海


發佈了88 篇原創文章 · 獲贊 31 · 訪問量 21萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章