【问题标题】:Domain Driven Design: How to model relations that are large but have few behaviors领域驱动设计:如何对大但行为很少的关系进行建模
【发布时间】:2014-10-29 00:49:34
【问题描述】:

假设我有两个实体用户和项目。这两个实体之间的域中唯一的行为是用户可以喜欢一个项目。由于对用户可以喜欢多少项目没有限制,因此这种多对多关系可能很大。

我认为让 User 在其模型中包含他们喜欢的项目列表或其他方式在性能方面没有意义,因为我必须加载可能很大的项目集合才能添加只有一项。从领域设计的角度来看,让任何一个实体在其字段中引用另一个实体对我来说也没有意义,因为没有任何行为需要存在项目或用户的集合。

我确实需要保持这种关系,因为 UI 需要显示用户喜欢的项目列表和喜欢项目的用户列表。该需求可以通过读取模型来满足,但我仍然需要一个域概念来捕获这种关系,以便它可以被持久化。

我能想到的一种方法是引入聚合的关系类型,比如 UserLikeItem,并让方法 user.like(item) 返回一个 UserLikeItem 实例,然后我可以使用 UserLikeItemRepository 来持久化。

这是一个有效的解决方案吗?在 DDD 中建模这种大型但非行为关系的自然方式是什么?

【问题讨论】:

  • 我喜欢(双关语!)您的解决方案,即使它不需要是 User IMO 上的方法。它还允许您捕获其他信息,例如项目被点赞的时间、在什么情况下等。相同的 AR 也可以用于不同,但也许您需要为它找到一个更好的名称。
  • 我同意,我唯一可能要添加的就是项目的 LikeCounter,这样您就可以显示项目的总点赞数,而无需点击 UseLikeItem 数据源.
  • 一个事务对象或一个域事件“UserLikedItem”似乎适合你给我们的小东西。

标签: domain-driven-design domain-model


【解决方案1】:

自从我前段时间遇到这种情况以来,这是我的看法。 UserItem 是它们彼此不了解/不关心的不同聚合的一部分(即使项目具有 userId)。 “点赞系统” (LS) 是从 whowhat 的不同聚合跟踪点赞。

LS 也并不真正关心用户或项目,尽管由于我看不到用户以外的其他人可以喜欢某物的情况,我可以说 Like 将始终暗示一个 userId(而不是整个用户概念)和主题(项目、视频、图片、帖子等)。

LS 只是保持用户 ID 和特定类型的另一个 itemId 的关联(如果您希望 LS 不与 Item 是什么耦合,则可以是字符串)。每次用户喜欢某个命令时,都会发出一个命令:RegisterLikeForItem { UserId, ItemId, ItemType} 。 LS 处理程序将存储该信息,然后发布事件 UserLikedItem。它的一个处理程序将是一个计数器,它将计算有多少用户喜欢该项目。另一个处理程序可以列出一个用户喜欢的项目(这将由 UI 查询)。

每个处理程序都服务于一个用例,并且可能每个处理程序都有自己的存储。我知道它看起来很复杂,但实际上很简单(一个用例需要一个处理程序,也许还需要一个存储)而且最重要的是,它非常灵活且可维护。该系统适用于一种或 1000 种物品类型。

【讨论】:

    【解决方案2】:

    我将对此进行挖掘:),IMO 如果没有行为,它就不会存在于“域模型”中,并且如果您的绝大多数概念没有行为,那么您就不需要“域”模型”,您可能应该查看transaction script 类型的模式而不是域模型。

    我会将您的问题解释为“我如何以高效的方式维持多对多关系” 对于这个问题,我们有多个答案,一个是您提到的其他可能只是将 id 列表存储在类中。

    域模型和持久化后端的面向对象表示是两个独立的东西,域模型首先是行为,所以你要考虑行为,然后将属性添加到将受该行为影响的域模型中,否则 您需要的是“持久性后端的面向对象表示”(DTO)

    但是当你有一个领域模型的案例时,它会变得很棘手,但是只有几个概念是乏味的并且缺乏行为,但这是另一天的问题:)

    【讨论】:

    • 我不同意'如果没有行为,它就不会存在于“域模型”中'。任何具有域含义/定义域概念的事物都是域的一部分,无论它具有行为还是数据结构。
    【解决方案3】:

    'Like'是领域事实,可以用Entity来表示。
    项目有喜欢 -> 项目包含喜欢的集合。
    此集合仅用于添加和删除喜欢 -> 项目具有 LikeCount 属性,并且喜欢的集合对于存储库查询是可选的(仅用于 Item.AddLikeFrom(user) 和 Item.RemoveLikeFrom(user) 方法)。

    看起来,这种关系是非行为的,但实际上它是关系一方的行为。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-05-17
      • 1970-01-01
      • 2010-10-15
      • 2015-09-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-28
      相关资源
      最近更新 更多