2011-07-19 48 views
3

我們正在將現有系統轉換爲DDD,並且正在努力將我們的頭部圍繞幾個概念進行包裝。管理實體的歷史記錄對象

我們有一個名爲Animal的聚合根,它具有諸如StatusSource之類的屬性。目前該數據庫有兩個表,分別叫做StatusHistorySourceHistory,它存儲關於動物狀態改變時的信息。這些表有時會刪除記錄,並且在從AnimalRepository獲取Animal時很少需要檢索。

所以最大的問題是它們屬於哪裏?以下是我們的一些想法:

  • 將它們作爲不同的實體對象作爲動物聚合的一部分。並且有相應的方法允許它們被更新,例如:Animal.UpdateStatus(newStatus),這會通過new StatusHistory(this)對象添加到集合中。但是正如上面提到的那樣,在爲存儲庫獲取現有動物時,這些很少需要,因此我們不希望存儲庫加載它們。我們目前不使用ORM,而是使用存儲庫內的表數據網關手動映射。

  • 使每個歷史實體成爲一個聚合根。我們並不是這樣的粉絲,因爲它感覺我們並沒有真正爲域名建模,而是朝着Active Record Pattern漂流。更新這些動物的任務必須位於動物實體之外。

  • 我們可以嘗試將這些歷史合併到另一個稱爲AnimalHistory的聚合根中,其全部目的是維護動物的歷史。但是,再一次將移動的邏輯關於將歷史存儲在動物身上。可能像AnimalProcessingService這樣的服務,這感覺我們可能會走向貧血設計。

我希望有另一種選擇,它會爲我們提供更清潔的設計。

回答

2

這是Martin Fowler最近撰寫的一篇有趣的文章,它可能解決您關於不需要檢索某些內容的一些問題,稱爲命令查詢責任分離。基本概念是,您可以對「查詢」(讀取)使用不同的「模型」,而不是「命令」(保存)。

http://martinfowler.com/bliki/CQRS.html

僅僅因爲你正在做的DDD並不意味着一切都需要包含在正確的域對象。設計您的域名與設計服務和活動等同樣重要。我的觀點是讓您的域名更加自然地關注「域名」所需的內容以及解決方案如何實現這些要求。 DDD沒有嚴格的方法,與正式的設計模式相比,它更像是一種選擇。所以把你的歷史對象作爲實體根並不一定是壞的,如果它們只用於保存。讓您的與「命令」相關的服務構成保存動物和歷史的正確邏輯流程。

我還想指出,像Animal.UpdateStatus(newStatus)這樣的東西是相當活躍的記錄,你似乎想避免。

0

如果您正在使用EJB3,那麼你可以寫你的聽衆不同的自定義實現,像@PostInsert@PostUpdate等事件。

在這些監聽器中提供您的實現。例如假設Animal中有更新,那麼你的PostUpdate監聽器將被調用,並且它將更新歷史記錄。

這種方法有一大優勢,因爲一切都發生在一個事務中,並且一旦編寫了通用代碼,您將永遠不必擔心更新歷史記錄表。

第二種方法將使用REFLECTION + INTERCEPTORS