问题标签 [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 投票
3 回答
6844 浏览

domain-driven-design - 只读数据库视图如何适应存储库模式?

示例:您的数据库有一个名为“CustomerOrdersOnHold”的 SQL 视图。此视图返回特定客户和订单数据字段的过滤组合。您需要在应用程序中从此视图中获取数据。对这种视图的访问如何适应存储库模式?你会创建一个“CustomerOrdersOnHoldRepository”吗?像这样的只读视图是否被视为聚合根?

0 投票
2 回答
1135 浏览

domain-driven-design - DDD:在聚合根中保留指向实体的链接,仅用于报告

我正在使用 DDD 重构一个项目,但我担心不要让太多实体成为自己的聚合根。

我有一个Store,它有一个ProductOptions 列表和一个Products 列表。AProductOption可以被几个Products 使用。这些实体似乎Store非常适合总体。

然后我有一个Order,它暂时使用 aProduct来构建它OrderLine的 s:

目前看来,DDD 规则受到尊重。但我想添加一个要求,这可能会违反聚合规则:商店所有者有时需要检查包含特定产品的订单的统计信息。

这意味着基本上,我们需要在 OrderLine 中保留对 Product 的引用,但这绝不会被实体内的任何方法使用。在查询数据库时,我们只会将此信息用于报告目的;因此,由于此内部引用,不可能“破坏” Store 聚合中的任何内容:

这个简单的要求是否要求 Product 成为聚合根?这也将级联到 ProductOption 成为聚合根,因为 Product 对它有引用,因此导致两个聚合在 Store 之外没有任何意义,并且不需要任何存储库;我觉得很奇怪。

欢迎任何评论!

0 投票
2 回答
1321 浏览

asp.net-mvc-3 - 获取所有聚合根实体子实体?

我正在尝试将我的应用程序从每个实体的存储库重构为每个聚合根的存储库。

一个基本的例子是我有一个 Cars 的实体根。汽车有租赁合同。据我所知,没有汽车就没有合同,因此汽车是总根。

我正在尝试实现一个用户视图,它将显示系统中的每个合同(根实体的所有子实体)。在重构之前,我可以去我的合约存储库并获取所有。由于合同存储库已被删除(因为它不是根),我现在需要将所有汽车从我的存储库中取出,然后获取他们的所有合同。

我的存储库有接口

我想创建一个 ICarManagementService 并让它有一个 GetAllContracts 方法(可能带有过滤器参数)。这是否意味着获得我需要的所有合同,将所有汽车实体与他们的合同一起取出,然后检索与租赁合同相关的每个实体并过滤它们?

然后我可以将这些传递给控制器​​并像以前一样自动映射合同。

这是最佳实践吗?

谢谢

格雷姆

0 投票
2 回答
190 浏览

nhibernate - 如何使用 NHibernate 从聚合根的子集合中最好地选择单个实体?

我想知道在以下情况下什么被认为是更好或更正确的做法:

我已经用 NHibernate 映射了以下业务实体:

  • 海报
  • 墙邮评论

一堵墙有零对多的墙贴。WallPost 具有零对多的 WallPostComments。聚合根是 Wall。

我正在编写一个将 WallPostComment 添加到 WallPost 的任务。该应用程序是一个MVC应用程序,添加新WallPostComment的请求包含评论所属的WallPost的id。为了添加评论,我需要检索应该添加的帖子。我的问题是:最好/最正确的方法是什么?

到目前为止,我已经尝试了两种方法,一种感觉更“正确”,尽管它效率低下。另一种更有效的方法感觉是“错误的”。

1) 我从会话中加载 Wall 聚合根,并从其 Posts 集合中选择 FirstOrDefault。这感觉“正确”,因为我正在通过聚合根访问墙帖,但是这样做会导致从数据库中获取所有墙帖(无界结果集)。

2) 我使用请求传递给我的 wallPostId 直接从会话加载墙帖。这感觉“错误”,因为我要绕过聚合根 - 但它是对单行数据的数据库的一次点击。

