2014-10-29 19 views
5

假設我有兩個實體User和Item。這兩個實體之間的域中唯一的行爲是用戶可以喜歡一個項目。由於對用戶可以喜歡多少項目沒有限制,因此這種多對多關係可能很大。域驅動設計:如何建模很大但行爲很少的關係

我不認爲讓用戶在其模型或其他方式中包含他們喜歡的項目列表是不明智的,因爲我將不得不加載可能大量的項目集合以便只添加一個項目。從域設計的角度來看,對於我來說,任何一個實體都可以在其領域中引用另一個實體,因爲沒有任何行爲需要存在一組項目或用戶。

我需要保持這種關係,因爲UI需要顯示用戶喜歡的項目列表以及喜歡項目的用戶列表。這個需求可以通過一個讀取模型來實現,但我仍然需要一個領域概念來捕獲這種關係,以便它能夠被持久化。

我可以想出的一種方法是引入一個聚合關係類型,比如說UserLikeItem,並讓方法user.like(item)返回一個UserLikeItem實例,然後我可以使用UserLikeItemRepository來持久化該實例。

這是一個有效的解決方案嗎? DDD的這種自然方式可以模擬這種類型的大而非行爲關係嗎?

+0

我喜歡(雙關語!)您的解決方案,即使它不需要是'用戶'國際海事組織的方法。它還允許您捕獲其他信息,例如項目被喜歡的時間,在什麼情況下等。相同的AR可以用於不同的,但也許你需要找到一個更好的名字。 – guillaume31 2014-10-29 11:32:17

+0

我同意,我可能會添加的唯一一件事就是爲項目添加一個「LikeCounter」,這樣您就可以顯示一個項目的總數,而不必擊中UseLikeItem數據源。 – 2014-10-29 12:13:59

+0

交易對象或域名事件「UserLikedItem」似乎適用於您提供給我們的信息。 – 2014-11-01 14:23:24

回答

0

我會深入挖掘這個:),IMO如果沒有行爲,它不會生活在「域模型」中,如果絕大多數概念沒有行爲,那麼你不需要一個「域模型「,您應該可以查看transaction script類型的模式,而不是域模型。

我會將你的問題解釋爲「我如何堅持多方面的關係,以高性能的方式」 對這個問題我們有多個答案,一個是你提到的其他可能只是存儲ID列表中的類。

域模型和持久性後端的面向對象表示是兩個單獨的事情,域模型是行爲第一,所以您考慮行爲,然後將屬性添加到將受該行爲影響的域模型中,否則你需要的是一個「持久性後端的面向對象的表示」(DTO)

但是,當你有一個領域模型的情況下,它會變得棘手,但只是一些概念貧乏,缺乏行爲,但那就是問題的另一天:)

+1

我不同意'如果沒有行爲,它不住在「域模型」中。任何具有域含義/定義域概念的東西都是域的一部分,無論它具有行爲還是數據結構。 – MikeSW 2014-11-01 16:11:39

0

'喜歡'是領域的事實,它可以由實體表示。
項目有喜歡 - >項目包含喜歡的集合。
此集合僅用於添加和刪除喜歡 - >項目具有LikeCount屬性,並且對於存儲庫查詢(僅在Item.AddLikeFrom(用戶)和Item.RemoveLikeFrom(用戶)方法中使用),可選擇收集喜歡。

它可能看起來,這種關係是非行爲的,但實際上它是關係方之一的行爲。

2

前段時間我碰到這種情況,這是我的看法。 用戶商品是他們不知道/彼此關心的不同聚合的一部分(即使商品具有userId)。 「Like System」(LS)是一種不同的聚合跟蹤,喜歡從什麼

LS並不真正關心用戶或項目,但因爲我看不到其他用戶可以喜歡的東西的情況,所以我可以說Like會永遠暗示一個userId(不是整個用戶的概念)和一個主題(Item,VIdeo,Picture,Post等)。

LS只是保持用戶Id和某個類型的另一個itemId(可以是一個字符串,如果你希望LS不能耦合到某個Item的)的關聯。每次發佈某個命令的用戶時:RegisterLikeForItem {UserId,ItemId,ItemType}。 LS處理程序將存儲該信息,然後發佈事件UserLikedItem。它的一個處理程序將是一個計數器,它將計算有多少用戶喜歡該項目。另一個處理程序可以列出一個用戶喜歡哪些項目(這將由UI查詢)。

每個處理程序服務於一個用例,可能每個處理程序都有自己的存儲空間。我知道它看起來相當複雜,但實際上很簡單(一個用例需要一個處理程序,也許是一個存儲)以及所有的投注,它非常靈活和可維護。該系統適用於一種或1000種物品類型。