0

我读过这篇文章,在这篇文章中,Udi Dahan 谈到了多对多的关系。在该示例中,他解释说,在多对多关系的情况下,例如工作与工作板之间的关系,并考虑到将工作添加到工作板的有限上下文,聚合根将是工作板和您只需将工作添加到它。在评论部分,他还解释说,在不同的有界上下文中,作业将是聚合根,这是有道理的,因为作业可以在没有作业板的情况下存在,并且您可以对不影响作业的作业执行许多操作木板。我有一个类似的问题,但我似乎无法弄清楚这将如何解决。我有两个问题:

  1. 如果我们需要删除工作,看起来取决于工作是否已发布,我们需要单独删除工作或删除工作但也将其从板中删除,这意味着修改同一事务中的两个聚合根,但这段代码应该去哪里?域服务?
  2. 如果工作和工作板可以是两个不同的聚合,工作实体需要存在于两个上下文中,那么我们如何处理这个问题,只需创建两个具有重复数据的工作类?

更新 1:

所以这就是我正在处理的场景......我有一个路由应用程序,我有代表旅行请求的请求,我有路线,有停靠点,每个停靠点都有一个或多个请求。为了创建路由,我使用执行路由的外部服务,并将路由结果存储在路由表中。

问题是我不怎么建模这种关系,这里有一个用例来考虑,请求取消是一个过程,根据请求的状态和路由的状态可以导致不同的动作:

  1. 请求未路由(未分配给路由),只需取消请求即可。
  2. 请求被路由,路由被调度,然后取消请求,从路由中删除请求,并重新创建路由(使用外部库),因为删除请求可能会导致删除停止,所以我需要重新创建路线内部,它仍然是一个更新。
  3. 请求被路由,路由在途中,然后我将请求标记为未显示,并更新路由。

所以起初我虽然请求、路由和路由表是单独的聚合,但这意味着我需要在同一个事务中修改多个聚合(通过使用服务或使用域事件)我不确定如果创建更高级别的聚合根(带有请求、路由数据和最终路由数据)是有意义的,因为我不会总是拥有所有数据来加载聚合根,事实上大多数时候我会有它的一部分,要么是 1 个请求,要么是具有多个请求的路由。我愿意接受建议,因为我似乎无法解决这个问题。

更新 2:因此添加更多上下文,我将向实体添加更多细节:

  • 请求,它代表一个旅行请求,它有几个具有定义工作流的状态
  • 路由,它有一个定义了转换的定义工作流,有一个停靠点的集合,每个停靠点都有一个有效负载的集合,每个有效负载都有一个请求 id,(Route -> stops[] -> payloads[]-> requestId)
  • 路由,它代表调用路由引擎的结果,它基于您要路由的一系列请求将生成路由/路由

所以这个实体存储在一个 mongodb 集合中,让我们看看用例:

UC - 请求取消我可以仅使用请求 ID 取消请求,但根据请求的状态,我可能还需要修改路由。1 请求未路由,因此使用请求 id,我获取请求并取消它,这很简单。2 请求被路由,并且路由被调度,在这种情况下,我需要获取请求,然后获取路由以及与该路由绑定的所有请求(它包括触发命令的请求),然后删除有效负载(以及与请求相关联的站点(如果它只有一个有效负载),因为此选项可以更改站点,我需要使用外部 api(路由引擎)重新创建路由并在路由表中创建一个条目。3 Request is Routed,Route是en-route,这种情况下我需要获取request,

UC - 启动路由一旦创建并安排好路由,我就可以启动它,这意味着修改路由状态、停止状态、有效负载状态以及相关请求的状态。

正如您在用例中看到的那样,路由 - 请求和路由表是非常密切相关的,所以起初虽然有单独的聚合根,请求是一个 AR,路由是一个 AR,路由是一个 AR,但这意味着修改同一笔交易中有多个 AR。现在让我们看看拥有所有实体的 AR 会是什么样子

class Aggregate {
  constructor(routeData, requests[]) {
  }
}

所以让我们再看看 UC UC - Request Cancellation

  1. 在这种情况下,我只有 1 个请求数据,所以我必须将 routeData 留空,这听起来不对
  2. 在这个我有路由和请求数据所以我很好
  3. 在这个我有路由和请求数据所以我很好

这里的主要问题是,一些操作可以在 1 个请求上完成,而其他一些操作将在路由上完成,而其他一些操作将在两者中完成。所以我不能总是通过 ID 获得聚合,或者我不能总是用相同的 ID 获得它。

4

1 回答 1

2
  1. 不存在“同一事务中的两个聚合根”这样的事情。事务的范围在单个聚合内,因为理论上所有聚合都应该存在于它们自己的微服务中。以原子方式更新两个或多个聚合的正确方法是使用 saga。Sagas 是一个复杂/高级的话题。如果可以的话,我建议您通过重新思考您的设计来避免它们。

  2. 在两个有界上下文之间拆分一个实体非常好,并且大多数时候是必要的,但是这些实体应该适应它们的上下文,例如在董事会有界上下文中,“工作”实体可能是一个“董事会卡片”,它不会有相同的属性比来自工作有界上下文的“工作”实体。

于 2021-04-06T17:50:41.230 回答