我有一个应用程序,它通过集成事件在本地跟踪外部文档的状态。某些外部文档类型不共享,而某些则共享。处理诸如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, ...);
}
外部文档总是应该仅对外部事件做出反应而更改,ExternalDocument
AR始终保留该文档的最新externalEventId
。
我应该在哪里放置以上逻辑?现在,逻辑完全在集成的事件处理程序中,并将诸如changeDocumentType
之类的命令委托给应用程序的层,但是我感到大多数BL都爬出了域。
查看IDDD示例时,大多数集成处理程序(例如this one)都将事件转换为应用程序的服务层命令。这是我目前所拥有的,但是我觉得这些命令只能在对外部事件做出反应时发生。
我的另一个想法是做类似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
这样的词更合适吗?无论如何,我正在这里寻找一些设计指导……谢谢!
答案 0 :(得分:1)
我的建议是引入一个有限状态机,以使“检索信息”和“消费信息”之间的界限清晰可见
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);
}
}
这就是说,处理此事件的过程具有自己的小状态机,以帮助跟踪需要获取哪些信息和需要存储哪些信息。
请注意,此状态机确实是短暂的东西-它正在管理一些簿记以处理此特定事件。一旦完成,它的状态就可以被丢弃(这与我们的域模型中的状态机进行对比,状态机管理着我们的域动态,我们将状态复制到持久性存储中以便以后恢复)。