我正在开发一个带有域事件的 CQRS 框架,我遇到了一种代码气味,我想得到一些建议。
我没有使用事件溯源 (ES(。ES 事件与域事件不同。域事件对域感兴趣,并可能导致发出新命令。ES 事件对持久性存储很重要。ES 事件也可能是域事件,但并非所有 ES 事件都是域事件。
我问题的根源在于以下声明:
域事件...可能会导致新命令...
具体来说,当其中一个命令失败时会发生什么。
在我读过的 CQRS 文章中,他们说应用程序层负责在命令发送到命令总线之前对其进行验证。 我不同意这一点有两个原因。1(我不信任客户端(安全欺骗(。2( 随着应用程序的成熟和新事件/处理程序/命令的添加,命令 A 的验证可能不知道它也需要验证命令 Foo。
因此,应用层需要知道命令是否成功。如果失败了,应用层需要一些信息来解释原因。但是随着命令触发事件,发出触发事件的新命令......我最终得到的响应类如下所示:
public interface ICommandResponse
{
ICommand OriginatingCommand { get; set; }
bool Successful { get; set; }
IEnumerable<Exception> Exceptions { get; set; }
IEnumerable<ICommandResponse> DerivativeCommands { get; set; }
IEnumerable<IEventResponse> EventResponses { get; set; }
}
public interface IEventResponse
{
IEvent OriginatingEvent { get; set; }
bool Successful { get; set; }
IEnumerable<Exception> Exceptions { get; set; }
IEnumerable<IEventHandlerResponse> EventHandlerResponses { get; set; }
}
public interface IEventHandlerResponse
{
string Descriptor { get; set; } // TODO: A way to identify the event handler.
bool Successful { get; set; }
IEnumerable<Exception> Exceptions { get; set; }
IEnumerable<ICommandResponse> DerivativeCommands { get; set; }
}
我想要的只是能够判断命令是成功还是失败,如果失败,为什么。我最终得到了这个递归树结构。我是否过于复杂了?
当其中一个命令失败时会发生什么
因此,在域事件的通常上下文中,答案是整个事务失败。
我想要的只是能够判断命令是成功还是失败,如果失败,为什么。
该信息如何返回调用方取决于您的代码风格 - 您可以引发异常,或返回某种Either
数据类型,或通知回调处理程序,或...
如果调用方在另一个进程中,您将需要将内部选项转换为某种消息。 带有可选原因字段的成功/失败状态将为您提供足够的经验,以确定要包含在下一个版本的架构中的内容。