问题标签 [aggregateroot]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
1 回答
246 浏览

repository - 领域驱动设计和聚合参考

我正在设计域模型,但有些东西似乎不太好。

我从一个主要的聚合开始。它引用了其他聚合,而那些其他聚合也引用了更多聚合。我可以从主聚合开始遍历洞域模型。

我看到的问题是我将在内存中保存所有聚合实例。

这是一个好的设计吗?我可以通过延迟加载来解决内存问题,但我认为我有更深层次的问题。

我有另一个关于聚合引用的问题。我应该懒惰地加载对其他聚合的引用吗?如果是这种情况,我几乎不会使用他们的存储库。那样可以么?

0 投票
1 回答
305 浏览

domain-driven-design - 聚合根中实体的操作

如果我设计了如下所示的 AR,您认为我应该如何更新订单行对象之一中的属性?

例如,我如何更改我的订单行之一的标题(示例问题)

这是订单聚合根

0 投票
1 回答
2055 浏览

domain-driven-design - DDD:存储库可以返回聚合内的实体吗?

我有一个City聚合,有一个PointOfInterest实体列表。后一个实体在逻辑上位于 City 聚合中,原因在此不作解释。除了聚合根 City 之外,没有任何实体拥有指向 PointOfInterest 的链接。

但是,我们有一个 PointOfInterest 网页,可从 City 页面浏览,该网页(主要出于 SEO 原因)id在其 URL 中仅包含 PointOfInterest。

因此,从控制器中,直接向 CityRepository 查询 PointOfInterest 会很方便,例如CityRepository.findPointOfInterestById().

另一种选择是查询CityRepository.findCityByPointOfInterestId(), then City.findPointOfInterestById(),在这种情况下看起来有点麻烦。

第一种方法有什么问题吗?

0 投票
4 回答
1707 浏览

domain-driven-design - 何时更新审计字段?DDD

我有一个会议对象:

Meeting{id, name, time, CreatedBy, UpdatedBy}

和一个

MeetingAssignee{id, MeetingID, EmployeeId, CreatedBy, UpdatedBy)

会议,作为聚合根,有一个方法 AssignEmployee。

我正要在调用 AssignEmployee 时将当前用户传递给 Meeting 对象,以便它可以相应地更新其审计字段。

但这似乎不对——是吗?显然,我可以公开审计字段并在以后更改它们 - 也许在服务级别?

每个人更新这些字段的其他首选方法是什么?

请注意:我们使用的不是 Nhibernate,而是一个自定义的 ORM,它没有任何自动功能。

谢谢。

0 投票
1 回答
1239 浏览

domain-driven-design - DDD:“文章”中的“评论”应该是聚合根吗?

我开始设计第一个简单的 DDD 风格的应用程序,并且开始了解这些概念是如何协同工作的。

如果我设计一个经典的博客应用程序,文章类将是我的聚合根之一。我想检索文章、管理和删除所有相关数据(出版日期、作者...)。我对评论有困难。起初,评论似乎是文章聚合的一部分:评论是针对一篇文章创建的,如果我删除一篇文章,我将删除相关评论。

然后我想在博客上显示一个小框,其中包含博客上发布的最新评论,用于任何文章。所以看起来我想从我的数据存储中检索评论(并且只有评论)。根据我对 DDD 思想的理解,这使它成为一个聚合根。但这似乎并不完全正确,因为 Comment 似乎强烈依赖于 Article。

你会如何建模?

谢谢。

0 投票
1 回答
128 浏览

language-agnostic - 需要共享实体的聚合

考虑一下我的模型,它由两个聚合根CustomerOrder一个“共享”实体组成Address

另请注意,Addressabstract具有以下子类PhysicalAddressPostOfficeBoxAddressPrivateBagAddress

ACustomer可以将许多地址组织成某种地址簿。下订单后,客户Address将从他们的地址簿中选择一个用作送货地址。

我最初的想法是在两个实体之间共享一个地址,但后来我选择了退出,因为这会给管理各自的不变量带来麻烦。

我可以选择的另一个选择是创建两个层次结构Address,每个层次结构都用作客户地址或送货地址。这似乎也不对,因为有很多重复的代码。

