# 物件導向程式設計基本原則 - SOLID >由 *Robert C. Martin* 所提出的物件導向設計五個原則(SOLID):單一職責、開放封閉、里氏替換、接口隔離以及依賴反轉 * 高內聚(high cohesion):同樣或類似的功能有沒有聚在一起,當有改動需求時,影響範圍就會縮小 * 低耦合(low coupling):模組與模組之間的關係黏著度越小越好 ## Single Responsibility Principle(SRP, 單一職責原則) >一個類別中不要有多於一個以上的變化理由 每個物件,不管是類別、函數,負責的功能,都應該==只做一件事==。 對函數而言,一個函數內同時做了兩件以上的事情,當發生錯誤時,很難快速定位錯誤的原因,也容易間接導至程式碼的可閱讀性降低。 另外如果將事情切分的太細(over design),使程式碼變得細碎不堪,這反而也會降低程式碼可讀性,因此一般只要求「接口必須保持單一原則」,而類別去套用接口,類別就盡量達成少的職責就好。 ## Open/Close Principle(OCP, 開放/封閉原則) >軟體中的實體,例如:類別、模組、函數等等,都必須對延伸開放,但對修改封閉 當需求有異動時,要如何在==不變動現在正常運行的程式碼==?使用「抽象」的方法 * 繼承(多型) * 抽象介面 * 依賴倒轉(Dependency Injection pattern, DIP) * 裝飾者模式 * 策略模式 如果為了新需求,去修改了原本的程式中的某一個函數,可能會造成其他呼叫使用該函數的的功能,出現非預期的錯誤。 ## Liskov substitution principle(LSP, 里氏替換原則) >子類對象能夠替換其父類對象,並且當子類使用父類方法時不會有問題 用於規範繼承,可以簡單測試執行父類別的某方法,再透過子類別測試執行該方法是否正常,如果正常執行代表這個繼承關係是健康的。如果反之則應該斷開父子繼承關係,採用依賴、聚合、組合等關係替代。 ## Interface Segregation Principle(ISP, 介面隔離) >客戶類不應該被強迫依賴那些它不需要的接口,類別間的彼此依賴應該建立在盡可能小的接口上 針對不同需求的用戶,開放其對應需求的介面提拱使用。可避免不相關的需求介面異動,造成被強迫一同面對異動的情況。 當介面規定了太多要求,而我們實作的子類別只需要其中一部份,或是有些要求根本無法達成,就會發生這個困境:放棄實作介面,或是用空實作和錯誤處理去欺騙介面。 ## Dependency Inversion Principle(DIP, 依賴反轉原則) >高階模組不應依賴低階模組,兩個都應該依賴在抽象概念上;抽象概念不依賴細節,而是細節依賴在抽象概念 > 這邊還有個例子我很喜歡,在這篇[依賴倒置原則](https://notfalse.net/1/dip)的文章中,用吃東西來舉例:如果寫死了依賴漢堡,難道一輩子就只能吃漢堡了嗎?如果想改成吃義大利麵,就要修改程式碼;有一百種食物,難道就要改一百次嗎? 我們在開發功能的時候,都是讓大功能(高階模組)調用各個小功能(低階模組)來實現目標,越高層的就越整體、越抽象、越接近目標;而越低階就越細節、越接近實作,關注點越小。而我們的思維通常是由大範圍往下到小實作,從整體目標逐漸拆解成各個步驟。 但是,當我們的高階模組直接依賴低階模組的時候,事情就會變得有點怪怪的。就像董事長必須清潔廁所導致沒空進行公司決策一樣,原本職責在於高層次、整體的模組,卻不得不因為這些低階模組的變動受到影響。那麼隨著層次越高,底下依賴的模組越多,改動的頻率就會提高。 並不是低階模組的實作提供了抽象層,而是高階模組針對所需要的功能提出了抽象,而低階模組去實現它。 原本是 `高階模組 → 低階模組` 的關係,變成了 `高階模組 → 介面 ← 低階模組` ## Reference **SOLID** [物件導向武功秘笈(3):內功篇 — 物件導向指導原則SOLID](https://www.ycc.idv.tw/introduction-object-oriented-programming_3.html) [09. 物件導向設計原則—SOLID](https://ithelp.ithome.com.tw/articles/10191553) [開放封閉原則 Open-Closed Principle (OCP)](https://medium.com/@f40507777/%E9%96%8B%E6%94%BE%E5%B0%81%E9%96%89%E5%8E%9F%E5%89%87-open-closed-principle-31d61f9d37a5) [菜雞與物件導向 (13): 介面隔離原則](https://igouist.github.io/post/2020/11/oo-13-interface-segregation-principle/) ###### tags: `design pattern`