哪个是更好或首选的方法?你还有什么建议?

0 投票
2 回答
666 浏览

security - DDD 和授权依赖对象作为聚合根?

我想知道是否应该将依赖对象建模为聚合根。假设我有一个TaskList,这个列表有Tasks。ATask不能没有 a 存在,TaskList但可以单独查看和编辑。没有特殊条件TaskList可以检查何时修改或添加任务 - 我认为这将是聚合根的主要原因。唯一的条件是,TaskList它及其任务只能由所有者编辑。TaskList如果有所有者并且只能通过任务列表编辑任务,则很容易确保此条件。否则,我将需要检测所有者或向任务添加所有者字段。

那么这里有什么合适的呢?

  • Task 和 TaskList 都作为聚合根并且每个都有一个所有者字段
  • 只有 TaskList 作为聚合根,Tasks 作为依赖实体

我错过了什么重要的东西吗?

0 投票
2 回答
231 浏览

validation - 网络:如何使用聚合根对其进行建模?

域模型定义实体之间的关系,我们定义聚合根以提供封装和事务边界。众所周知的关系是一对一关系(实体或值对象包含在聚合根中)、一对多关系(聚合根包含子对象的集合)和多对多关系。后者很困难,因为聚合根之间的多对多关系会使您在事务边界方面遇到麻烦。因此,在许多情况下,多对多关系的一个方向被视为更重要,并且只有该关系被建模为一对多关系。
现在,更进一步。网络。等效合作伙伴之间的多对多关系。如何在不违反聚合根的事务边界的情况下对其进行建模?
看看这个广泛适用的例子:
我有一个带节点的网络。每个节点都有有限数量的端口。一个端口只能连接到另一个节点上的一个端口。我必须能够使用端口添加和删除节点之间的连接。
一种直观的方法是将节点建模为包含端口的聚合根。连接似乎是价值对象,一个端口可以有一个连接。我可以实现一个 Node.ConnectTo(nodeId, portId) 方法,该方法将连接(节点 A 上的端口 X 和节点 B 上的端口 Y 之间)添加到聚合根节点 A。最好我会调用此方法两次,一次节点 A 和节点 B 上一次并将其包装在事务中。但是,这会违反事务边界,因此我决定仅将其存储在节点 A 上。
要在应用程序客户端上查看节点 B 上的连接,需要一个单独的读取模型。但这没问题,CQRS 架构为我们提供了这些可能性。因此,添加、删除和查看连接不是问题。
当我想在将连接添加到端口之前验证端口是否仍然空闲时,就会出现问题。尊重我们的事务边界的结果是(在写入模型中)聚合根可能不知道端口已经连接的事实,但可能存储在任何其他聚合根中。
当然,您可以信任客户端的验证,继续添加连接,如果您要添加它的节点没问题,并依靠运行一致性检查的进程来执行无效连接的补偿操作。但与围绕两个 ConnectTo 调用包装事务相比,这对我来说似乎很重要......
这让我认为也许我的聚合根被错误地选择了. 我开始将节点和网络视为聚合根,其中网络是连接的集合。网络聚合的好处是您始终可以验证添加或删除连接。除非一个新的连接会导致两个现有网络的加入......并且您的聚合可能会变得很大,可能只会导致一个巨大的网络。也不可行。
那么,您认为这应该如何建模呢?您是否看到将聚合根视为事务边界的解决方案,您可以验证您的网络,并且您不会冒险将整个网络存储为单个聚合?还是我在这里要求所有 3 个 CAP,这根本不可能?

0 投票
1 回答
238 浏览

scala - 处理应用程序级并发 - 我有什么选择?

我们有一个瘦 Web 层 ( Scalatra ),它将传入的 HTTP 请求转换为事件(案例类),然后发送到线程绑定的事件处理参与者。一些事件包含聚合根的 id,由于各种原因我们需要对其进行变异。应用程序数据的总量太大而无法放入内存,因此我们需要在对其进行操作之前通过其 id 从数据源中检索聚合。当然我们不希望事件处理参与者阻塞,所以想法是产生一个新的(基于事件的?) 加载数据、对其进行变异并将其存储回数据源的参与者。理想情况下,我想在应用程序中处理并发,而不是依赖数据源的 ACID 功能。基本上我需要对每个聚合进行序列化/事务访问。

