S.O.L.I.D原則
S.O.L.I.D原則
講師: Will保哥
課程:.NET 技術講座:打造堅固耐用的 C# 程式碼
圖片來源: Will保哥 .NET 技術講座:打造堅固耐用的 C# 程式碼 課程投影片
- 耦合度
耦合度越高,代表程式之間的相依性越高,容易造成改A壞B的情況(==耦合是不可避免的==)
- 內聚力
在一個模組內只完成一件事情,意味著這個模組可以被重複利用(例如發送通知) 低內聚的表現,意味著將所有的功能都寫在同一個class,造成難以維護、理解
內聚力越高,類別越多,耦合度會增加
耦合度越低,類別越少,內聚力降低
兩者是互相衝突的,要靠當下的情境來判定使用
學習S.O.L.I.D物件導向設計原則的好處
- 降低程式碼複雜度
- 較佳的程式碼可讀性
- 提升模組可重複利用姓
- 使模組具有高內聚低耦合
- 面臨需求變更時可減少破壞現有模組的風險
S.O.L.I.D
單一責任原則SRP (Single Responsibility Principle)
SRP主要精神就是提高內聚力。每個類別盡量只做一件事。
- 常見問題: 1.類別複雜度過高 2.維護時找不到要改哪 3.發生邏輯問題時找不到Bug在哪 4.使用類別時不知道應該呼叫哪個方法
- 使用時機:
- 在確認需求的情況下,如果只有一個類別需要用到這個方法,那就==不需要額外拉出==一個新的類別來為了做到SRP。
- 類別中有一段程式碼有重複利用的需求。
- 系統中有非必要的功能(未來的需求),老闆逼你要實作時,責任會依附在類別中,對維護造成困擾,這時候就可以透過SRP來實作。
開放封閉原則OCP (Open Closed Principle)
開放擴充但封閉修改 藉由新的程式碼來擴充系統的功能,而不是藉由修改已存在的程式碼來擴充系統
- OCP的使用時機:
既有的類別已經被清楚定義,處於一個強調穩定的狀態 需要擴充現有的類別,加入新的屬性或方法 擔心修改現有的程式碼會破壞現有系統的運作 系統開始設計時就決定要採用OCP模式 ==可以透過"介面"或"抽象類別"進行實作==
里氏替換原則LSP (Liskov Substitution Principle)
建議使用==介面==來實作LSP,來降低耦合度。 LSP在實作時,要注意,實作的方式是否正確 ==子類別替換基底類別的時候不會報錯==
介面隔離原則ISP (Interface Segregation Principle)
把不同的屬性和方法,放在不同的介面中 特定需求沒用到的方法,不要加入介面中 使系統可以容易的達成鬆散耦合,安全重構,功能擴充
- ISP的使用時機:
當介面需要被分割的時候 假設類別有20個方法,並實作一個有15個方法的介面 有某個用戶端只會使用該類別中的10個方法 你就可以為這類別的10個方法定義介面並設定實作介面 你的用戶端就可以改用介面操作 這個過程可以用來降低主程式與這個類別的耦合力
不符合ISP介面隔離原則,==BeginTransaction沒有被使用到==
符合ISP介面隔離原則,==沒有用到的方法應該額外獨立出來==
讓使用者可以自行決定要實作哪個介面,若使用不存在的則會報錯
相依反轉原則DIP (Dependency Inversion Principle)
所有類別都要相依於抽象,而不是具體實作 可透過DI Container達到目的 為了要達到類別間鬆散耦合的目的 開發過程中,所有類別之間的耦合關係一律透過抽象介面
- 關於DIP的實作方式
- 型別全部都相依於抽象,而不是具體實作
- 經過套用DIP之後,原來有相依於類別的程式碼
- 都改成相依於抽象型別
- 從緊密耦合的關係變成鬆散耦合關係
- 可以依據需求,隨時抽換具體實作類別
關於DIP的使用時機:
- 想要降低耦合的時後
- 希望類別都相依於抽象,讓團隊更有效率的開發系統
- 想要可以替換具體實作,讓系統變得更有彈性
- 符合DIPP通常也意味者符合OCP與LSP原則
- 只要再多考量SRP與ISP就很棒了
- 想要導入TDD或單元測試的時候