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