Joe*_*erg 2 domain-driven-design business-logic cqrs
我有两个与 CQRS 和领域驱动设计 (DDD) 相关的问题。
据我了解 CQRS 背后的隔离思想,一个会有两个独立的模型,一个读模型和一个写模型。只有写入模型才能通过命令访问和使用业务域模型。而读取模型则是通过查询的方式直接将数据库内容转化为DTO,根本无法访问业务领域。
对于上下文:我正在编写一个 Web 应用程序后端,为粒子物理提供计算服务。现在我的问题:
1.) 我的业务领域逻辑包含一些函数,这些函数计算数学值作为给定测量系统配置的输出作为输入。因此,从技术上讲,这些是只读查询,可以即时计算值,并且不会更改任何模型中的任何状态。因此,它们应该是读取模型的一部分。然而,因为这些功能与域密切相关,所以它们必须是域模型的一部分,而域模型又是写模型的一部分。当应该包含所有查询的读取模型无法访问域模型时,我应该如何通过我的 API 使这些计算函数可用于前端?
我真的必须触发命令将所有计算保存到数据库中,以便读取模型可以访问计算结果吗?这些“一次性”计算只会被前端短期使用,以后没有人需要访问持久的计算结果。必须是测量配置,而不是计算结果。每当用户点击前端的“计算”按钮时,这些将被重新计算多次。
2.) 我也觉得我复制了很多数据验证代码,因为读模型和写模型都必须反序列化和验证流程链中相同或非常相似的请求参数http request body -> json -> unvalidated DTO -> validated value -> command/query.
我应该如何处理?我可以在读取模型和写入模型之间共享验证代码吗?这似乎消除了隔离。
在此先感谢您的帮助和想法。
我认为您拥有的是一组具有给定输入的域服务,它们返回输出。正如您所说,此服务位于域中。但是,没有什么可以拒绝您在读取模型中使用它们。只要不改变函数内部的域,就可以在域之上的任何层使用它们。如果出于任何原因,此解决方案不可行,例如因为服务需要您不能/不想在查询端构建的域对象,则您始终可以将域服务包装在应用程序服务中。在那里,您输入一个基础对象,对域进行所有转换,调用域服务并返回结果值。
对于第二个问题,可以在领域层构建一个验证服务,作为一组服务或者简单的函数。同样,没有什么可以拒绝您在验证步骤中使用它们。我在上一个 Web 应用程序中做了同样的事情:表单数据的验证步骤调用一组域服务,在处理命令期间构建域对象时也会使用这些服务。更改域中的验证同样会影响与 Web 相关的验证更改。您验证了两次(在构建命令之前和在构建域对象期间),但没关系。
看看端口/适配器或洋葱架构:它有助于理解什么应该留在层内以及重叠层可以使用什么。