我认为在这种情况下,您需要将两种验证类型分开;域验证和应用程序验证。
验证命令属性“文本”在20到200个字符之间时,您将进行应用程序验证。因此,您可以使用GUI以及在POST之后也在服务器上执行的view-model-validator对此进行验证。电子邮件也是如此(顺便说一句,我希望您认识到,根据RFC,像32.d +“ Hello World .42” @mindomän.local“这样的电子邮件是有效的)。
然后,您还有另一个验证;检查文章是否存在-如果确实存在从GUI发送的关于为其添加注释的命令,则必须问自己一个问题,为什么不应该存在该文章。您的GUI最终是否一致,并且您具有可以从数据存储中物理删除的汇总根(即文章)?在这种情况下,您只需将命令移至错误队列,因为命令处理程序无法加载聚合根。
在上述情况下,您将拥有处理有毒消息的基础结构-例如,它们将重试该消息1-5次,然后将其移动到Poision队列中,您可以在其中手动检查消息的集合并重新分发相关消息。监视是一件好事。
所以现在我们讨论了:
应用验证
- 在GUI中使用javascript
- 通过Web服务器上的MVC验证
缺少聚合根+毒物队列
与域不同步的命令呢?也许您在域逻辑中有一条规则说,对一篇文章发表5条评论后,只允许使用400个字符以下的评论,但是一个人对第5条评论为时已晚,而成为第6条-GUI没有抓住它,因为这与他发送命令时的域不一致-在这种情况下,您的域逻辑中有一个“验证失败”,您将返回相应的失败事件。
该事件可以是到消息代理或您的自定义调度程序上的消息形式。如果应用程序是单块的,则Web服务器可以同步侦听所提到的成功事件和失败事件,并显示适当的视图/部分视图。
通常,您具有自定义事件,这意味着许多类型的命令都会失败,并且从Web服务器的角度来看,正是您预订了此事件。
在我们正在使用的系统中,我们通过MassTransit + RabbitMQ消息总线+经纪人对命令/事件进行请求-响应,并且在此特定域中有一个名为的事件(部分模拟了工作流程)InvalidStateTransitionError
。大多数尝试沿着状态图中的边缘移动的命令可能会导致此事件发生。在我们的案例中,我们根据最终一致的范例对GUI进行建模,因此我们将用户发送到“命令接受”页面,然后让Web服务器的视图通过事件订阅进行被动更新。应该提到的是,我们也在汇总根中进行事件源(也将对Sagas进行)。
因此,您看到,您正在谈论的许多验证实际上是应用程序类型的验证,而不是实际的域逻辑。如果您的域很简单,但您正在执行DDD,则使用简单的域模型没有问题。但是,当您继续对域进行建模时,您会发现该域可能不像最初那样简单。在许多情况下,聚集的根/实体可能只接受由命令引起的方法调用并更改其某些状态,甚至不执行任何验证-尤其是如果您像在网络服务器中验证命令那样信任命令,由您控制。
我可以推荐观看2011年挪威开发者大会上有关DDD的两个演讲以及Greg在Öredev2010上的演讲。
干杯,亨克