2011-08-10 38 views
2

正在通過規範對象是矯枉過正在庫正在通過規範對象是矯枉過正在庫

我問這是因爲,如果我們像FindCustomersCreatedToday法通過規範對象,

class CustomerRepository 
{ 
    public List<Customer> FindCustomersCreatedToday(ISpecification ISCreatedToday) 
    { 
     List<Customer> customers= Load all customers from db; 

     List<Customer> newList=new List<>(); 

     foreach(var customer in customers) 
     { 
       if(ISCreatedToday.SatisfiedBy(customer) 
       { 
        newList.Add(customer); 
       } 
     } 
    } 

} 
以上

我在我看到的大多數網站中實現,他們從數據庫中獲取所有實體並循環遍歷它們,並將它們中的每一個傳遞給規範,但我不喜歡一次加載所有實體然後創建一個新的過濾列表的想法。

假設我有10000個客戶,並且只有10個通過了這個標準。

是不是殺過規格?

回答

2

是的,如果你期望很多客戶,這絕對是一種矯枉過正。您可以使用規範實例中的信息生成適當的SQL/HQL或ICreteria(假設您使用NHibernate)。

public IList<Customer> FindCustomers(CreationDateRangeSpecification spec) { 
    ICriteria c = _nhibernateSession.CreateCriteria(typeof(Customer)); 
    c.Add(Restrictions.Between("_creationDate", spec.Start, spec.End)); 
    return c.List<Customer>(); 
} 

這段代碼比您發佈的代碼稍遜一些,但它仍然擅長捕獲規範中的某些域信息。

使用規範時需要注意的一件事是它是一個領域概念。它屬於域層,應該沒有數據訪問技術。獲取數據的技術非常重要,它們在領域層不重要,它們屬於數據訪問層。在我看來,像Expression<Func<Customer, bool>>這樣的東西是針對域代碼的「基礎結構」。此外,基於Linq的規範傾向於要求域對象將其數據公開爲有時會破壞其封裝的屬性。因此,整個事情可能變成「Linq超過Anemic Model」。我們強烈建議您閱讀DDD book。它有一章專用於規範模式以及您正在處理的所有權衡。

+0

我認爲在規範中,對象只有一個屬性。 IsSatisfiedBy返回布爾值。但就你而言,事實並非如此。此外,如果您將ISpecification作爲參數傳遞,那麼它是如何知道它具有Start和End屬性的,因爲ISpecification是一個接口,或者您必須公開它,而我認爲這不是一個好主意。 – kamal

+0

檢查此http://linqspecs.codeplex.com/ – kamal

+0

@kamal:IsSatisfiedBy不是必需的。如果您只使用規範傳遞到存儲庫,那麼擁有它是很好的,但可能並不需要。我用代碼和一些解釋更新了答案。 – Dmitry

2

正如Ayende指出他的N-layer app review,LINQ是規範技術如果您需要使用規格模式。它具有可轉換爲SQL或HQL或任何其他查詢語言的優點,因此可以在數據源上執行表示爲Expression<Func<T, bool>>的規範,而無需下載所有數據。

+0

非常感謝。我從你的鏈接中獲得了這個鏈接。 http://linqspecs.codeplex.com/。但是,格雷格年輕人指出,我們不應該直接在方法中傳遞規範,因爲它可能會破壞一些域規則http://codebetter.com/gregyoung/2009/01/16/ddd-the-generic-repository/。我需要你對此發表評論。 – kamal

+0

你能幫我在這個http://codebetter.com/gregyoung/2009/01/16/ddd-the-generic-repository/,他告訴我們,我們不應該有通用的存儲庫,但我們應該在存儲庫中有FindUserByName而不是FindUsers(Ispecification規範)。存儲庫中沒有函數爆炸。 – kamal

+0

有兩種'finder'方法。通常,當試圖在沒有任何CQRS符號的情況下實現DDD時,這兩種類型的查找器方法都會在資源庫對象中結束。第一個用於處理交易。它通常是GetSomethingById(id)。它可能是GetSomethingByName(name)或任何東西。關鍵是,這種方法被業務邏輯所使用。我同意格雷格的意見,你應該努力在這裏儘可能的明確,而不是使用規範。 –

相關問題