【发布时间】:2021-07-02 06:46:08
【问题描述】:
我读过这个post,在这篇文章中,Udi Dahan 谈到了多对多的关系。 在该示例中,他解释说,在多对多关系的情况下,例如工作与工作板之间的关系,并且考虑到将工作添加到工作板的有界上下文,聚合根将是工作板和您只需将工作添加到它。 在评论部分他还解释说,在不同的有界上下文中,作业将是聚合根,这是有道理的,因为作业可以在没有作业板的情况下存在,并且您可以对不影响作业的作业执行许多操作木板。 我有一个类似的问题,但我似乎无法弄清楚这将如何解决。我有两个问题:
- 如果我们需要删除工作,看起来取决于工作是否已发布,我们需要单独删除工作或删除工作但同时将其从董事会中删除,这将意思是在同一个事务中修改两个聚合根,还有这段代码应该去哪里?域服务?
- 如果工作和工作板可以是两个不同的聚合,工作实体需要存在于两个上下文中,那么我们如何处理这个问题,只需创建两个具有重复数据的工作类?
更新 1:
这就是我正在处理的场景...我有一个路线应用程序,我有代表旅行请求的请求,我有路线,其中有停靠点,每个停靠点都有一个或多个请求。为了创建路由,我使用了一个执行路由的外部服务,并将路由结果存储在路由表中。
问题是我不怎么建模这种关系,这里有一个用例来考虑,请求取消是一个过程,根据请求的状态和路由的状态可以导致不同的动作:
- 请求未路由(未分配给路由),只需取消请求即可。
- 请求被路由,路由被调度,然后取消请求,从路由中删除请求,并重新创建路由(使用外部库),因为删除请求可能会导致删除停止,所以我需要要重新创建路由内部,它仍然是一个更新。
- 请求已路由,路由在途中,然后我将请求标记为未显示,并更新路由。
所以起初我虽然请求、路由和路由表是单独的聚合,但这意味着我需要在同一个事务中修改多个聚合(通过使用服务或使用域事件) 我不确定创建更高级别的聚合根(带有请求和路由数据,最终路由数据)是否有意义,因为我不会总是拥有所有数据来加载聚合根,事实上大多数有时我会得到它的一部分,要么是 1 个请求,要么是具有多个请求的路由。 我愿意接受建议,因为我似乎无法解决这个问题。
更新 2: 因此,添加更多上下文,我将向实体添加更多细节:
- 请求,它代表一个旅行请求,它有几个状态和定义的工作流程
- 路由,它有一个定义的工作流和定义的转换,有一个停靠点的集合,每个停靠点都有一个有效负载的集合,每个有效负载都有一个请求 ID,(Route -> stops[] -> payloads[]-> requestId)
- 路由,它代表调用路由引擎的结果,它根据您要路由的一系列请求将生成路由/路由
所以这个实体存储在一个 mongodb 集合中,让我们看看用例:
UC - 请求取消 我只能使用请求 ID 取消请求,但根据请求的状态,我可能还需要修改路由。 1 请求未路由,因此使用请求 id,我获取请求并取消它,这很简单。 2 请求被路由,并且路由被调度,在这种情况下,我需要获取请求,然后获取路由以及与该路由绑定的所有请求(它包括触发命令的请求),然后删除有效负载(以及与请求相关联的站点(如果它只有一个有效负载),因为此选项可以更改站点,我需要使用外部 api(路由引擎)重新创建路由并在路由表中创建一个条目。 3 Request is Routed, Route is en-route,在这种情况下,我需要获取请求,然后获取路由以及与该路由相关的所有请求(它包括触发命令的请求),并更改请求未显示,但也将有效负载标记为未显示
UC - 开始路线 一旦创建并安排了路线,我就可以启动它,这意味着修改路线的状态、停止的状态、有效负载的状态以及关联请求的状态。
正如您在用例中看到的那样,路由 - 请求和路由表非常密切相关,所以起初虽然有单独的聚合根,请求是一个 AR,路由是一个 AR,路由是一个 AR,但是这意味着在同一事务中修改多个 AR。 现在让我们看看拥有所有实体的 AR 会是什么样子
class Aggregate {
constructor(routeData, requests[]) {
}
}
让我们再看看 UC UC - 请求取消
- 在这种情况下,我只有 1 个请求数据,所以我必须将 routeData 留空,这听起来不对
- 在这个我有路由和请求数据,所以我很好
- 在这个我有路由和请求数据,所以我很好
这里的主要问题是,有些操作可以在 1 个请求上完成,有些操作会在路由上完成,有些操作会在这两个请求上完成。所以我不能总是通过 Id 得到聚合,或者我不能总是用相同的 id 得到它。
【问题讨论】:
-
“请求”、“路线”和“停止”之间似乎有很强的关系。是什么让您认为您需要多个聚合根? “请求”、“路线”和“停止”成为同一个聚合的一部分是否有意义?
-
实际上会,但我已经读到您需要始终通过 Id 获取聚合,在这种情况下,我认为我不能,在某些情况下它将通过 requestId,在其他一些情况下情况下它会是 routeId,所以,这个大聚合总会有一部分数据,有时只是一个请求,有时是多个请求和路由数据,有时只是路由数据,所以我的意思是你可以根据您正在加载的数据,不执行所有操作,仅执行其中一些操作
-
“您需要始终按 Id 获取聚合”您是对的。在对您的用例知之甚少的情况下,很难提供帮助。请提供一些。
-
感谢您的回复,我已经添加了更多上下文信息并尝试解释2个用例。
-
在我看来,您这里只有一个聚合,即“请求”,如果处于路由状态,它可以具有可选路由。向请求聚合发送命令以更新路由。
标签: domain-driven-design aggregateroot aggregates dddd