我在航空预订申请中使用CQRS。一个用例是帮助客户取消他们的门票。但在取消之前,客户想知道罚款。
罚款根据空中规则计算。我们的一些提供商可以通过公开Web服务来计算惩罚,而其他人则不会。 (他们发表了一些解释算法的论文)。所以我定义了一个域服务
public interface AirTicketService {
//ticket demand method
MonetaryAmount penalty(String ticketNumber);
void cancel(String ticketNumber, MonetaryAmount penalty);
}
我的问题是哪一方(命令/查询)负责调用此域服务并在CQRS样式的应用程序中返回结果?
我想使用Command:CalculatePenlatyCommand,这样,很容易重用域模型,但这有点奇怪,因为这个命令不会修改状态。
或者,如果这是一个查询,我应该检索票证的readmodel吗?但是在命令和查询方面都需要相同的DomainService,这也很奇怪。
域推导是查询吗?
答案 0 :(得分:1)
没有必要将所有东西都塞进命令查询管道中。您可以独立于UI查询此服务,而无需发出命令或询问读取模型。
答案 1 :(得分:1)
如果使用现有模型满足查询,如果它“适合”该模型的术语和结构,则没有任何问题。无需为此目的构建单独的读取模型。这并非没有风险,因为查询的语义和上下文应该与仅用于写入目的的模型紧密相关。我提到的风险是写入和读取问题可能分开(我们回到正方形,即人们首先选择CQRS的原因)。因此,随着新要求的出现,你必须继续关注。
非常适合这个模型的查询就是我所谓的“模拟器”,您希望使用当前状态运行模拟,例如向最终用户提供反馈。不止一次,我发现模拟逻辑可以作为反馈机制和执行(写操作/命令)转向机制重用。不同之处在于我们对模拟结果的处理方式。同样,这不是没有风险,需要仔细判断。
答案 2 :(得分:1)
你可以提出计算惩罚命令的论据根本不是奇怪的。 用户要求系统执行某些操作 - 命令。
您甚至可以在您的域中进行 Penalty Calculation Requested Event 事件,并且感觉正确。因为,在某些时候,您可能会感兴趣,比如说,不确定的客户,那些想要取消门票但是每次都改变主意等等的客户。计算也可以异步执行 - 你可以在以后以各种方式向用户提供结果(惩罚成本)...
或者,以某种其他方式:在预订票证事件上,也存储取消罚款。然后,您可以随时访问该值,而无需重新计算...但这可能是错误的(?),因为惩罚在很大程度上取决于时间,权利(您取消机票的时间越晚,支付的越多) ?
如果所有这些都想要过度并发症等,那么我想我也同意rmac's answer :)