SOLID Principles
#OOP
SOLID principles 是 Uncle Bob (Robert C. Martin) 在 2004 年整理的五個 OOP 設計原則的縮寫(但有些原則不是 Uncle Bob 自己提出的),它們分別是:
Single Responsibility Principle
一個 class 不應該同時為多個「角色」實作功能,應只對一個角色負責。
範例
一間公司裡有三種職位:hr、accounting 與 engineer,每個員工都有 reviewPerformance 與 askForLeave 兩個動作,不同職位的 reviewPerformance 方式不同,但他們 askForLeave 的方式都相同。
錯誤做法
把所有邏輯都在 Employee 中實作,透過 if-else 來管理不同職位 reviewPerformance 的方法,這樣很容易讓整個 method 看起來又臭又長:
class Employee {
public reviewPerformance(title: "hr"|"accounting"|"engineer"): number {
if (title === "hr") {
// implement algorithm for hr
} else if (title === "accounting") {
// implement algorithm for accounting
} else {
// implement algorithm for engineer
}
}
public askForLeave(): void {
// implement algorithm for hr, accounting and engineer
}
}建議做法
把每個職位獨立成一個 class,Employee class 拉成階層較高的 abstract class,只實作內容相同的部分(如 askForLeave method),其它交由各個繼承 Employee 的 class 實作:
abstract class Employee {
protected abstract reviewPerformance (): number;
protected askForLeave (): void {
// implement algorithm for hr, accounting and engineer
}
}
class Hr extends Employee {
protected reviewPerformance (): number {
// implement algorithm
}
}
class Accounting extends Employee {
protected reviewPerformance (): number {
// implement own algorithm
}
}
class Engineer extends Employee {
protected reviewPerformance (): number {
// implement algorithm
}
}參考資料
Open-Closed Principle
一個系統應該要可以擴充功能,且擴充功能時應不須要修改到既有功能的 code,也不用擔心既有的功能壞掉。
實務上的例子如 Google Chrome,你可以在上面安裝多個 extensions,這些 extensions 的開發者不須要修改到 Google Chrome 的 code 就可以開發出各式各樣的 extensions。
參考資料
Liskov Substitution Principle
詳見 Liskov Substitution Principle。
重點摘要
若把 codebase 中任何型別為 $T$ 的物件替換成型別為 $S$ 的物件後,仍然可以正常運行,則稱型別 $S$ 為型別 $T$ 的 subtype,或說 $T$ 為 $S$ 的 supertype。
==Subtype 與 subclass 是兩個完全不相干的概念==,只有遵守特定規則來繼承,才會形成 subtype,否則就只是 subclass。
當你想要使用繼承時要非常小心,因為==大多數的情況都不該用繼承==,繼承是所有依賴關係裡面最強的,而太過依賴總是沒啥好事。
Interface Segregation Principle
重點摘要
不要定義單一個功能過度全面的 interface,因為不是大家都想實作你定義的所有 methods,應該把它們拆成幾個功能內聚性高的 interfaces。
反過來說,class 也不要隨便依賴一些自己其實用不到的 interfaces。
遵守 ISP 的優點:小則當底層模組有變動時,沒有依賴它的其它模組就不用 recompile;大則當底層的系統元件有變動時,沒有依賴它的其它系統元件就不用跟著修改。
參考資料
Dependency Inversion Principle
重點摘要
表層模組不應依賴於底層模組,兩者都應依賴於 interface/abstract class。
Interface/abstract class 不應依賴於具體實作,反而是具體實作應該依賴於 interface/abstract class。
何謂「依賴」?
想了解「依賴」(dependency) 的定義,可以參考 Dependency Injection,但請注意,dependency injection 與 dependency inversion principle 是不同的概念。
實現方式
Inversion of Control.draft (IoC)
[!Note] IoC 是一個比較廣義的概念,並不是所有形式的 IoC 都遵守 Dependency Inversion Principle。
參考資料
Last updated