首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 開發 21 大代碼壞味道:從重複代碼到註釋濫用的完整識別與重構指南

     編輯:Java 相關知識

Martin Fowler《重構》經典 21 種代碼壞味道,是識別技術債、指導重構方向的「體檢清單」。本文逐一解析每種壞味道的成因、危害與重構策略,助你練就「代碼嗅覺」。

1. Duplicated Code 重複代碼

徵狀: 相同邏輯出現在多處(複製貼上)。
重構: Extract Method、Pull Up Method、Extract Class。
原則: OAOO (Once And Only Once)。

2. Long Method 過長函數

徵狀: 函數超過一屏、承擔多重職責。
重構: Extract Method、Replace Method with Method Object。
準則: 一個函數只做一件事,5-15 行為宜。

3. Large Class 過大類別

徵狀: 欄位/方法過多、職責不清。
重構: Extract Class、Extract Subclass、Extract Interface。
原則: Single Responsibility Principle (SRP)。

4. Divergent Change 發散式變化

徵狀: 一個類因不同原因頻繁修改(如:會計邏輯變、UI 也變)。
重構: Extract Class 將變化方向隔離。
核心: 將「不變的」與「變化的」分離,讓變化單獨復用。

5. Shotgun Surgery 霰彈式修改

徵狀: 一處修改牽動多個類(與 Divergent Change 相反)。
重構: Move Method、Move Field 將相關邏輯聚合到同一類。
目標: 高內聚,變化局部化。

6. Feature Envy 依戀情結

徵狀: 方法頻繁呼叫他類 getter 進行計算。
重構: Move Method 將行為搬移到數據最豐富的類。
判斷: 方法用「自己」的數據少、用「別人」的多 → 搬家。

7. Data Clumps 數據泥團

徵狀: 同一組數據(如:開始/結束日期、x/y 座標)反復出現在多類欄位、方法參數。
重構: Extract Class 封裝為值物件(DateRange、Point)。

8. Primitive Obsession 基本型別執著

徵狀: 用 int 表示金額、用兩個 String 表示範圍。
重構: Replace Data Value with Object 引入 Money、Range、ZipCode 等小物件。
收益: 類型安全、行為封裝、領域語言化。

9. Switch Statements Switch 語句

徵狀: 基於常數/型別碼的大型 switch。
重構: Replace Conditional with Polymorphism(策略模式/狀態模式/子類多態)。
原則: 開放封閉原則 (OCP),新增型別不修改既有代碼。

10. Parallel Inheritance Hierarchies 平行繼承體系

徵狀: 新增子類時,必須同步新增另一體系的對應子類。
重構: Move Method、Move Field 合併體系,或用組合替代繼承。

11. Lazy Class 懶惰類別

徵狀: 類幾乎不幹活(如只委派、只有幾個簡單欄位)。
重構: Inline Class 內聯刪除。
成本: 每個類都有維護開銷(閱讀、編譯、部署)。

12. Speculative Generality 推測性概化

徵狀: 為「未來可能用到」加入抽象、參數、鉤子,實際只有測試用例呼叫。
重構: Collapse Hierarchy、Remove Parameter、Delete Dead Code。
口號: YAGNI (You Aren't Gonna Need It)。

13. Temporary Field 暫時欄位

徵狀: 某欄位只在特定情況下有意義(如演算法中間狀態)。
重構: Extract Class 將該欄位與相關行為移至專屬類。
典型: 遞歸演算法的暫存變數。

14. Message Chains 訊息鏈

徵狀: a.getB().getC().getD().doSomething()。
重構: Hide Delegate、Extract Method 封裝鏈路。
風險: 內部結構變動波及所有呼叫端(違反迪米特法則)。

15. Middle Man 中間人

徵狀: 類過半方法只是單純委派。
重構: Remove Middle Man 讓呼叫端直接存取真實對象。
度: 適度委派是封裝,過度委派是累贅。

16. Inappropriate Intimacy 過度親密

徵狀: 兩類互相翻閱私有欄位/方法(friend、反射、同包無修飾符)。
重構: Move Method、Extract Class、Hide Delegate 建立清晰邊界。
比喻: 類應守「禁慾主義」,只公開必要契約。

17. Alternative Classes with Different Interfaces 異曲同工

徵狀: 功能相似的類擁有不同方法簽名。
重構: Rename Method 統一協議、Extract Superclass 提煉共同介面。

18. Incomplete Library Class 不完美庫類別

徵狀: 第三方庫缺少所需功能,無法修改源碼。
重構: Introduce Foreign Method、Introduce Local Extension(包裝/子類/組合)。

19. Data Class 資料類別

徵狀: 只有 getter/setter、無行為的類(純 DTO)。
重構: Encapsulate Field、Move Method 將行為搬入。
例外: 邊界傳輸物件 (DTO) 允許無行為,但領域模型必須有行為。

20. Refused Bequest 拒絕遺贈

徵狀: 子類只用父類極小部分功能,繼承關係不純。
重構: Replace Inheritance with Delegation、Extract Superclass 重新劃分層次。
信號: 繼承體系設計有缺陷(違反里氏替換原則)。

21. Comments 註釋濫用

徵狀: 大量註釋解釋「代碼在幹什麼」。
重構: Rename Method、Extract Method 讓代碼自述。
保留: 「為什麼這樣做」(業務規則、演算法來源、TODO)。

壞味道速查卡

類別核心壞味道關鍵重構手法
規模Duplicated CodeExtract Method/Class
Long MethodExtract Method
Large ClassExtract Class/Subclass
變化Divergent ChangeExtract Class
Shotgun SurgeryMove Method/Field
Parallel HierarchiesMerge Hierarchies
封裝Feature EnvyMove Method
Data ClumpsExtract Class
Primitive ObsessionReplace Data Value with Object
繼承/多態Switch StatementsReplace Conditional with Polymorphism
Refused BequestReplace Inheritance with Delegation
Alternative InterfacesExtract Superclass
其他Lazy ClassInline Class
Speculative GeneralityDelete Dead Code
CommentsExtract Method/Rename

實戰建議

  1. 定期掃描:IDE 插件 (SonarLint、IntelliJ Inspections) 自動偵測。
  2. 小步重構:每次只消除一個壞味道,跑測試確保行為不變。
  3. 重構前寫測試:無測試不重構,防止回歸。
  4. 領域語言優先:用 Money、DateRange 替換基本型別,消除 Primitive Obsession 往往能連帶解決 Data Clumps、Feature Envy。

結語

壞味道不是錯誤,而是「這裡可能有更好設計」的信號。掌握 21 種壞味道與對應重構手法,是從「寫出能跑的代碼」進階為「寫出可維護、可擴展系統」的必經之路。下次 Code Review 時,試著給每個檔案貼上壞味道標籤,你會驚訝於技術債的可視化程度。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved