原文連結:The S.O.L.I.D Principles in Pictures
本文所刊登的圖片,皆屬原作者 Ugonna Thelma 所有。
這篇比較特別一點,是從「イラストで理解するSOLID原則 - Qiita」這篇翻譯得知英文原文,因此會以英翻中為主。
本文將以圖解方式,依序說明 SOLID 原則:
以下正文開始。
若您熟悉物件導向程式設計,那麼您應該聽過 SOLID 原則。
這五個軟體開發原則,是在建立軟體時應遵循的指南,使軟體更容易擴展和維護。這些原則是由軟體工程師 Robert C. Martin 所推廣。
網路上雖然有許多關於 SOLID 的優秀文章,但我很少看到有附圖片的範例。這對於像我這樣的視覺學習者來說,想要參與學習是有點困難的。
因此,本文的主要目的就是通過插圖來幫助理解這些原則,並強調每個原則的目標。
其中一些原則可能看起來很類似,但其實並不針對相同的目標。即使看起來相似,也可能滿足一個原則並違反另一個原則。
為了使本篇內容簡單易懂,將使用詞語「Class(類別)」,但請注意這個詞語在本文也適用於 Function(函數)、Method(方法)或 Module(模組)。
更新*
有留言在本文中提到,「開放封閉原則 OCP」可能違反了「單一職責原則 SRP」,但需注意本文目的是單獨解釋每一個原則。
此外,責任(或角色)並不同於行動。在「單一職責原則」中,使用 "I am Painter",而在「開放封閉原則」中,則使用 "I can Paint"。
這一點非常重要,為了履行一個責任(或角色)可以執行多個動作。Class 應該具備一個責任(SRP),但實現該責任的功能應該能夠擴展的(OCP)。
現在,讓我們開始吧!
類別應該具備單一職責。
如果一個類別有多個職責,將提高錯誤的可能性。因為修改其中一個職責,可能會連帶影響其他職責。
這個原則的目標是確保操作分離,即使變更可能導致錯誤發生,也不會對其他無關的操作產生影響。
類別應該對擴展開放,但對修改封閉。
修改一個類別的當前行為,將會對使用該類別的所有系統造成影響。
若希望類別執行更多功能,理想的方法是添加功能到既有的函數,而不是進行修改。
這個原則的目標是擴展類別功能,而不改變該類別現有行為。藉此避免在使用該類別的地方出現錯誤。
若 S 是 T 的子類別(subtype),則程式中 T 型的 Object 可被 S 型的 Object 替換,且不改變程式的任何屬性。
當一個子類別無法與其父類別執行相同的操作時,這可能會引發錯誤。
若由一個類別建立另一個類別,該類別會成為父,新的類別成為子。子類別必須能夠執行父類別能夠執行的所有操作。這個過程稱作繼承。
子類別在處理與父類別相同的請求時,將會產生相同的結果,或相同類型的結果。
圖片顯示父類別可提供咖啡(任何種類的咖啡),而子類別提供卡布奇諾是可接受的,因爲卡布奇諾屬於咖啡的一種,但提供水則是不可接受的。
當子類別不符合這些要求時,代表著子類別完全改變,如此即違反了這個原則。
這個原則的目標是強制一致性,確保父類別或其子類別能夠以相同的方式使用,而不會出現任何錯誤。
客戶端不應被強迫依賴於未使用的方法。
在類別中執行不必要的操作將造成許多浪費,若該類別無法執行這些操作,則可能導致意外的錯誤。
類別應該只執行履行其職責所需的操作。其他操作應該完全刪除,或如果將來可能被其他類別使用,則應該移至其他地方。
這個原則的目標是將操作的集合分割成更小,以確保類別僅執行所需的功能。
高層模組不應該依賴於低層模組。兩者都應依賴於抽象化。
抽象化不應該依賴於細節。細節應該依賴於抽象化。
首先,簡單定義這裡使用到的術語。
高層模組(或類別):使用工具執行動作的類別
低層模組(或類別):執行動作所需的工具
抽象:表示連接兩個類別的介面
細節:工具的操作方式
在這個原則中,類別不應該與執行動作的工具混合在一起。相反地,工具應該與可以連接類別的介面融為一體。
此外,類別和介面都不應該知道工具的操作方式,但工具必須符合介面的規範。
這個原則的目標是透過引入一個介面,以減少高層類別對低層類別的依賴。
本篇針對這五個原則進行說明,並強調其目標。這些原則的目標是降低發生問題的可能,使程式碼易於調整、擴展及測試。
非常感謝您的閱讀。希望您對這個主題有更深的瞭解,並且在閱讀本文的過程能像我寫作的過程一樣愉快。
若有任何問題或建議,歡迎留下評論。