一個類別應該只有一個改變的原因
定義職責
單一職責SRP中,我們把責任定義為變化的原因
大家習慣把相關的行為、資料通通封裝再一起
實際上已經超過一種以上責任
甚至把不相關的(Utility、Util之類的)也通通封裝再一起
這種不用說了,一定違反單一職責原則SRP
你是否有遇到?
- 改A地方壞B地方 (脆弱性,修改時會導致相依所產生連動的BUG)
- 一個Class的行數過多 (代表有些工作可能可以分離開來)
- 無法寫測試 (高耦合,需要傳入參數過多,不好寫測試)
- 有使用到”or” 或 “and” 的字 (兩個以上的責任)
- 有使用Utility、Util之類的名稱
範例
舉書中兩個範例
1.Modem
Modem 數據機中有 dial撥號、handup掛斷、send傳送資料跟 recv接收資料四種方法
在這個方法中有兩個職責,一個是連接管理(dial、handup),另一個是資料通訊(send、recv)
一旦資料通訊或連接管理需要修改時,呼叫到另一部分也跟著需要修改或重新編譯
這時候就會有僵化性(依賴關係發生連鎖異動)與脆弱性(修改時造成很多地方出現BUG)的壞味道
這時候就可以將兩個職責拆開
這樣的好處是當發生問題時不會影響到另一個,而且其中一個修改後不需要重新編譯
2.Rectangle
Rectangle有兩個方法
- area 算面積
- draw 在GUI上畫圖
上圖展示的同一類裡兩個方法會因為計算面積的方法改變,而有機會去影響其他使用者
面積的算法與畫圖的方式是兩個改變的原因,這樣這一個類別有兩個職責
所以我們必須將這兩個性質的就可以分開如下圖來實作
分離職責的困難點
- 職責的劃分:劃分角度會影響職責大小
- 類別的命名:命名的重要,是否將責任清楚的表達
- 顆粒度的控制:切割太細過於複雜
- 類別之間的依賴:如果這兩個職責永遠連動都是同時變化,那就不必分離,否則會違反不必要複雜性的壞味道,不需要過度提早優化
總結
如書中所說,SRP為最好理解但最難運用正確的原則,就是發現職責,並且將職責分離,但職責要怎麼分離要依實際情況,也是最難實作的
參考來源
Agile Principles, Patterns, and Practices in C#, Robert C. Martin (Author)