这可以使用演员来实现吗?最好的方法是什么?ConcurrentHashMap在事件处理参与者内部保留一个包含以聚合根 ID 为键的参与者?

还是我们必须涉及 STM:s (ScalaSTM/Akka) 或类似的东西?

0 投票
1 回答
618 浏览

domain-driven-design - DDD - 应该如何处理查找实体?

我们正在使用 DDD 开发一个项目,但在如何处理查找实体方面遇到了困难。例如,我们有一个名为“Customer”的聚合,实体“Customer”也是聚合根。实体“客户”具有属性“客户类型 ID”。

但我们也有一个实体“CustomerType”代表所有现有的客户类型(ID 和描述)。将有一个管理功能允许用户维护客户类型(即添加新的客户类型等)。

请注意,我不是在谈论更改特定客户的客户类型,而是在维护客户类型列表。

对于冗长的故事,我深表歉意,但这是我的问题:

  • 我认为“CustomerType”是一个实体而不是一个值对象是对的吗?

  • “CustomerType”应该在聚合“客户”内还是应该在它自己的聚合内,因为我们将在特定客户的上下文之外访问它并维护它?

  • 如果这个实体和任何其他作为基本查找实体的实体(如客户状态、产品类型等)应该是它们自己的聚合(并且是这些聚合的聚合根),我不会最终得到数百个存储库? (因为每个聚合根都有自己的存储库)

正如你所看到的,我在这里陷入了混乱,只需要指出正确的方向。

=================================== 我试图写一些代码来回复eulerfx的回复,但我做不到不能让它工作,所以我会把它放在这里。

关于第 2 点,我们显然只会在屏幕上显示类型的描述(例如“个人”)。这是否意味着我最终会得到这样的结果?:

公共类 CustomerType 继承 EntityBase(Of Integer) 实现 IAggregateRoot

或者“客户”类中的属性应该是 CustomerTypeID?

关于第 3 点,聚合和有界上下文有什么区别?难道“客户”聚合(“客户”是聚合根)还包含仅存在于客户上下文中的任何实体和值对象,而不是有界上下文?

0 投票
2 回答
217 浏览

architecture - 领域驱动设计 - 聚合根设计问题

我目前正在重构一个系统。

我有以下情况:

该系统旨在提供有关跨多个业务部门的公司的信息。每家公司都可以活跃在一个或多个领域。公司可以参与某些合作伙伴计划。一家公司可以有一个或多个合作伙伴制造商(例如,车库可以与 BMW/Mercedes 建立合作伙伴关系)等。所有这些参与都存在一个给定的时间段(有效期)。此外,像宝马这样的制造商必然会涉足一个业务领域。因此,如果 BMW 对公司业务部门有效,则公司只能成为 BMW 的合作伙伴。也就是说,因为该系统不仅维护像车库这样的商业部门的公司,而且还维护拖车服务等。

所以现在我的设计可能会导致一些不变量。

公司 -> 分配(不会慢慢改变) -> 业务部门

公司 -> 合伙企业(日期从 - 到) -> 组织 <- 业务部门

公司和组织必须共享相同的业务部门分配。

所以现在,可以改变一个组织的业务部门分配。那么这将是同一业务部门的规则无效。

你会如何建模这样的东西?

0 投票
1 回答
611 浏览

c# - 应用层和契约

首选通信是什么:IAggregationRoot标记存储在合同中Domain LayerData Access Layer在合同中引用它,IRepository反之亦然?

编辑

我查看了Tim Maccharty'shttp://www.wrox.com/WileyCDA/WroxTitle/productCd-0470147563,descCd-authorInfo.html)实现repository patternunit of work模式。拥有自己/伪造的IUnitOfWorkRepository. 我对在哪里存储此类合同感到更加困惑。

谢谢!