一位開發人員和我正在談論(輕描淡寫)對象的屬性的惰性加載。控制反轉,依賴注入瓦特/ SRP和延遲加載
- 他說,要使用靜態IoC查找調用來解析對象的對象並延遲加載對象。
- 我說違反SRP,並使用擁有的服務來解決該對象。
那麼,如何處理IoC和SRP之後的Lazy-Loading?
你不能單元測試那個懶加載的屬性。他斥責那個人說:「你已經爲UserStatsService進行了單元測試 - 這是你的代碼覆蓋範圍。」一個有效的點,但該屬性仍然未經測試,但「完整」的覆蓋。
設置/碼型:
- 項目採用嚴格的依賴注入規則(在所有服務中,庫的構建函數注入,等等)。
- 項目通過Castle的方式使用IoC(但可以是Unity等任何項目)。
一個例子如下。
public class User
{
public Guid UserId { get; set; }
private UserStats _userStats;
// lazy-loading of an object on an object
public UserStats UserStats
{
get
{
if (_userStats == null)
{
// ComponentsLookup is just a wrapper around IoC
// Castle/Unity/etc.
_userStats =
ComponentsLookup
.Fetch<UserStatsService>()
.GetByUserId(this.UserId);
}
return _userStats;
}
}
}
以上顯示了一個延遲加載對象的示例。我說不要使用它,並且在需要該對象的任何地方從UI層訪問UserStatsService。
編輯:下面的一個答案提醒我關於延遲加載的NHibernate技巧,這是虛擬化您的屬性,允許NHibernate創建延遲加載本身的過載。光滑,是的,但我們沒有使用NHibernate。
沒有人真正解決延遲加載的問題。一些好的文章,做題親近:
- Using Dependency Injection frameworks for classes with many dependencies
- http://blog.vuscode.com/malovicn/archive/2009/10/16/inversion-of-control-single-responsibility-principle-and-nikola-s-laws-of-dependency-injection.aspx
我看到延遲加載的好處。不要誤解我的意思,我只是懶惰地加載了我的複雜類型和它們的子類型,直到我轉向忍者的D.I.方式。好處是在用戶的統計信息顯示在用戶界面層,例如,在100行的列表中。但是對於DI,現在您必須引用幾行代碼才能獲得該用戶的統計信息(不違反SRP並且不違反德米特定律),並且必須經過這麼長的查找路徑100多次。
是的,加入緩存並確保UserStatsService被編碼爲Singleton模式,大大降低了性能成本。
但我想知道是否有其他人有[固執]的開發人員,不會屈服於IoC和D.I.完全規則,並具有有效的性能/編碼點來證明解決方法的正確性。
+1我完全同意這個問題應該在實體之外。有了NHibernate(我知道它是如何重載延遲加載屬性的,是的),這很容易。但是,我們不使用NHibernate。另外,在你描述的罕見用例(沒有NHibernate)的情況下,這很容易使用大量的內存 - 將子屬性加載到回購級別。因此,延遲加載的概念僅適用於需要的情況下的高性能。我會繼續研究其他模式。 – eduncan911 2010-01-12 19:59:34
在IList <>下執行延遲加載與NHibernate無關;這只是一個簡單的例子。它對靜態調用的主要好處是上下文敏感。當你將一個靜態調用放入一個類中時,你會自動將其上下文整個AppDomain,要求每個實例的工作方式完全相同。假設您有一個實體的列表頁面和導出。您可能會延遲加載列表頁面,但會導致出口負載過重(因爲您知道您將處理所有內容)。這種上下文行爲(以及批處理大小等)基本上被靜態調用所排除。 – 2010-01-13 00:24:19