DDD:领域事件应该如何访问网络请求数据?

DDD: How should domain events access web request data?

假设我们的 Analytics 模型订阅了 CommentPosted 事件,并希望针对发布所述评论的请求的跟踪器 cookie 记录发布的评论 ID。不幸的是,我们的 CommentPosted 事件对 HTTP 请求一无所知,因为它只引用了已发布的评论。

为了解决这个问题,在我们的侦听器中,我们可以使用 DI 获取当前请求并使用它从那里检索所需的 cookie。但是,这将我们的域与 Web 层紧密耦合。

另一种方法是要求 Controller 将所需的 cookie 传递给 CommentingService,后者将使用 cookie 调用 AnalyticsService。但现在评论系统必须调解分析。

有没有更好的方法来插入它,而无需评论对分析一无所知并且域对 Web 层一无所知?

在我看来,分析的某些部分需要属于您的域。分析在领域方面为您做了什么?

多个服务可以订阅一个事件。 analyticsService 可以订阅 CommentPostedEvent。这样您就可以避免 CommentService 依赖于分析服务。然后分析服务可以找出它还需要什么(比如获取原始请求)。

你甚至可以做的是定义一个更通用的 HttpTrackingEvent 并在 post 对你想要的 cookie 完成时也引发它。 (不仅针对评论,还针对任何具有正确跟踪 ID 的 httppost)然后 AnalyticsService 可以订阅该事件并(希望)发现您正在创建新评论。

如果你想让你的主域不知道分析子域,反之亦然,你可以在控制器级别有一个 interceptor/request 处理器来捕获 http 信息以及包含信息的通用命令数据结构关于用户正在执行的操作。然后拦截器可以直接调用 Analytics 应用程序服务或发布包含这些详细信息的事件以用于分析目的。

如果您不仅要跟踪应用程序中所有命令共享的特征,还要跟踪更具体的 domain-level 细节,事情就会变得有点复杂。特别是那些只有在域操作完成后才知道的(例如新发布的 CommentId)。

  • 您的 Comment 应用程序服务可以在命令完成后 return NewCommentId 到 Controller,并且它可以中继到拦截器,但这并不真正符合CQRS 命令的概念。

  • 另一种选择是在分析跟踪会话和用户在该会话期间执行的域操作之间建立一些关联 ID。该枢轴可以是命令。 Analytics 拦截器保留 CommandId 以及它想要的所有 http-derived 信息,并且当域聚合发布 CommentPosted 事件时,它可以在事件中包含原始 CommandId。如果 AnalyticsService 订阅此事件,它将能够将其关联回命令所属的会话 (trackerId)。