我将如何正确地模拟这种情况?

0 投票
4 回答
2194 浏览

domain-driven-design - 查找值是否应该建模为聚合根?

作为我的域模型的一部分,假设我有一个WorkItem对象。该WorkItem对象与查找值有多种关系,例如:

WorkItemType

  • 用户故事
  • 漏洞
  • 增强

Priority

  • 高的
  • 中等的
  • 低的

可能还有更多,例如Status,Severity等...

DDD 指出,如果聚合根中存在某些内容,则不应尝试在聚合根之外访问它。因此,如果我希望能够添加新的 WorkItemType(如 Task)或新的 Priorities(如 Critical),这些查找值是否需要与它们自己的存储库聚合根?这似乎有点矫枉过正,特别是如果它们只是一个键值对。我应该如何允许用户修改这些值并仍然遵守聚合根封装规则?

0 投票
1 回答
505 浏览

php - 在 DDD 聚合中实现排序/过滤业务逻辑

我对 DDD 相当陌生,对我来说,我实际上是在寻找一个好的聚合函数。我有一长串用户 ( User) 并为此创建了一个聚合 ( UserAggregate)。

现在在我看来,我可能会根据不同的标准显示用户。假设在这里我没有对我的数据库查询中的列表进行排序,可以在聚合中进行排序吗?我无法想出可以正确执行此操作的应用程序的另一部分,但我可能会误解聚合的功能。

顺便说一下,过滤也是如此。当我阅读有关 DDD 聚合的信息时,我立即想到了Doctrine\Common\Collections\Collection链接)。对我来说,那种东西看起来像是一个聚合体。所以DDD专家,请赐教:-)

更新

顺便说一句,我想的唯一方法是使聚合相当不相互,并让助手创建新的聚合。但这似乎不是要走的路:

第二个聚合是一个新实例,所以助手看起来像这样:

0 投票
2 回答
1708 浏览

domain-driven-design - DDD:对非聚合根的引用的解决方案

我有两个聚合根和两个非聚合根实体:

实体关系

我知道,这种关系D -> B违反了 DDD 原则。

我听说,在大多数情况下,解决方案是使引用的实体成为新的聚合根。

但是,如果B 是A的真正孩子(B 不能没有 A),那么让 B 成为一个新的聚合根真的是一种选择吗?

0 投票
3 回答
1252 浏览

domain-driven-design - 如何处理跨聚合根的并发约束

恐怕我已经知道答案了,但我希望有人可以提供以前没有找到的替代解决方案。与往常一样,根据有效聚合设计进行 DDD比我想象的要困难,但这是我的场景。

  • 我们有两个 AR,User 和 RoleGroup
  • 一个用户可以被授予一个特定的角色组,从而获得该角色组中角色(一个集合值对象)提供的权限。角色组的身份作为另一个 VA 保存在用户 AR 中。
  • 当从系统中删除 RoleGroup 时,我们会引发一个域事件,处理程序使用该事件来查找引用该 RoleGroup 的所有用户并删除该引用。相应的投影反规范化器将使用相同的事件来更新用户的有效角色。这是授予该用户的各个角色和所有授予 RoleGroup 的角色的组合。
  • 这不一定是事务性的(因为它最终可以是一致的)。
  • 我们通过 Jonathan Oliver 的 EventStore 3.0 以及 Lokad.CQRS 和 NCQRS 中的元素来使用 Event Sourcing。

因此,理论上,当一个请求(它是一个 ASP.NET MVC 应用程序)正在执行上述场景时,另一个请求可能会将相同的 RoleGroup 授予用户。如果在上述域事件处理程序扫描与该角色组相关的用户之后发生这种情况,则该请求将完成。此时,您有一个已删除的角色组(尽管不是物理删除)和一个仍持有该角色组身份的用户。

你如何防止这种情况发生?我们目前正在考虑将用户的身份授予该 RoleGroup AR 的特定 RoleGroup 一部分,以便删除 RoleGroup 并将其授予用户将导致乐观并发冲突。但不知何故,这感觉不是正确的解决方案。