Robert C. Martin (Uncle Bob)

良好設計的基礎原則#

將因相同原因而變動的東西聚集在一起,將因不同原因而變動的東西分開。

這個原則通常被稱為單一職責原則(Single Responsibility Principle, SRP)。簡言之,一個子系統、模組、類別甚至函式,都不應該有超過一個需要變動的理由。

經典的反面教材#

一個典型的例子是一個處理商業邏輯、報表和資料庫的類別:

public class Employee {
    public Money calculatePay() ...
    public String reportHours() ...
    public void save() ...
}

有些程式設計師可能認為把這三個功能放在一起完全合理——畢竟類別本來就是操作共同變數的函式集合。然而問題在於,這三個函式因完全不同的原因而改變:

  • calculatePay商業規則改變而改變
  • reportHours報表格式需求改變而改變
  • saveDBA 調整資料庫結構而改變

這三個變動原因的結合使得 Employee 非常不穩定。更重要的是,任何依賴 Employee 的類別都會受到這些變動的影響。

正確的分離方式#

將職責分離到不同的類別中:

public class Employee {
    public Money calculatePay() ...
}
public class EmployeeReporter {
    public String reportHours(Employee e) ...
}
public class EmployeeRepository {
    public void save(Employee e) ...
}

每個類別可以放入各自的元件中——報表相關類別進入報表元件、資料庫相關類別進入 repository 元件、商業規則進入商業邏輯元件。這些類別可以獨立修改和獨立部署,任何一個的修改都不會強迫其他元件重新編譯或重新部署。

依賴反轉的進一步可能#

雖然上述方案中 Employee 仍然被其他類別依賴,但透過**依賴反轉原則(Dependency Inversion Principle, DIP)**的運用,甚至 Employee 本身也可以獨立修改和部署——但那是另一本書的主題了。

謹慎運用 SRP,將因不同原因而變動的東西分開,是打造具有獨立可部署元件結構設計的關鍵之一。