核心觀點#

在軟體開發中,我們往往面臨一個兩難:「讓程式運作」「讓程式整潔」

多數開發者在讓程式運作後就停手了,轉向下個任務,卻忽略這時正是該回頭整理程式碼的關鍵時刻。
良好的類別設計是組織大型系統複雜度的基石,它讓開發者能迅速找到目標,
並只需理解當前受影響的範圍,而無需將整個系統的複雜性塞入腦中。

  • 類別應該要短小: 過長類別通常代表承擔了過多職責
  • 單一職責原則 (SRP): 一個類別應只有一個修改理由
  • 高凝聚性 (High Cohesion): 類別內的變數與方法應緊密相關,形成邏輯上的一體

類別的組織結構#

封裝與可見性#

根據標準的 Java 或物件導向慣例,類別內的元素排列順序通常如下:

  1. 變數列表: 靜態公用常數 ➡️ 靜態私有變數 ➡️ 私有實體變數
  2. 函式列表: 公用函式 ➡️ 該函式呼叫的私有工具函式(由上而下)

變數和工具函式應盡量保持為 privateprotected
我們應極力避免讓變數公開,保持封裝性是控制系統混亂的第一步。

類別應保持短小#

關於類別設計的第一條規則是「短小」,
第二條規則是「還要更短小」。

  • 衡量的標準: 我們不以程式碼行數衡量,而以職責 (Responsibilities) 衡量
  • 命名檢測法: 如果無法用簡潔名稱命名(例如名稱須包含 Processor, Manager, Super),
    或在描述類別功能時須用「而且 (And)」、「或者 (Or)」等連接詞,通常代表它做太多事了

凝聚性 (Cohesion) 與拆分#

凝聚性是衡量類別設計品質的重要指標。

什麼是凝聚性?#

類別應只有少量實體變數(Instance Variables),且類別中每個方法都應操作這些變數中的一或多個。

  • 高凝聚性: 當類別中的方法頻繁地使用該類別變數時,代表它們邏輯上緊密合成一體
  • 低凝聚性: 若某些變數只被少數幾個方法使用,這就是一個訊號——該拆分了

如何拆分?#

當你發現一個大函式,為了重構而拆解成數個小函式時,往往這些小函式需共用某些變數。
這時,不要將這些變數提升為原類別的全域變數(這會降低凝聚性),
而應將這些小函式與它們共用的變數,獨立抽離成一個新類別

重構路徑參考
  1. 現狀: 一個巨大的函式,包含複雜邏輯
  2. 第一步: 拆解大函式為多個小函式
  3. 副作用: 參數傳遞變複雜,或類別內出現一組「只有幾個新函式會用到」的實體變數
  4. 解決方案: 將這組變數與函式移出,建立一個新的小類別。這能讓原類別恢復高凝聚性

為了變更而設計#

軟體系統必須持續演進,而每次修改都有破壞現有功能的風險。
良好的類別設計能將這種風險降至最低。

1. 開放閉合原則 (OCP)#

理想系統應由許多小類別組成,特徵是:不需修改現有程式碼,就能透過「擴充延伸」併入新功能。
需要新增功能時,應是繼承或實作新類別,而不是打開現有類別去修改原本邏輯(這易引入 Bug)。

2. 相依性反向原則 (DIP) 與解耦#

  • 隔離修改: 具體類別(Concrete Classes)包含實作細節,而細節會變動。
    我們應用介面(Interface)與抽象類別(Abstract Class)隔離這些變動
  • 降低耦合: 最小化類別間的耦合性,意味類別應相依於抽象性,而非具體細節
    這不僅讓系統更靈活,也讓單元測試更容易(可用 Mock 物件模擬抽象介面)

“Systems that are clean allow us to extend them without modifying existing code.”
整潔系統允許我們在不修改現有程式碼的情況下進行擴充。