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。
重點摘要
若在可運行的 function(或程式碼片段)中,將任何型別為 $T$ 的物件替換成型別為 $S$ 的物件後,function/程式碼片段應該仍然可以正常運行,則稱型別 $S$ 為型別 $T$ 的 subtype,或說 $T$ 為 $S$ 的 supertype。
==Subtype 與 subclass 是兩個完全不相干的概念==,只有遵守特定規則來繼承,才會形成 subtype,否則就只是 subclass。
當你想要使用繼承時要非常小心,因為==大多數的情況都不該用繼承==,繼承是所有依賴關係裡面最強的,而太過依賴總是沒啥好事。
Interface Segregation Principle
Interface 不要定義地太過全面,因為不是大家都想實作你定義的所有 methods。反過來說,class 也不要隨便實作一些自己其實用不到的 interfaces。
參考資料
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