SOLID 原則:軟體設計的基本原則
高質量的軟體設計是構建可靠、可維護和可擴充套件軟體系統的關鍵。SOLID 原則是一組指導軟體開發的五個基本設計原則,它們幫助開發者建立更加健壯和靈活的系統。
SOLID 原則是五個設計和程式設計的基本原則,它們分別是:單一職責原則(Single Responsibility Principle, SRP)、開放封閉原則(Open-Closed Principle, OCP)、里氏替換原則(Liskov Substitution Principle, LSP)、介面隔離原則(Interface Segregation Principle, ISP)和依賴倒置原則(Dependency Inversion Principle, DIP)。
單一職責原則(SRP)
單一職責原則強調每個軟體模組應該只有一個引起變化的原因。
SRP 是 SOLID 五大設計原則中最容易被誤解的一個。很多程式設計師根據 SRP 這個名字想當然地認為這個原則是指:一個模組應該只有一個職責或者每個模組都應該只做一件事。雖然也的確有這麼一個設計原則,即確保一個函式只完成一個功能,這在我們將大型函式重構成小函式時經常會用到。但這只是一個面向底層實現細節的設計原則,並不是 SRP 的全部。
對 SRP 更準確的描述應該是:任何一個軟體模組都應該只對某一類行為者負責。通俗一點講,就是一個模組應該只給同一類別的使用者使用,或者說這個模組使用者使用這個模組改變系統行為時都是基於相似的原因。
開放封閉原則(OCP)
開放封閉原則原則認為,設計良好的計算機軟體應該易於擴充套件,同時抗拒修改。換句話說,一個設計良好的計算機系統應該在不需要修改的前提下就可以輕易被擴充套件。這意味著當我們需要新增新功能時,應該儘量透過擴充套件現有程式碼來實現,而不是修改現有程式碼。
OCP 是我們進行系統架構設計的主導原則,其主要目標是讓系統易於擴充套件,同時限制其每次被修改所影響的範圍。
OCP 的實現方式是透過將系統劃分為一系列元件,並且將這些元件間的依賴關係按層次結構進行組織,使得高階元件不會因低階元件被修改而受到影響。
里氏替換原則(LSP)
里氏替換原則簡單來說就是如果想用可替換的元件來構建軟體系統,那麼這些元件就必須遵守同一個約定,以便讓這些元件可以相互替換。
早期,大家普遍認為 LSP 不過是指導如何使用繼承關係的一種方法,然而隨著時間的推移,LSP 逐漸演變成了一種更廣泛的、指導介面與其實現方式的設計原則。這裡的介面可以有多種形式——可以是類似 Java 的介面,有多個實現類;也可以像 Ruby 一樣,幾個類共用一樣的方法簽名,也可以是幾個服務響應同一個 REST 介面。這些場景中的使用者都依賴於一種介面,並且都期待該介面的不同實現具有可替換性。
介面隔離原則(ISP)
介面隔離原則主要告誡軟體設計師應該在設計中避免不必要的依賴。
在一般情況下,任何層次的軟體設計如果依賴於不需要的東西,都會是有害的。從原始碼層次來說,這樣的依賴關係會導致不必要的重新編譯和重新部署,對更高層次的軟體架構設計來說,問題也是類似的。
依賴倒置原則(DIP)
依賴倒置原則出高層策略性的程式碼不應該依賴實現底層細節的程式碼,恰恰相反,那些實現底層細節的程式碼應該依賴高層策略性的程式碼。
DIP 主要想告訴我們的是,如果想要設計一個靈活的系統,在原始碼層次的依賴關係中就應該多引用抽象型別,而非具體實現。
實際上,嚴格執行執行這條設計原則是不現實的,因為軟體系統在實際構造中不可避免地需要依賴到一些具體實現。只要這些具體實現是穩定的,可能的修改也受到嚴格的控制,那麼直接依賴這些具體實現不會存在太大的問題。
我們主要應該關注的是系統內部那些會經常變動的具體實現模組,這些模組是不停開發的,也就會經常出現變更。如果想要在軟體架構設計上追求穩定,就必須多使用穩定的抽象介面,少依賴多變的具體實現。設計師和架構師會花費很大精力來設計介面,以減少未來對其進行改動,爭取在不修改介面的情況下為軟體增加新的功能。
應用設計原則(DIP)
在實際的軟體開發過程中,SOLID 原則可以指導我們進行更合理的設計決策。以下是一些應用 SOLID 原則的策略:
- 識別職責:在設計模組時,識別並分離不同的職責,確保每個模組只對一個行為者負責。
- 使用抽象:透過定義穩定的抽象層,降低系統對具體實現的依賴,提高系統的可擴充套件性。
- 避免過度設計:遵循開閉原則,避免過早地設計系統可能不需要的功能,減少不必要的複雜性。
- 定義清晰的介面:遵循介面隔離原則,為不同的客戶端定義不同的介面,避免不必要的依賴。
- 反轉依賴:透過依賴注入等技術,使高層模組依賴於抽象,而不是低層模組的具體實現。
在實際的軟體設計過程中,我們需要根據專案的具體需求和團隊的實際情況來靈活運用這些原則。雖然這些原則並不是銀彈,但它們確實為我們提供了一種有效的思維方式和方法論,幫助我們設計出更加健壯、可維護、可擴充套件的軟體系統。這些原則不僅幫助我們避免了一些常見的設計錯誤和陷阱,還提高了程式碼的質量和可重用性。因此,在軟體設計和開發過程中,我們應該深入理解並靈活運用這些原則。