重構-Java(代碼的壞味道)

1. Duplicate Code(重複代碼)

  • 同一個類的兩個函數含有相同的表達式-Extract Method
  • 兩個互爲兄弟的子類的含有相同的表達式-Extract Method,Pull Up Method,Template Pattern
  • 兩個不相關的類出現Duplicate Code,對其中一個使用Extract Class

2. Long Method(過長函數)

  • 把函數變小-Extract Method
  • 大量的參數和臨時變量-Replace Temp With Query,Introduce Parameter Object,Preserve Whole Object,Replace Method With Method Object消除臨時變量元素,Decompose Conditional處理條件表達式

3. Large Class(過大的類)

  • 如果類的數個變量有着相同的前綴或結尾,或者是太多的實例變量,太多代碼-Extract SubClass,Extract Class
  • Extract Interface,爲每一種使用方式提煉出一個接口

4. Long Parameter List(過長參數列)

  • 向已有對象發出一個請求取代一個參數-Replace Parameter With Method
  • 來自同一對象的數據收集起來-Preserve Whole Object
  • 製造一個“參數對象”-Introduce Parameter Object

5. Divergent Change(發散式變化)-一個類受多種變化的影響

  • 某特定原因而造成的變化-Extract Class提煉到同一個類中

6. Shotgun Surgery(霰彈式修改)-一種變化引發多個類的相應修改

  • 需要修改的代碼的問題散步四處-Move Method和Move Field把需要修改的代碼放進同一個類中,如眼下沒有合適的類就創造一個,Inline class把一系列相關行爲放進一個類

7. Feature Envy(依戀情結)

  • Strategy和Visitor,可以輕鬆地修改函數行爲(代價:多了一層間接層)

8. Data Clumps

  • 將各個類中相同的字段、函數簽名中相同的參數-運行Extract Method提煉到一個類中
  • 運用Introduce Method和Preserve Whole Object爲其減肥

9. Primitive Obsession(基本類型偏執)

  • 小任務上運行小對象-Replace Data Value With Object
  • 如果想要替換的數據值是類型碼-運用Replace Type Code With Class將其換掉
  • 如果有與類型碼相關的條件表達式-Replace Type Code With Subclass 或 Replace Type Code With State/Strategy
  • 如果在參數列表中看到的基本數據型數據-Introduce Parameter Object
  • 從數組中挑選數據-Replace Array With Object

10. Switch Statements

  • Replace Conditional With Polymorphism - 以多態取代條件式

你手上有個條件式,它根據對象型別的不同而選擇不同的行爲。將這個條件式的每個分支放進一個subclass內的覆寫函數中,然後將原始函數聲明爲抽象函數。

  • Replace Parameter with Explicit Methods - 以明確函數取代參數

你有一個函數,其內完全取決於參數值而採取不同反應。針對該參數的每一個可能值,建立一個獨立函數。

11. Parallel Inheritance Hierarchies(平行繼承體系)

如果你發現一個繼承體系的類名稱前綴和另一個體系的類名稱前綴完全相同,那便是這種懷味道。
解決的一般策略爲:讓一個繼承體系的實例去引用另一個繼承體系的實例。

  • Move Method
  • Move Field

12. Lazy Class(冗贅類)

  • 如果某些子類沒有做足夠的工作 - Collapse Hierarchy(摺疊繼承體系),superclass和subclass之間無太大區別。將它們和爲一體。
  • 對幾乎沒有用的組件 - Inline class(你的某個class沒有做太多的事情(沒有承擔足夠的責任)。將class的所有特性搬移到另一個class中,然後移除原class。)

13. Speculative Generality

當有人說“喔,我想我們總有一天要做這事”,並因而企圖用各式各樣的鉤子和特殊情況來處理一些非必要的事情。

  • Remove Parameter
  • Rename Method

14. Temporary Field(臨時字段)

15. Message Chain(過度耦合的消息鏈)

一個對象請求另一個對象,然後再向後者請求另一個對象…這就是消息鏈,這樣可能會導致對象間的關係發生變化時,客戶端不得不做出相應的修改。

  • Hide Delegate(隱藏委託關係)

客戶直接調用其server object(服務對象)的delegate class。在sever端(某個class)建立客戶所需要的所有函數,用以隱藏委託關係。

16. Middle Man

  • InlineMethod - 移除函數,將其放入調用端。

  • Replace Delegation with Inheritanc (以繼承取代委託)
    你的兩個classes之間使用了委託關係,並經常爲整個接口編寫許多極其簡單的請託函數。讓請託Class繼承受託class。

17. Inappropriate Intimacy

  • .Change Bindirectional Association to Unidirectional 將雙向關聯改爲單向(兩個classes之間有雙向關聯,但其中一個class如今不再需要另一個class的特性。去除不必要的關聯(association)。)

  • Replace Inheritance with Delegation(以委託取代繼承) - 某個subclass只使用superclass接口中的一部分,或是更本不需要繼承而來的數據。在subclass中新建一個值域用以保存superclass;調整subclass函數,令它改而委託superclass;然後去掉兩者之間的繼承關係。

18. Alternative Classes With Different Interfaces

  • Extract Superclass

19. Incomplete Library Class(不完全的庫類)

  • Introduce Foreign Method(引入外加函數)

你所使用的server class 需要一個額外函數,但你無法修改這個class。在client class 中建立一個函數,並以一個server class實體作爲第一引數(argument)。

  • Introduce Local Extension(引入本地擴展)

20. Data Class (數據類)

  • Self Encapsulate Field(自封裝值域)- 你直接訪問一個值域(field),但與值域直接的耦合關係變得逐漸變得笨拙。爲這個值域建立取值/設值函數,並且只有這些函數來訪問值域。
  • Encapsulate collection (封裝羣集)
  • Remove Setting Method(移除設值函數)- 你的class中的某個值域,應該在對象初創時被設值,然後就不再改變。去掉該值域的所有設置函數。

21. Refused Bequest(拒絕遺贈)

22. Comments(過多的註釋)

  • Introduce Assertion(引入斷言)- 某一段代碼需要對程序狀態做出某種假設。以assertion(斷言)明確表現這種假設。
  • Extract Method
  • Rename Method
  • 當你感覺需要寫註釋時,請先嚐試重構,試着讓所有的註釋都變得多餘。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章