來自:http://game-lab.org/?p=207
書籍:《重構:改善既有代碼的設計》

簡介
Martin Fowler和《重構:改善既有代碼的設計》(中文版)另幾位作者清楚揭示了重構過程,他們為面向對象軟體開發所做的貢獻,難以衡量。《重構:改善既有代碼的設計》(中文版)解釋重構的原理(principles)和最佳實踐方式(best practices),并指出何時何地你應該開始挖掘你的代碼以求改善。《重構:改善既有代碼的設計》(中文版)的核心是一份完整的重構名錄(catalog of refactoring),其中每一項都介紹一種經過實證的代碼變換手法(code transformation)的動機和技術。某些項目如Extract Method和Move Field看起來可能很淺顯,但不要掉以輕心,因為了解這類技術正是有條不紊地進行重構的關鍵。
筆記
Composing Methods
- 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: 你有一個大型函數,其中對局部變量的使用,使你無法使用Extract Method。将這個函數放入一個單獨的對象,如此一來局部變量就變成了對象内的值域,然後你尅在同一個對象中将這個大型函數分解為數個小型函數。
- Substitute Algorithm: 你想要把某個算法替換為另一個更清楚的算法,将函數本體替換為另外一個算法。
Moving Feature Between Object
- Move Method: 你的程式中,有個函數與其所駐class之外的另外一個class進行更多交流(調用或者,或被後者調用)。在該函數最長引用的class中建立一個有着類似行為的新函數。将舊函數變成一個單純的委托函數,或是将舊函數完全删除。
- Move Field: 你的程式中,某個值域被其所駐class之外的另一個classs更多的用到。在target class建立一個new field,修改source field的所有使用者,令它們改用 new field。
- Extract Class: 某個class做了應該由兩個classes做的事。建立一個新class,将相關的值域和函數從舊class搬移到新class。
- Inline Class: 你的某個class沒有做太多事情(沒有承擔足夠責任)。将class的所有特性搬移到另外一個class中,然後移除原class。
- Hide Delgate: 客戶直接調用server object(服務對象)的delegate class。在server端(某個class)建立客戶所需的所有函數,用以隐藏委托關系。
- Remove Middle Man: 某個class做了過多的簡單委托動作。讓用戶端直接調用delegate(受托類)。
- Introduce Foreign Method: 你所使用的server class 需要一個額外的函數,但你無法修改這個class。在client class中建立一個函數,并以一個server class實體作為第一個參數。
- Introduce Local Extension: 你所使用的server class需要一些額外的函數,但你無法修改這個class。建立一個新class,使它包含這些額外函數。讓這個擴充品成為source class的subclass(子類)或 wrapper(外覆類)。
Organizing Data
- Self Encapsluate: 你直接通路一個值域,但與值域直接的耦合關系逐漸變得笨拙。為這個值域建getting/setting methods,并且以這些函數來通路值域。
- Replace Data Value with Object: 你有一比資料項,需要額外的資料和行為。你将這筆資料變成一個對象。
- Change Value to Reference: 你有一個class,衍生出許多相等實體,你希望将它們替換為單一對象。将這個value object變成一個reference object。
- Change Reference to Value: 你有個reference object,很小且不可變,而且不易管理。将它鞭策一個value object。
- Replace Array with Object: 你有一個數組,其中的元素各自代表不同的東西。以對象替換數組,對于數組中的每個元素,以一個值域表示。
- Duplicate Observed Object: 你有一些domain data置于GUI控件中,而domain Method 需要通路之。将該資料copy 到一個domain object中,建立一個Observer模式,用以對domain object和GUI object内的重複資料進行同步控制。
- Change Unidirectional Association to Bidirectional : 兩個classes都需要對方的特性,但期間隻有一條單向連接配接。添加一個反向指針,并使修改函數能夠同時更新兩條連接配接。
- Change Bidirectional Association to Unidirectional: 兩個classes直接有雙向關聯,但其中一個class如今不再需要另一個class的特性。去除不必要的關聯。
- Replace Magic Number with Symbolic Constant: 你有一個字面數值,帶有特别的含義。創造一個常量,根據其意義為它命名,并将上述的字元數值替換為這個常量。
- Encapsulate Filed: 你在class中一個public值域,将它聲明為private,并提供相應得分通路函數。
- Encapsulate Collection: 有個函數傳回一個群集,讓這個函數傳回該群集的一個隻讀映像,并在這個class中提供添加/删除群集元素的函數。
- Replace Record with Data class: 你需要面對傳統程式設計環境中的record struct。為該record建立一個啞資料對象。
- Replace Type Code with Class : class之中有一個數值型别碼,但它并不影響class的行為。以一個新class替換該數值型别碼。
- Replace Type Code with Subclass: 你有一個不可變的type code,它會影響class的行為。以一個subclass取代這個type code。
- Replace Type Code with State/Stratgery: 你有 一個type code,它會影響class的行為,但你無法使用subclassing。以state object取代type code。
- Replace Subclass with Fields: 你的各個subclass的唯一差别隻在傳回常量資料的函數身上。修改這些函數,使它們傳回superclass中的某個值域,然後銷毀subclass。
Simplifing Conditional Expression
- Decompose Condtional: 你有一個複雜的條件語句,從if、then、else三個段落中分别提取出獨立函數。
- Consolidate Condtional Expression: 你有一系列條件測試,都得到相同的結果。将這些測試合并為一個條件式,并将這個條件式提煉成為一個獨立函數。
- Consolidate Duplicate Condtional Fragment: 在條件式的每個分支上有着相同的一段代碼。将這段代碼搬移到條件式之外。
- Remove Control Flag: 在一系列布爾表達式中,某個變量帶有控制标記的作用。以break語句或return語句取代控制标記。
- Replace Nested Condtional wiht Guard Clauses: 函數中的條件邏輯使人難以看清楚正常的執行路徑。使用衛語句表現是以特殊情況。
- Replace Conditional with Polymorphism: 你手上有個條件式,它根據對象型别的不同而選擇不同的行為。将這個條件表達式的每個分支放進一個subclass内的覆寫函數中,然後将原函數聲明為抽象函數。
- Introduce Null Object: 你需要再三檢查某物是否為null value,将null value替換為null object。
- Introduce Assertion: 某一段代碼需要對程式狀态作出某種假設,以斷言明确表現這種假設。
Making Method Calls Simpler
- Rename Method: 函數的名稱未能揭示函數的用途,修改函數的名稱。
- Add Parameter : 某個函數需要從調用端得到更多資訊,為此函數添加一個對象參數,讓該對象帶進函數所需資訊。
- Remove Parameter: 函數本體不再需要某個參數,将該參數删除。
- Seperate Query from Modifier: 某個函數既傳回對象狀态值,又修改對象狀态,建立兩個不同的函數,其中一個負責查下,另一個負責修改。
- Parameterize Method: 若幹函數做了類似的工作,但在函數本體中卻包含了不同的值,建立一個單一函數,以參數表達那些不同的值。
- Replace Parameter with Explict Methods: 你有一個函數,其内完全取決于參數采取不同的反應。針對該參數的每一個可能值,建立一個對立函數。
- Preserver Whole Object :你從某個對象中取出若幹值,将他們昨晚某一次函數調用時的參數。改使用傳遞整個對象。
- Replace Parameter with Methods: 對象調用某個函數,并将所得結果作為參數,傳遞給另一個函數。而接收該參數的函數也可以調用前一個函數。讓參數接受者去除該項參數,并直接調用前一個函數。
- Introduce Parameter Object : 某些參數總是很自然的同時出現,以一個對象取代這些參數。
- Remove Setting Method: 你的clas中的某個值域,應該在對象初始時被設值,然後就不再改變。去掉該值域的設值函數。
- Hide Method: 有一個函數,從來沒有被其它任何class用到。将這個函數修改為private。
- Replace Constructor with Factory Method: 你希望在建立對象時不僅僅是對它做簡單的建構動作。将構造函數替換為工廠函數。
- Encapsulate Downcast: 某個函數傳回的對象,需要由函數調用者執行向下轉型動作。将down-cast動作移動到函數中。
- Replace Error Code with Exception: 某一個函數傳回一個特定的代碼,用以表示某種錯誤情況。改用異常。
- Replace Exception with Test: 面對一個調用者可預先加以檢查的條件,你抛出了一個異常。修改調用者,使它在調用函數之前先做檢查。
Dealing with Generalization
- Pull Up Field: 兩個subclass擁有相同的值域,将此一值域移至superclass
- Pull Up Method: 有些函數,在各個subclass中産生完全相同的結果,将該函數移至superclass
- Pull Up Constructor Body: 你在各個subclass中擁有一些構造函數,他們的本體代碼幾乎完全一緻。在superclass中建立一個構造函數,并在subclass構造函數中調用它
- Push Down Method: superclass中的某個函數隻與部分而非全部subclass有關。将這個函數移到相關的那些subclass去
- Push Down Field: superclass中的某個值域隻被部分而非全部subclass用到。将這個值域移到需要它的那些subclass去
- Extract Subclass: class中的某些特性隻被某些而非全部實體用到。建立一個subclass,将上面所說的那一部分特性移到subclass中
- Extract Superclass: 兩個class有些相似特性。為這兩個classes建立一個superclass,将相同特性移到superclass
- Extract Interface: 若幹客戶使用class接口中的同一子集;或者,兩個classes的接口有部分相同。将相同的子集提煉到一個獨立的接口中。
- Collapse Hierarchy: superclass和subclass直接無太大差別,将它們合為一體。
- Form Template Method: 你有一些subclasses,其中相應的某些函數以相同的順序執行類似的措施,但各措施實際上有所不同。将各個措施分别放進獨立函數中,并保持它們都有相同的簽名式,于是原函數也就變得相同了。然後将原函數移到superclass。
- Replace Inheritence with Delegation: 某個subclass隻使用superclass接口中的一部分,或是根本不需要繼承而來的資料。在subclass中建立一個值域用以儲存superclass;調整subclass函數,令他改而委托superclass;然後去掉兩者直接的繼承關系。
- Replace Delegation with Inheritence: 你在兩個classes之間使用委托關系,并經常為整個接口編寫許多及其簡單的請托函數(delegating method),讓請托class繼承受托class。
Big Refactoring
- Tease Apart Inheritance: 某個繼承體系同時承擔兩項責任。建立兩個繼承體系,并通過委托關系讓其中一個可以調用另一個。
- Convert Procedural Design to Objects: 你手上有一些代碼,以傳統的過程化風格寫就。将資料記錄變成對象,将行為分開,并将行為移入對象之中。
- Seperate Domain from Presentation: 某些GUI class之中包含了domain logic。将domain logic分離出來,為它們建立獨立的domain classes。
- Extract Hierarchy: 你有某些class做了太多工作,其中一部分工作是以大量條件式完成的。建立繼承體系,以一個subclass表示一種特殊情況。
書籍:《重構手冊》
簡介
利用這本通過示例“說話”的執行個體手冊,可以充分發揮重構的強大功能,改善現有的軟體。
身為程式員,你必須具備的一個基本功就是能夠找出并改善有問題的代碼,使程式能夠在軟體的整個生命周期中正常運轉。重構可謂是安全地改善既有代碼設計的一門藝術,由此可以提供高效而可靠的系統,使紛雜淩亂歸于平穩有序,并能最大限度地抑制異常的出現!重構可能很難掌握,但是在專業顧問William C.Wake所撰寫的這本書中,經由作者娓娓道來,有關内容得以通過一種易于學習的方式展現出來,不僅使學習之旅頗具實效,而且充滿樂趣。
對于許多人來說,學習重構的最大障礙是如何找出代碼的“壞味道(smell)”,即可能存在問題之處。本書并非讓你流水帳式地通讀這些壞味道,而是確定你對這些壞味道有切實的了解。在此奉上了一系列精心組織的問題,通過這些問題的解決,你将會茅塞頓開,不僅會在更深層次上了解重構,而且還将獲得你自己的一些心得體會。Wake采用了執行個體手冊的方式來組織全書,以幫助你了解最為重要的重構技術并将其應用于代碼之中。這是一種強調學習的方法,要求你必須充分應用本書所提供的諸多技術。除此之外,這種方法還有一個附帶的好處,即盡管目前你所作的工作也許并非重構,利用本書也将有助于你更多地考慮如何建立優質的代碼。
書籍:《重構與模式》
簡介
本書開創性地深入揭示了重構與模式這兩種軟體開發關鍵技術之間的聯系,說明了通過重構實作模式改善既有的設計,往往優于在新的設計早期使用模式。本書不僅展示了一種應用模式和重構的創新方法,而且有助于讀者結合實戰深入了解重構和模式。書中講述了27種重構方式。
2012/03/09 09:07 于上海