【问题标题】:Event validation事件验证
【发布时间】:2017-06-22 08:52:48
【问题描述】:

我们正在考虑在工作中实施 CQRS 模式,并且有几个关于验证的问题。

假设我们有 3 个聚合根:

  • User
  • Business
  • UserToBusinessRelationship

当用户注册时,发送的事件将是:

UserCreated
BusinessCreated
UserAddedToBusiness

需要验证事件,例如创建用户和企业之间的链接,用户和企业都应该创建。

我看到了两种方法。

  1. 前期验证:使用最后处理的快照和未处理的事件即时构建读取模型并将其用于验证。

  2. 处理时验证:按原样接受事件/命令并在处理事件时进行验证。

第一种方法有即时反馈,但它需要创建一个最终读取模型,仅用于验证。第二个更简单,但不会向消费者提供出错的反馈。

我在想这样的事情:当你发出一个事件时,你会得到一个 id,你以后可以用它来查询事件的状态。如果事件处理成功,你会得到“OK”,否则你会得到一个错误,告诉你出了什么问题。

这是一种有效的方法还是矫枉过正?消费者如何知道该事件已被处理并且数据已准备好使用?

【问题讨论】:

  • “事件验证”是什么意思?在 CQRS 中,仅验证命令;在它们被接受并生成事件之后,这些事件必须被接受,它们被认为非常有效,它们代表已经发生的事实。
  • 也许您的问题的答案在这里:danielwhittaker.me/2014/11/22/…

标签: domain-driven-design cqrs event-sourcing


【解决方案1】:

很好的问题 Leonti - 您可能会发现我关于 CQRS 系统验证的博文很有帮助。你可以在这里找到:How To Validate Commands in a CQRS Application

从标题中可以看出,CQRS 的重点是验证命令而不是事件。

为什么?

因为命令可以来自用户输入,因此不应该被信任。 另一方面,事件是从域内发出的,并且可以信任。可能存在涉及离开系统边界的事件或接收并非源自系统内部的事件的 CQRS 实现。在那些边缘情况下,应该小心。

另一个潜在的危险信号是您描述聚合的方式。在我看来(而且我不知道您的域,所以不能 100% 确定)它们更类似于数据库中的表而不是聚合。重要的是不要让您的持久性机制决定您的模型。

更具体地回到您的问题。

一般来说,有两种验证类型。肤浅而深刻。表面是缺少字段、有效的电子邮件地址等。深层是域概念在起作用的时候。例如需要货物的重量和表面的验证,但货物是否适合承运人可能是一个领域概念。

您可能需要验证事物的存在。是否存在企业或用户。虽然此验证很可能需要您访问数据库,但它仍然是肤浅的,因为它不太可能是一个明确的域概念。

无论如何,我希望这会有所帮助。

【讨论】:

    【解决方案2】:

    这里主要有两个方面:

    1. 在 CQRS 中,您有命令和查询。事件从何而来?假设您还指的是事件溯源,仍然在使用命令时,您在客户端上进行一些验证,一些在命令处理程序中,一些在您的域模型中(聚合不变量和约束)。这个特殊的例子看起来像是在客户端和命令处理程序内部验证的东西。

    2. 请记住,由于您对三个不同的聚合具有三个不同的操作,因此您需要三个事务。这意味着,如果其中一个无法完成 - 您的系统将进入无效状态。您要么需要重新考虑聚合边界以拥有一个聚合根,要么考虑使用其他技术,例如事件驱动策略、sagas(流程管理器)或路由单(sagas)。

    当然,UserToBusinessRelationship 听起来更像是一个 RDBMS 多对多链接表,而不是聚合表,但我对您的域一无所知。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-10-11
      • 2010-10-26
      • 1970-01-01
      • 2011-11-15
      • 2020-10-26
      • 2011-05-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多