首页 > 解决方案 > 集成事件处理逻辑(编排与域逻辑)

问题描述

我有一个应用程序通过集成事件在本地跟踪外部文档的状态。某些外部文档类型不共享,而有些则共享。在处理外部事件时,例如DocumentTypeChanged我必须执行类似于以下的逻辑:

internalTypeId = internalDocumentTypeFrom(event.newTypeId);
shared = isSharedType(event.newTypeId);
if (internalTypeId == UNKNOWN && shared) trowMissingSharedDocTypeMappingError();

if (documentTracked(event.documentId)) {
  changeDocumentType(event.documentId, internalTypeId, event.id);

  if (!shared) removeDocument(event.documentId, event.id);
} else if (shared) {
  applicationId = mostRecentApplicationIdOfBn(event.businessNumber)
  attachDocument(applicationId, event.documentId, event.id, ...);
}

外部文档总是应该只响应外部事件而改变,ExternalDocumentAR 总是保留externalEventId该文档的最新版本。

我应该把上面的逻辑放在哪里?现在逻辑都在集成的事件处理程序中,并将诸如应用程序层之类的命令委托changeDocumentType给应用程序层,但我觉得大多数 BL 都在爬出域。

在查看 IDDD 示例时,大多数集成处理程序(例如这个)正在将事件转换为应用程序的服务层命令。这有点像我目前所拥有的,但我觉得这些命令只能在对外部事件的反应中发生这一事实很难传达。

我的另一个想法是做类似的事情externalDocumentAppService.handleDocumentTypeChange(externalDocumentId, externalTypeId, externalEventId, bn, occurredOn),然后应用程序的服务方法可能如下所示:

class ExternalDocAppService {
    handleDocumentTypeChange(externalDocumentId, externalTypeId, externalEventId, bn, occurredOn) {
        internalTypeId = internalDocumentTypeFrom(externalTypeId);
        shared = isSharedType(event.newTypeId);

        document = documentRepository.findByExternalId(externalDocumentId);

        if (document) {
            document.handleTypeChange(internalTypeId, shared, externalEventId, occurredOn);
        } else if (shared) {
            application = caseRepository.mostRecentApplicationOfBn(bn);
            document = application.attachDocument(externalDocumentId, ...);
        }

        if (document) documentRepository.save(document);
    }
}

class ExternalDocument {
    …
    handleTypeChange(internalTypeId, shared, externalEventId, occurredOn) {
        if (internalTypeId == UNKNOWN && shared) trowMissingSharedDocTypeMappingError();

        this.typeId = internalTypeId;
        this.latestExternalEventId = externalEventId;
        this.latestExternalChangeDate = occurredOn;

        if (!shared) this.remove(...);
    }
}

查看代码,在应用程序层中仍然会有一些业务逻辑,例如知道忽略新的未共享文档。我们能否证明在域服务中提取应用程序的服务逻辑是合理的,应用程序服务将简单地委托给域服务(或多或少)?

我也不确定反应式命令名称,例如handleTypeChange. 会changeTypeBecauseOfExternalTypeChange更合适吗?无论如何,我在这里寻找一些设计指导......谢谢!

标签: oopdomain-driven-designintegrationbounded-contexts

解决方案


我的建议是引入有限状态机,以便“检索信息”和“消费信息”之间的界限清晰

class ExternalDocAppService {
  handleDocumentTypeChange(externalDocumentId, externalTypeId, externalEventId, bn, occurredOn) {

    // These might belong inside the finite state machine?
    internalTypeId = internalDocumentTypeFrom(externalTypeId);
    shared = isSharedType(event.newTypeId);

    fsm = new FSM(internalTypeId, shared, externalEventId, occurredOn);
    fsm.onDocument(
      documentRepository.findByExternalId(externalDocumentId)
    )

    if (fsm.needsApplication()) {
      fsm.onApplication(
        caseRepository.mostRecentApplicationOfBn(bn)    
      )
    }

    document = fsm.document();
    if (document) documentRepository.save(document);
  }
}

也就是说,处理这个事件的过程有自己的小状态机来帮助跟踪需要获取哪些信息以及需要存储哪些信息。

请注意,此状态机实际上是一个短暂的东西 - 它正在管理一些簿记以处理此特定事件。一旦我们完成了它,它的状态就可以被丢弃(这与我们的领域模型中的状态机进行对比,它管理着我们的领域动态,我们将状态复制到我们的持久性存储中,以便我们以后可以恢复)。


推荐阅读