Architecture CQR和计算

Architecture CQR和计算,architecture,cqrs,Architecture,Cqrs,我目前正在研究一些遵循CQRS模式的概念验证代码,我无法找到一个令人满意的解决方案来解决我(认为我)遇到的问题 系统根据特定场景计算市场变化对给定投资组合的影响 投资组合可以包含一到数百个持有量,市场场景由用户根据特定请求预先定义或动态定义 在最简单的形式中,这个问题的解决方案是一个服务,它返回给定输入的一些值,但是在CQRS的情况下,我认为执行计算的部分(域)不应该被实际返回数据的部分(查询)调用 考虑到这样一个系统很容易有几个投资组合,而且场景的数量也可能相当高,我认为存储计算结果是没有意义

我目前正在研究一些遵循CQRS模式的概念验证代码,我无法找到一个令人满意的解决方案来解决我(认为我)遇到的问题

系统根据特定场景计算市场变化对给定投资组合的影响

投资组合可以包含一到数百个持有量,市场场景由用户根据特定请求预先定义或动态定义

在最简单的形式中,这个问题的解决方案是一个服务,它返回给定输入的一些值,但是在CQRS的情况下,我认为执行计算的部分(域)不应该被实际返回数据的部分(查询)调用

考虑到这样一个系统很容易有几个投资组合,而且场景的数量也可能相当高,我认为存储计算结果是没有意义的


任何人都有这个问题的解决方案,或者可以为我指出一篇解决类似问题的文章的方向?

对我来说,CQR的全部要点是创建两个域模型。一个优化用于使用命令更新数据,另一个优化用于使用查询读取数据。查询不应明显改变系统。将计算结果存储在排序缓存中是查询域模型的一个实现细节。只要缓存在时间上是无效的,也就是说,查询端最终与命令端是一致的,就可以了。当然,您应该控制应用程序中可接受的“最终”数量

当您计算市场变化对投资组合的影响时,您正在对查询域模型执行查询。我认为为您感兴趣的场景创建查询类型没有问题


总之,我认为你没有问题。请记住,您可以(应该?!)隐藏查询处理程序和/或查询域模型中计算的复杂性。

CQRS并没有说您应该在写端预先计算所有内容。当系统状态通过命令更改时,将创建事件,投影将侦听这些事件并创建可用于查询的模型。这个模型的外观和用途取决于你。如果愿意,您甚至可以创建系统的完整第三范式数据库表示的投影


如果在读取端进行这些计算对您来说更实际,那么我认为这样做没有问题,只要丢失计算结果是可以的

如果您使用CQR是因为您需要巨大的可伸缩性,而可伸缩性围绕着读取这些计算的结果,那么您将希望将这些预先计算的结果存储在您的读取模型中

如果规模/性能不是主要问题,那么我认为动态计算没有问题


无论哪种方式,听起来计算器/计算本身都是读取模型的一部分,而不是域模型。听起来,命令/写入端将包含一组输入,这些输入将通过计算器/计算投射到输出上。

只有在写入模型中需要这些计算的结果来保持不变量时,才需要IMHO计算。不多也不少

让我们以(非常简化的)银行领域为例: 如果你的不变量表示你不能提取超过你账户余额的钱,那么你应该计算余额(即该账户的取款和存款的总和),并可能存储它(如果你有某种合计),以便能够检查取款金额是否超过实际余额,但是如果您的系统没有这样的不变量,那么计算是不必要的,并且平衡很可能只应该在系统客户端的读取端进行计算

我还想到,您可能会问,是否可以使用read-side进行这些计算(如果计算量很大的话)——这要看情况而定。 大多数人会说,不应该在写端使用读端,但就连Greg Young也曾说过,有时候它是可以接受的。
请记住,在写端使用读端可能会使您的模型不一致,因为读端数据可能已过时。

+1。是的,read模型可以是一个完整的第三范式数据库,一个OLAP多维数据集,一个数据仓库,一个Excel文件——任何东西,它都可以预先计算,按需投影,或者介于两者之间的任何地方。因此,您的建议与@BorisEegerink一致,基本上我会有两个域模型。一个适合写作,另一个适合检索数据?如果组合的数量可以管理,那么预先计算结果看起来是个好主意?@mhttk-是的,我认为这是个好主意。我同意Boris Eetgerinks的回答。我喜欢你对这件事的看法。我想当你看到这样的情况时,应用程序中写模型和读模型之间的角色就清楚了。谢谢你的回答。这似乎表明在读端可以有业务逻辑,即作为读端域模型的一部分。我更喜欢这种方法,而不是认为阅读端只是关于阅读状态的不同表示/视图(例如,非规范化)的建议。这带来了另一个问题。读取端是否可以发布事件(基于它根据接收到的事件确定的属性)?其他(子)系统可能希望了解这些属性的更改,而不必查询(轮询)读取端。如上所述,读取端是否可以发布事件(基于从接收到的事件计算出的属性)?例如,如果在读取端计算余额(因为写入端不需要不变量),则读取端可以发布具有新余额的事件。其他(子)系统可能希望了解这些属性的更改,而不必查询(轮询)读取端。你会怎么做