第1篇: 講述了如何創造"縫". "縫"(seam)是須要知道的概念.html
第2篇, 避免在構建對象時寫出不易測試的代碼.ide
第3篇, 依賴項和迪米特法則.單元測試
本文是第4篇, 將介紹全局狀態引發的問題.測試
全局狀態, 也能夠叫作應用程序狀態, 它是一組變量, 這些變量維護着應用程序的高級狀態.ui
在程序裏, 全局狀態可能都存放在一個全局狀態對象裏, 例如ASP.NET裏面的HttpContext; 或者它們多是全局的變量, 這些全局變量在程序的任何地方均可以訪問.spa
不論是如何實現的全局狀態, 每一個全局狀態變量在內存裏只有一個實例. 因此若是一個類裏更新了全局變量的值, 那麼另外一個類訪問該變量的時候它的值就是剛纔被更新的值.code
有些狀況下, 使用全局狀態確實有用; 可是若是使用不當, 則會對測試形成很大的影響.htm
就舉一個例子吧.對象
有這樣一個獲取當前登陸用戶權限的類, 它使用的是單例模式:blog
這個是典型的單例模式, 它會保證在程序中只返回一個實例, 這裏就很少介紹了.
下面這個Service會調用上面這個Auth類:
Auth是單例模式的, 並且還調用了靜態方法.
如今的狀態是, OfficeService和Auth所包含的全局狀態緊密的耦合到了一塊兒.
首先應該把單例模式去掉, Auth類只保留兩個屬性和一個方法:
而後在service裏面應該注入IAuth接口並使用:
那麼接下來就須要保證這個IAuth不管在程序中注入了多少次, 都是同一個實例.
這時就須要使用依賴注入(DI) 庫了. 如今的DI庫一般容許指定IoC容器中每對綁定服務的做用範圍(Scope), 或叫作生命週期管理.
例如ASP.NET Core內置的IoC容器就內置了這種功能. 在ASP.NET Core 項目的Startup類裏, 這樣寫就能夠保證每次請求IAuth的時候只會獲得同一個對象實例:
如今這個"單例"的工做是由IoC容器來負責了. 在其它地方正常的注入IAuth使用便可.
先寫到這, 本文的概念性內容和更多的例子請參考Angular創始的人這篇文章: http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/