使用CQRS在DDD中进行命令验证

chr*_*ris 14 validation domain-driven-design cqrs

我正在学习DDD并使用CQRS模式.我不明白如何在不读取数据存储的情况下在命令处理程序中验证业务规则.

例如,克里斯想要给阿什利一份礼物.

该命令可能是GiveGiftCommand.

在什么时候我会证实克里斯实际拥有他想要的礼物?如果不从数据库中读取,我该怎么做?

Tom*_*uλa 13

关于命令处理程序中的验证有不同的观点和意见.

命令可以被拒绝,如果命令无效,我们可以对命令说" ".

通常,您将在UI上进行验证,并且可能在命令处理程序中重复(有些人也倾向于将其放在域中).然后,命令处理程序可以运行可以在实体外部发生的简单验证,例如正确格式的数据,是否存在预期值等.

另一方面,业务逻辑不应该在命令处理程序中.它应该在您的域中.

所以我认为潜在的问题是......

我应该从命令处理程序查询读取端吗?

我会说不.不要在命令处理程序或域逻辑中使用读取模型.但是,您始终可以从客户端查询读取模型,以获取命令所需的数据并验证命令.您将在客户端查询读取方以检查Chris是否实际拥有他想要提供的礼物.当然,涉及读取模型的验证可能最终是一致的,这当然是在命令处理程序内可以从聚合中拒绝命令的另一个原因.

有些人不同意说,如果您需要命令来包含处理程序验证命令所需的数据,那么您永远不会更改处理程序/域中的验证逻辑而不会影响客户端.这会向客户端暴露过多的领域知识,并违背客户只想表达意图的事实.因此,他们倾向于为GiftService您的命令处理程序提供一个接口(它是无处不在的语言的一部分),然后根据需要实现接口 - 这可能包括查询读取端.

我认为客户端应该始终认为它发出的命令会成功.不应该需要调用读取端来验证命令.获得两个相互矛盾的命令的可能性很小(用户使用相同的电子邮件地址创建帐户).然后,您应该有一个意思是发布纠正措施,例如Saga/Process Manager.因此,如果命令本来可以被验证而不是首先发送,那么采取纠正措施就不那么成问题了.

  • 阅读模型只是对事实的一种投射,可以在真实的事实背后.因此,在询问阅读模型时,您必须牢记这一点. (4认同)
  • 你在说什么样的服务?我假设域名服务.就我而言,我将命令处理程序视为应用程序服务,因此没有业务逻辑.只是编排用例. (3认同)
  • 域模型是面向命令的.如果在几个聚合之间传播,它的结构不允许总是有效地查询它自己的数据.它会以人工方式耦合聚合根,这样效率不高. (2认同)
  • 另外,在cqrs谷歌小组的进一步讨论中,我学到了一些东西.命令处理程序应调用聚合根上的方法以应用该命令.Aggregate Root将在初始化时加载事件流,最终结果将是聚合的当前状态.然后,您可以使用该当前状态执行一些业务规则. (2认同)