Martin Fowler 在《重構》中定義的「代碼異味」是識別軟體品質劣化的關鍵指標。本文梳理 21 種經典異味,對應重構方向,助你建立代碼質量紅綠燈機制。
結構層面異味
| 異味 | 核心問題 | 重構方向 |
| 1. 重複代碼 | Copy-Paste 程式設計,違反 OAOO 原則 | 提煉方法、提煮類、Pull Up Method |
| 2. 過長方法 | 單方法承擔多重意圖 | 提煉方法、分解條件表達式 |
| 3. 過大類別 | 單一類別承擔過多職責 | 提煉類、提煉超類別 |
| 4. 發散式變化 | 類內變化原因多元,修改波及面廣 | 拆分類別,隔離變化維度 |
| 5. 霰彈式修改 | 單一變更引發多處連鎖修改 | 搬移方法/欄位,合併相關類別 |
| 6. 功能依賴 | 方法頻繁存取他類內部狀態 | 搬移方法至數據所在類 |
| 7. 數據泥團 | 多組數據總是成群出現 | 提煉為獨立值物件 |
| 8. 基本型別偏執 | 用基本型別表達領域概念(如用 double 表達金額) | 以值物件封裝領域概念 |
行為與協議異味
| 異味 | 核心問題 | 重構方向 |
| 9. Switch 語句 | 基於常數分支,違背開閉原則 | 多態、狀態模式、策略模式 |
| 10. 平行繼承體系 | 修改一體系必須同步修改另一體系 | 合併體系、移動方法 |
| 11. 冗餘類別 | 類別職責過輕,維護成本大於價值 | 內聯類別、Collapse Hierarchy |
| 12. 推測性通用性 | 實現未用功能,唯一調用者是測試 | YAGNI 原則:刪除 |
| 13. 暫時欄位 | 欄位僅在特定場景有效 | 提煉類、引入 Null Object |
| 14. 訊息鏈 | a.getB().getC().doSomething() | 隱藏委託、引入中介者 |
| 15. 中間人 | 類別過度委託,接口大多轉發 | 移除中間人、直接調用 |
| 16. 過度親密 | 類別間過度訪問私有細節 | 搬移方法/欄位、提煮類 |
| 17. 介面不一致的替代類 | 同義操作擁有不同簽名 | 重命名方法、提煉超類別 |
資源與文檔異味
| 異味 | 核心問題 | 重構方向 |
| 18. 不完美庫類別 | 第三方庫缺乏所需功能 | 引入裝飾器、適配器模式 |
| 19. 資料類別 | 只有 getter/setter 無行為 | 封裝集合、搬移行為進類別 |
| 20. 被拒絕的遺贈 | 子類只用父類極小部分功能 | 以組合取代繼承 |
| 21. 過度註釋 | 大量註釋掩蓋代碼不清晰 | 以重構替代註釋:好代碼自文檔化 |
實踐建議
- 將異味識別納入 Code Review 標準清單
- 配合 SonarQube 等靜態分析工具自動化檢測
- 重構必須有測試保護網,小步快跑、持續集成
- 記住:重構不是重寫,而是在保持行為不變前提下改善結構