我读过这篇文章,在这篇文章中,Udi Dahan 谈到了多对多的关系。在该示例中,他解释说,在多对多关系的情况下,例如工作与工作板之间的关系,并考虑到将工作添加到工作板的有限上下文,聚合根将是工作板和您只需将工作添加到它。在评论部分,他还解释说,在不同的有界上下文中,作业将是聚合根,这是有道理的,因为作业可以在没有作业板的情况下存在,并且您可以对不影响作业的作业执行许多操作木板。我有一个类似的问题,但我似乎无法弄清楚这将如何解决。我有两个问题:
- 如果我们需要删除工作,看起来取决于工作是否已发布,我们需要单独删除工作或删除工作但也将其从板中删除,这意味着修改同一事务中的两个聚合根,但这段代码应该去哪里?域服务?
- 如果工作和工作板可以是两个不同的聚合,工作实体需要存在于两个上下文中,那么我们如何处理这个问题,只需创建两个具有重复数据的工作类?
更新 1:
所以这就是我正在处理的场景......我有一个路由应用程序,我有代表旅行请求的请求,我有路线,有停靠点,每个停靠点都有一个或多个请求。为了创建路由,我使用执行路由的外部服务,并将路由结果存储在路由表中。
问题是我不怎么建模这种关系,这里有一个用例来考虑,请求取消是一个过程,根据请求的状态和路由的状态可以导致不同的动作:
- 请求未路由(未分配给路由),只需取消请求即可。
- 请求被路由,路由被调度,然后取消请求,从路由中删除请求,并重新创建路由(使用外部库),因为删除请求可能会导致删除停止,所以我需要重新创建路线内部,它仍然是一个更新。
- 请求被路由,路由在途中,然后我将请求标记为未显示,并更新路由。
所以起初我虽然请求、路由和路由表是单独的聚合,但这意味着我需要在同一个事务中修改多个聚合(通过使用服务或使用域事件)我不确定如果创建更高级别的聚合根(带有请求、路由数据和最终路由数据)是有意义的,因为我不会总是拥有所有数据来加载聚合根,事实上大多数时候我会有它的一部分,要么是 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 个请求数据,所以我必须将 routeData 留空,这听起来不对
- 在这个我有路由和请求数据所以我很好
- 在这个我有路由和请求数据所以我很好
这里的主要问题是,一些操作可以在 1 个请求上完成,而其他一些操作将在路由上完成,而其他一些操作将在两者中完成。所以我不能总是通过 ID 获得聚合,或者我不能总是用相同的 ID 获得它。