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

Java 開發必知的 21 種代碼壞味道與重構指南

     編輯:Java 相關知識

前言:識別代碼壞味道,提升軟體品質

在 Java 開發過程中,代碼重複、過長方法、臃腫類別等問題屢見不鮮。這些「代碼壞味道」不僅降低可讀性,更增加維護成本。Martin Fowler 在《重構》一書中系統梳理了常見壞味道,本文結合 Java 實戰場景,深度解析 21 種核心壞味道及其重構策略,助你寫出更優雅、可維護的代碼。

一、結構層面的壞味道

1. 代碼重複

最普遍的壞味道,通常源於「複製-貼上」編程習慣。重複代碼分散邏輯,修改時易遺漏。重構核心原則是 OAOO (Once And Only Once):提取公共方法、引入模板方法模式、或通過繼承/組合消除重複。

2. 過長方法

方法承擔過多職責,導致難以理解、測試與復用。遵循「單一意圖原則」:一個方法只做一件事。可通過 Extract Method 拆分邏輯,配合 Compose Method 重組調用鏈。

3. 臃腫類別

類別職責過重,違反 單一職責原則 (SRP)。拆分策略:識別內聚的屬性與方法群,提取為獨立類別(Extract Class),或引入組合模式將行為委託給協作對象。

二、變化管理相關的壞味道

4. 發散式變化

單一類別因不同原因頻繁變更(如業務規則變動、資料庫結構調整、UI 交互修改)。重構方向:將變化方向隔離,按變化原因拆分類別,使每個類別只因單一原因變化。

5. 霰彈式修改

一處需求變更引發多個類別連鎖修改。表明相關行為與數據分散在不同類別。解決方案:將共同變化的數據與行為聚合到同一類別(Move Method、Move Field)。

6. 功能嫉妒

方法頻繁調用其他對象的 getter 進行計算,而非操作自身數據。判斷標準:若方法對某類數據的訪問遠超自身類,應 將行為移至數據所在類(Move Method),或引入 Visitor 模式處理跨對象操作。

7. 數據泥團

多個類別、方法參數中反覆出現相同數據組合(如 `startDate/endDate`、`street/city/zip`)。這些數據應 封裝為值對象(如 `DateRange`、`Address`),提升語義表達與復用性。

8. 基本型別執著

用 `int` 表示金額、`String` 表示電話號碼,缺乏領域語義與驗證邏輯。重構:引入小對象封裝基本型別(如 `Money`、`PhoneNumber`、`PostalCode`),利用類型系統約束業務規則。

三、繼承與多態相關壞味道

9. Switch 語句濫用

基於類型碼或常量的 `switch/if-else` 鏈,破壞開閉原則。重構路徑:以多態取代條件邏輯——引入子類、狀態模式或策略模式,將分支行為封裝為獨立類別。

10. 平行繼承體系

新增一個子類,必須同步新增另一體系的對應子類(如 `Employee`/`EmployeeFactory`、`Document`/`DocumentPrinter`)。本質是 霰彈式修改的特例,解法:將從屬關係內化為單一體系內的組合(如 `Employee` 持有 `Factory` 引用)。

11. 冗餘類別

類別職責過輕,維護成本超過價值。常見於過度設計的中介類、僅委託的包裝類。果斷 內聯類別,將職責併入調用者。

12. 投機性通用性

為「未來可能用到」預留的抽象層、鉤子方法、參數化配置。YAGNI 原則指導:僅為當前需求設計,未被生產代碼調用的通用性代碼應刪除,測試用例除外。

四、封裝與協作缺陷

13. 臨時字段

對象某些字段僅在特定場景下有效(如演算法中間狀態),導致對象狀態語義模糊。重構:提取專用類別持有臨時字段,將相關演算法遷移至此類(Extract Class + Move Method)。

14. 訊息鏈

調用鏈過長:`a.getB().getC().doSomething()`。客戶端過度依賴對象內部結構。解法:隱藏委託關係,在中介對象添加便捷方法,或引入 外觀模式簡化接口。

15. 中間人

類別過度委託,接口多數方法僅轉發調用。雖封裝內部結構,但造成「空殼類」。重構:移除中間人,讓客戶端直接訪問委託對象,或將實質行為下沉至委託類。

16. 過度親密關係

雙向直接訪問私有成員、互相調用內部方法。破壞封裝邊界。重構手段:將共享行為提取為獨立類、引入中介者模式、或重新劃分職責邊界。

17. 接口不一致的替換類

功能相似的類擁有不同方法簽名(如 `load()` vs `read()`)。重構:統一協議接口,向上提取公共介面,配合適配器模式兼容既有實現。

五、其他常見問題

18. 不完美的庫類

第三方庫缺乏所需功能且難以修改。對策:引入包裝器/裝飾器擴展行為,或採用 擴展點模式隔離對庫的依賴。

19. 純數據類

類別僅含字段與 getter/setter,無業務行為。違反「對象 = 數據 + 行為」原則。重構:將操作該數據的行為遷移至類內(Move Method),若屬於 DTO 則明確標記為數據傳輸對象。

20. 被拒絕的遺贈

子類僅使用父類少量功能,繼承關係語義不清。通常意味著 繼承層次設計錯誤。解法:改用組合委託,或重新設計層次結構,確保「Is-A」關係成立。

21. 過度註釋

代碼自述性差,需大量註釋解釋「做什麼」。註釋應解釋「為什麼」,而非「怎麼做」。重構目標:通過命名、結構、提取方法使代碼自文檔化,註釋僅補充業務語境與非顯性決策。

總結:重構是持續改進的習慣

識別壞味道不是目的,重構才是核心。建議在日常開發中:

  • 代碼審查時建立「壞味道檢查清單」
  • 小步提交,每次重構聚焦單一壞味道
  • 配備完善單元測試保障重構安全
  • 團隊共享重構模式庫,沉澱最佳實踐

記住:代碼質量不是寫出來的,是重構出來的。

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