.NET Core TDD 前傳: 編寫易於測試的代碼 -- 單一職責


第1篇: 講述了如何創造"縫".  "縫"(seam)是需要知道的概念.

第2篇, 避免在構建對象時寫出不易測試的代碼.

第3篇, 依賴項和迪米特法則.

第4篇, 全局狀態引起的問題.

本文是第5篇, 也是最后一篇, 介紹的是單一職責

 

類做了太多的工作

例子, 某軟件公司, 原有項目開發, 測試, 售前, 售后, 財務等員工. 后來由於公司沒錢, 裁掉了測試, 讓開發兼職; 過了段時間, 又裁掉了需求和售后, 還是由你這個開發來兼職; 再過了段時間, 又裁掉了財務和售前, 還是由你來兼職.

某天上班之后, 你剛想寫代碼, 就接到了客戶來電, 說鍵盤不好用, 讓你去給調試一下. 花了1個小時從客戶那里調試回來又剛想寫點代碼, 某客戶說發票沒給, 你又去快遞發票. 回來之后又想寫代碼, 又有客戶來電話咨詢你公司的XXX管理系統, 經過半個小時的講解, 客戶沒興趣. 這時已經到了中午, 你卻發現你的本職工作一點都做.

在現實世界中, 給某個員工賦與很多沖突的角色或職責是很不明智的.

在軟件開發里也是這樣的, 在為一個類賦予太多的職責會引出很多維護和測試的問題.

單一職責

單一職責是面向對象軟件設計的准則之一, 它說的是: "一個類只能因為一個原因去改變".

這就是說我們應該增加 因為相同原因而做出改變的東西 的內聚性, 而降低 由於不同原因而做出改變的東西 的耦合性.

這句話通常被描述為: "一個類或一個方法只應該做一件事情, 並且要把它做好".

 

如果一個類有了太多的職責, 那么職責間的交互就會埋藏於類里, 這樣做就很難一次修改一個職責. 對於測試來說, 這些交互之間也沒有明顯的"縫隙".

依賴項的構建工作並不是目標類本身的職責, 這項工作應該和類本身的職責分開. 所以我們會使用依賴注入配置好的對象. 我們應該對類進行抽取, 讓其成為單一職責的類.

 

引起的問題

如果一個類有多個職責, 那么在測試上它會有以下問題:

  • 如果一個類/方法有太多的功能, 那么針對它的測試就會特別多, 很容易讓人難於理解也很難維護.
  • 測試的設置也會更加的麻煩. 
  • 由於有多個原因去修改該類, 那么它的測試類/方法就會修改的更加頻繁.

 

危險信號

什么樣的類/方法會違反單一職責呢?

  • 如果你在描述該類功能的時候用到了"和", "或", "還", "並且"等詞.
  • 類或者方法的代碼很多.
  • 注入了太多的依賴項.
  • 一個類改變的太頻繁了也可能意味着這個類的職責可能不止一個.

 

解決方案

如果一個類有很多職責, 那么可以這樣做:

  • 識別出類里面各個獨立的職責.
  • 給每個職責貼上標簽.
  • 解耦, 把其它功能抽取到單獨的類, 最后保證每個類都是單一職責.

 

例子

舉一個很簡單的典型例子:

 

這個類, 有4個依賴項, 不算特別多, 但是也不少. 它的名字在這里就是它的描述, 里面包含了"或"的意思. 在它的方法參數里, 有一個標識, 像這樣會改變方法的高級行為的標識, 通常就意味着該方法會有不止一個職責. 而方法體里面, 我們可以看到它確實有兩個職責, 分別是發送郵件和打電話給客戶.

 

優化后

經過識別, 抽取后, 該類應該分成下面兩個類:

EmailCommand:

 

 

CallCommand:

 

這個系列的帖子就到這了.

下面開始介紹TDD.

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM