2013-01-04 17 views
0

目前潛入DDD,我讀過埃裏克埃文斯的大部分藍皮書。到目前爲止非常有趣:)DDD - 無效期滿

我一直在建模一些聚合物,他們持有過期實體的集合。我拿出那個表達的一般方法:

public class Expirable<T> 
{ 
    public T Value { get; protected set; } 
    public DateTime ValidTill { get; protected set; } 

    public Expirable(T value, DateTime validTill) 
    { 
     Value = value; 
     ValidTill = validTill; 
    } 
} 

我很好奇,最好的辦法是無效的可到期(廢止或一組工作時,忽略它)是什麼。到目前爲止,我一直在考慮在Repository構造函數中這樣做,因爲這是您從中訪問聚合並充當「集合」的地方。

我很好奇,如果有人提出瞭解決方案來解決這個問題,我會很高興聽到它:)其他方法也非常歡迎。

UPDATE 2013年10月1日:

這是不與來自Greg Young的所述CQRS/ES方法DDD。但是,從我剛開始閱讀這本書和第一個應用程序開始,Evans就已經採用了這種方法。像格雷格楊說的,如果你必須做好桌子,你必須先做幾個;)

+0

好的模式的確如此,但是你有沒有一個例子說明'T'通常會在「過期不變」場景中出現?你會在哪裏放置強制執行不變的代碼? – guillaume31

+0

查看我的評論下面的例子要點。 –

+0

你的例子只使用'UserSession'作爲'T'。 'UserSession'不是DDD意義上的一個不變量 - 一個由Aggregate Root執行的業務規則。既然你提到了不變式,我只是好奇地想知道你是如何用'Expirable '來實現它們的。 – guillaume31

回答

0

一直在閱讀了關於DDD與CQRS/ES(Greg Young的方法),發現在MSDN網站上有關CQRS/ES一個很好的例子:http://msdn.microsoft.com/en-us/library/jj554200.aspx

在這個例子中,他們使用的命令消息隊列中排隊一個將來會有消息過期,它會在指定的時間調用Aggregate,從聚合中移除/關閉expired構造。

1

有可能有多種方法來解決這個問題,但我個人會使用規範模式解決這個問題。假設對象到期是一個屬於域的業務規則,除了你寫的類外,我還會有一個規範。這裏有一個例子:

public class NotExpiredSpecification 
{ 
    public bool IsSatisfiedBy(Expirable<T> expirableValue) 
    { 
     //Return true if not expired; otherwise, false. 
    } 
} 

然後,當你的存儲庫返回聚集的列表或一組進行任何業務操作時,這可以用來限制設置爲未到期值,這將讓你代碼具有表現力並將業務邏輯保留在域中。

要了解有關規範模式的更多信息,請參閱this paper

+0

有趣的想法,沒有想到的! :)我已閱讀關於規格的章節。這個解決方案的問題是你將不得不在存儲器中加載完整的NotExpired集合,效率不高。在另一邊它打開了一些想法給我嘗試。 –

+0

你能詳細說說嗎?規範方法並不意味着你必須加載所有東西,事實上,你只應該加載你需要的東西。規範僅僅是這樣你可以過濾出你正在使用的集合中的過期值。如果有些值不需要加載到內存中,那麼您的存儲庫將負責過濾,並且在加載存儲庫時會發生這種情況。 –

+0

的確如此!我後來想到我正在處理InvalidateExpirable方法時(參見上文)。我可以將該方法中的「查詢」部分重構爲規範。使域更加優雅和富有表現力。我以後可能會這樣做,但現在就足夠了。查詢並不是真正的問題,問題在於何時何地去除不變量(性能明智,這可能是我猜測的一個問題)。每次啓動存儲庫或存儲庫中返回數據的每個方法時? (會更容易出錯) –

0

我在我的抽象存儲庫InvalidateExpirable中添加了一個方法。一個例子是UserRepository,我在這樣的活動用戶會話中刪除:InvalidateExpirable(x => x.Sessions, (user, expiredSession) => user.RemoveSession(expiredSession));

InvalidateExpirable的簽名如下所示:protected void InvalidateExpirable<TExpirableValue>(Expression<Func<T, IEnumerable<Expirable<TExpirableValue>>>> selector, Action<T, Expirable<TExpirableValue>> remover)。該方法本身使用反射來從選擇器參數中提取選定的屬性。該屬性名稱粘在一個通用的HQL查詢中,該查詢將遍歷調用remove lambda的集合。 user.RemoveSession將從聚合中刪除會話。這樣我就保持聚合負責它自己的數據。同樣在RemoveSession未來案件中引發了一個域名事件。

參見:https://gist.github.com/4484261爲例

工作得很好SOFAR,我要看看它是如何工作的進一步下跌的應用雖然。