在DDD / CQRS中,ReadModel应该充当ViewModel,如果不是,那么映射的责任在哪里? [英] In DDD/CQRS, should ReadModel act as ViewModel, if not then where belongs responsibility for mapping?

查看:314
本文介绍了在DDD / CQRS中,ReadModel应该充当ViewModel,如果不是,那么映射的责任在哪里?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设读取模型 ProductCatalogueItem 是由聚合/写入模型构建的,与写入模型分开存储,并且包含可出售的每种产品,并具有以下特性:

Assume read model ProductCatalogueItem is built from aggregates/write-models, stored separately from write-models, and contains each product available for selling, and has following properties:


  • 基础:产品代码名称价格可用库存数量

  • 文档: short_description 描述,...

  • 产品特征:重量长度深度宽度颜色,...

  • basics: product_code, name, price, number_of_available_stock,
  • documentation: short_description, description,...
  • product characteristics: weight, length, depth, width, color,...

而且,有两种视图:


  • 包含可用产品报价的列表/表格/网格的产品列表,并且视图仅需要以下基本属性:产品代码名称价格可用库存数量

  • 显示所有属性的产品详细信息-基础知识,文档,产品特性

  • product list containing list/table/grid of available product offers, and the view needs only following basic properties: product_code, name, price, number_of_available_stock,
  • product details showing all the properties - basics, documentation, product characteristics.

自然地,想到了两个ViewModel:

Naturally, there come two ViewModels in mind:


  • ProductCatalogueListItem 仅包含基本属性,

  • ProductCatalogueItemDetails 包含所有属性。

  • ProductCatalogueListItem containing only basic properties,
  • ProductCatalogueItemDetails containing all the properties.

现在,..有两个选项(我可以看到)。

Now,.. there two options (I can see).


  1. ViewModels是ReadModels的1:1表示

因此有两个读取模型,而不是一个, ProductCatalogueListItem ProductCatalogueItemDetails 。并且,读取服务将具有两种方法:

Therefore the are two read models, not one, ProductCatalogueListItem and ProductCatalogueItemDetails. And, the read service will have two methods:


  • List< ProductCatalogueListItem> searchProducts(FilteringOptions)

  • ProductCatalogueItemDetails getProductDetails(product_code)

  • List<ProductCatalogueListItem> searchProducts(FilteringOptions),
  • ProductCatalogueItemDetails getProductDetails(product_code).

然后,控制器直接返回这些模型(或映射到dto进行传输层)。

And, controllers return these models directly (or, mapped to dto for transport layer).

这里的问题是过滤,..读取服务应该在不同于方法调用返回的读取模型上执行搜索查询吗?因为,ProductCatalogueListItem没有足够的信息来执行过滤。

The issue here is filtering,.. should read service perform search query on a different read model, than is returned from the method call? Because, ProductCatalogueListItem doesn't have enough information to perform filtering.


  1. ViewModels是ReadModels的另一个项目

读取服务将有两种方法:

The read service will have two methods:


  • List< ProductCatalogueItem> searchProducts(FilteringOptions)

  • ProductCatalogueItem getProduct(product_code)

  • List<ProductCatalogueItem> searchProducts(FilteringOptions),
  • ProductCatalogueItem getProduct(product_code).

而且,从ReadModels到ViewModels的映射是由上层(可能是控制器)完成的。

And, the mapping from ReadModels to ViewModels is done by upper layer (probably controller).

有过滤没有问题,但是,还有另一个问题,即离开域层的数据多于实际需要的数据。并且,控制器将具有更多逻辑。由于不同的运输技术可能使用不同的控制器,因此映射代码可能会在这些控制器中重复。

There is no issue with filtering,... But, there is another issue, that more data leave domain layer, than is actually needed. And, controllers would grow with more logic. As there might be different controllers for different transport technologies, then mapping code would probably get duplicated in those controllers.

哪种方法根据DDD / CQRS来组织职责是正确的,还是完全其他?

Which approach to organize responsibilities is correct according to DDD/CQRS, or completely something else?

要点是:


  • 我应该构建两个读取模型,并使用其中一个进行搜索,然后返回其他模型吗?

  • 我应该构建一个已使用的单一读取模型,然后映射到受限模型视图只包含要查看的基本信息?

推荐答案

首先,您做错了断言:

...读取模型ProductCatalogueItem是通过聚合/写入模型构建的...

"...read model ProductCatalogueItem is built from aggregates/write-models..."

读取模型不了解聚合或有关写入模型的任何信息,您可以直接从数据库构建读取模型,并返回UI所需的数据。

Read model doesn't know of aggregates or anything about write model, you build the read model directly from the database, returning the data needed by the UI.

因此,视图模型是读取模型,但它没有请勿触摸写入模型。这就是为什么存在CQRS的原因:具有不同的模型(读取模型),以优化查询以返回客户端所需的数据。

So, the view model is the read model, and it doesn't touch the write model. That's the reason why CQRS exists: for having a different model, the read model, to optimize the queries for returning the data needed by the client.

更新:

我会尽力解释自己:

CQRS只是根据方法类型将一个对象分成两个对象。有两种方法类型:命令(任何改变状态的方法)和查询(任何返回值的方法)。就是这样。

CQRS is simply splitting one object into two, based on the method types. There are two method types: command (any method that mutates state) and query (any method that returns a value). That's all.

将这种模式应用到应用程序的服务边界时,您将拥有写服务和读服务,因此可以分别缩放命令和查询处理,您也可以有两个模型。

When you apply this pattern to the service boundary of an application, you have a write service and a read service, and so you can scale differently the command and query handling, and you can have also two models.

但是CQRS没有两个数据库,没有消息传递,没有最终的一致性,没有从write更新read模型模式,不是事件来源。您可以不进行CQRS。我之所以这样说,是因为我在您的断言中看到了一些误解。

But CQRS is not having two databases, is not messaging, is not eventual consistency, is not updating read model from write model, is not event sourcing. You can do CQRS wihtout them. I say this because I've seen some misconceptions in your assertions.

也就是说,根据用户希望看到的信息来完成读取模型的设计。 UI,即读取模型是视图模型,它们之间没有映射,它们都是同一模型。您可以在下面的参考文献(3)和(6)中阅读它。我认为这是您整个问题的答案。我不了解的是过滤问题。

That said, the design of the read model is done according to what information the user wants to see in the UI, i.e., the read model is the view model, you have no mapping between them, they both are the same model. You can read about it in the references (3) and (6) bellow. I think this answer to your whole question. What I don't understand is the filtering issue.

一些很好的参考文献:

(1) http://codebetter.com/gregyoung / 2010/02/16 / cqrs-task-based-uis-event-sourcing-agh /

(2) http://www.cqrs.nu/Faq/command-query-responsibility-segregation

(3)Vaugn Vernon撰写的实现域驱动设计一书。第4章:体系结构,命令查询责任隔离或CQRS部分

(3) "Implementing Domain Driven Design" book, by Vaugn Vernon. Chapter 4: Architecture, "Command-Query Responsibility Segregation, or CQRS" section

(4) https://kalele.io/really-simple-cqrs/

(5) https://martinfowler.com/bliki/CQRS.html

(6) http://udidahan.com/2009/12 / 09 / clarified-cqrs /

这篇关于在DDD / CQRS中,ReadModel应该充当ViewModel,如果不是,那么映射的责任在哪里?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