我们以一个简单的“账户注册”为例,流程如下:
- 用户访问网站
- 点击“注册”按钮并填写表格,点击“保存”按钮
- MVC 控制器:通过读取 ReadModel 来验证用户名的唯一性
- RegisterCommand:再次验证用户名的唯一性(这里是问题)
当然,我们可以通过读取 MVC 控制器中的 ReadModel 来验证 UserName 的唯一性,以提高性能和用户体验。但是,我们仍然需要在 RegisterCommand 中再次验证唯一性,显然,我们不应该在 Commands 中访问 ReadModel。
如果我们不使用事件溯源,我们可以查询领域模型,所以这没有问题。但是如果我们使用事件溯源,我们无法查询域模型,那么我们如何在 RegisterCommand 中验证 UserName 的唯一性呢?
注意: User 类有一个 Id 属性,UserName 不是 User 类的关键属性。使用事件溯源时,我们只能通过 Id 获取域对象。
BTW:在需求中,如果输入的用户名已经被占用,网站应该向访问者显示错误消息“对不起,用户名XXX不可用”。不能向访问者显示“我们正在创建您的帐户,请稍候,我们稍后会通过电子邮件将注册结果发送给您”这样的消息是不可接受的。
有任何想法吗?非常感谢!
[更新]
一个更复杂的例子:
要求:
下单时,系统会检查客户的订单历史,如果他是有价值的客户(如果客户在去年每月至少下过10个订单,他是有价值的),我们对该订单进行10%的折扣。
执行:
我们创建 PlaceOrderCommand,在命令中,我们需要查询下订单历史,看看客户端是否有价值。但是我们怎么能做到呢?我们不应该在命令中访问 ReadModel!正如 Mikael所说,我们可以在帐户注册示例中使用补偿命令,但如果我们在此排序示例中也使用它,它会太复杂,代码可能太难以维护。