前言:代碼壞味道與重構
Martin Fowler 在《重構》中定義了 21 種經典代碼壞味道,它們是系統腐化的早期信號。本文結合 Java 實戰場景逐一解析,並給出針對性重構方向,助您練就「嗅覺敏銳、重構果斷」的工程師直覺。
類別一:臃腫者(規模失控)
| 編號 | 壞味道 | 核心危害 | 重構切入點 |
| 1 | Duplicated Code 重複代碼 | 維護成本指數級上升,邏輯不一致風險 | Extract Method / Extract Class / Pull Up Method |
| 2 | Long Method 過長函數 | 難理解、難測試、難複用 | Extract Method、以函數替換暫時變量、引入參數物件 |
| 3 | Large Class 過大類 | 職責不清、耦合度高、測試困難 | Extract Class / Extract Subclass / Extract Interface |
類別二:變化失控(單一職責違背)
| 編號 | 壞味道 | 核心危害 | 重構切入點 |
| 4 | Divergent Change 發散式變化 | 一個類因多種原因頻繁修改,違背 SRP | Extract Class 將不同變化維度拆分 |
| 5 | Shotgun Surgery 霰彈式修改 | 一處修改牽動多處,擴散性極強 | Move Method / Move Field 集中相關邏輯 |
| 6 | Parallel Inheritance Hierarchies 平行繼承體系 | 新增子類必須同步修改另一體系,耦合極深 | Move Method 合併體系、引入組合替代繼承 |
類別三:特性誤置(行為與數據分離)
| 編號 | 壞味道 | 核心危害 | 重構切入點 |
| 7 | Feature Envy 特性依戀 | 方法過度關注其他類內部數據,封裝破壞 | Move Method 將行為搬移到數據所在類 |
| 8 | Data Clumps 數據泥團 | 同組數據到處游走,缺乏整體封裝 | Extract Class 形成值物件、引入參數物件 |
| 9 | Primitive Obsession 基本型別偏執 | 用基本型別建模領域概念(如用 double 表金額),語義缺失 | Replace Data Value with Object、引入值物件 |
| 10 | Switch Statements Switch 驚悚現身 | 基於型別碼分支,違背開閉原則 | Replace Type Code with Subclasses / State / Strategy |
類別四:溝通障礙(介面與依賴混亂)
| 編號 | 壞味道 | 核心危害 | 重構切入點 |
| 11 | Message Chains 訊息鏈 | 客戶端依賴深層導航路徑,脆弱極難重構 | Hide Delegate、引入門面模式 |
| 12 | Middle Man 中間人 | 類過度委派,失去實質行為,增加間接層 | Remove Middle Man、直接調用真實對象 |
| 13 | Inappropriate Intimacy 過度親密 | 雙向深度訪問私有成員,耦合失控 | Move Method / Move Field / Extract Class 切割邊界 |
| 14 | Alternative Classes with Different Interfaces 異曲同工異介面 | 語義相同卻介面不一,多態無法發揮 | Rename Method / Move Method 統一協議 |
類別五:冗餘與投機(過度設計與廢代碼)
| 編號 | 壞味道 | 核心危害 | 重構切入點 |
| 15 | Lazy Class 孤兒類 | 職責過少不足以支撐維護成本 | Inline Class / Collapse Hierarchy |
| 16 | Speculative Generality 投機性通用性 | 為未來可能需求過度設計,YAGNI 原則違背 | Delete Dead Code / Collapse Hierarchy / Inline Class |
| 17 | Temporary Field 暫時欄位 | 欄位僅特定場景有效,語義模糊 | Extract Class 形成專用物件、引入 Null Object |
| 18 | Data Class 資料類 | 僅有 getter/setter 無行為,貧血模型 | Encapsulate Field / Move Method 賦予行為 |
| 19 | Refused Bequest 拒絕遺贈 | 子類僅使用父類極小部分,繼承關係錯誤 | Replace Inheritance with Delegation |
類別六:其他
| 編號 | 壞味道 | 核心危害 | 重構切入點 |
| 20 | Incomplete Library Class 不完美庫類 | 第三方庫缺功能,無法直接修改 | Introduce Foreign Method / Introduce Local Extension |
| 21 | Comments 註釋濫用 | 代碼自述性差,被迫用註釋解釋 | Extract Method / Rename Method / Introduce Assertion 讓代碼說話 |
實戰建議
- 建立團隊壞味道清單,Code Review 時對號入座。
- 小步重構、持續測試,單元測試是重構安全網。
- 關注業務價值,優先重構高頻變更、高故障率模組。
- 善用 IDE 重構工具,降低操作風險。
結語
代碼壞味道不是錯誤,而是設計腐化的症狀。掌握這 21 種模式,如同醫生掌握體徵,能在系統癱瘓前精準介入。重構是程式設計師的基本功,更是對專業負責的體現。願您代碼整潔、架構演進、業務長青。