CQRS命令和查询。它们是否属于DDD方面的应用程序或域级别?

问题描述 投票:0回答:3

阅读不同的DDD文献我偶然发现了一个理论问题。问题是我是否应该在应用程序或域级别放置命令和查询。

因此,一些作者如Scott Wlaschin(在他的书“Domain Modeling Made Functional”中)这样说

如果命令成功,它将启动工作流,进而创建相应的域事件

因此,例如“Place Order”命令和Domain Event“Order Placed”之间存在对应关系。这让我相信,我应该将命令和事件放在一个级别并组织它,如下所示:

\Model
    \Message
         \Command
             PlaceOrder.lang
         \Event
             OrderPlaced.lang

因此,我将所有命令放在域级别,而应用程序服务调用这些命令并将它们包装在例如事务中。

然而,还有另一种观点,在Scott Millett的书(领域驱动设计的模式,原理和实践)中表达。引述说:

命令是业务任务,系统的用例,它位于应用程序层中。您应该使用业务语言编写命令。

由于这种矛盾,我不太确定,处理命令(以及查询)的最规范方法是什么。在现实世界中,他们是否生活在域或应用程序级别?

domain-driven-design cqrs
3个回答
2
投票

命令和查询肯定是在应用程序级别。

他们正在调用应用程序服务方法,这些方法负责跨越事务,高级别日志记录和委托给业务对象。

查询服务也在应用程序级别,返回域的优化视图,通常不使用域存储库,而是直接访问数据。


1
投票

由于这种矛盾,我不太确定,处理命令(以及查询)的最规范方法是什么。在现实世界中,他们是否生活在域或应用程序级别?

在这一点上,文献有点令人困惑,主要是出于历史原因。

当我们谈论消息时,也就是我们的应用程序/服务的API;这些属于域模型之外。

根本问题是消息模式是应用程序与与之通信的客户端之间的合同定义的一部分。合同,特别是那些跨越组织边界的合同,需要保持稳定,因为变革的成本很高。

将此与您的域模型的内存表示形成对比,后者纯粹是一个实现细节,可以随时更改。您的数据模型位于中间位置 - 客户端不关心您的信息在持久存储中的样子,但您未来的应用程序需要能够读取前任留下的信息。

Udi Dahan说服务“共享契约和架构,而不是类或类型”时,他正在描述正在交换的消息。客户不需要关心我们在域模型的实现中使用的“类或类型”。

现在,公平地说,客户不需要关心我们在应用程序的实现中使用的“类或类型”。您获取PlaceOrder消息(由在网络上发送给您的字节序列表示的语义)并将其表示为类型化内存引用的内存排列这一事实是您自己的事情。

我们在这里要注意的是,负责解释字节的代码属于代码的一部分,负责与其他事物进行通信,而不是管理业务内存抽象的代码部分。


1
投票

至于我,DDD的主要思想是无处不在的语言,有界上下文和上下文映射。因此,如果我们专注于这些概念,所有其他部分将成为实现细节。

15年前,当编写“蓝皮书”时,它就是Java的时代。如今,有不同的范例来去匆匆。

我喜欢将命令,请求,事件和响应分成不同的级别。主要问题是你很快就会缺少合适的词汇。但这是一个众所周知的编程问题。

实施的核心是一个词汇表。它不是整个无处不在的语言,但可能是其中的大部分。在那里,我模拟特定于域的类和结构,主要使用不可变数据类型。你把工厂和不变量放在那里。词汇不依赖于代码的其他部分。

接下来,业务核心有决策者,他们接受命令并产生事件或拒绝。命令是改变系统状态的意图。事件是关于改变系统状态的决定。两者都是不可变的并且使用词汇表达。命令包含制定决策所需的综合数据,因此决策者无需从某处检索其他数据。因此,决策者可以是一个纯粹的功能。

命令和事件是系统业务核心的内部。但是您可以获得请求并以某种有线格式发送响应,如JSON,XML,ProtoBuf等。您应该编组/解组它,添加其他数据,如身份验证/标识,不同的跟踪ID,并将其转换为某种对象模型,它对线格式一无所知。我将这些对象模型称为业务请求和业务响应。它由应用程序层拥有。

仅凭请求和响应是不够的。除了他们的数据,您还需要从存储库和其他依赖项中检索其他数据,并在做出有关状态更改的决策后继续存在。因此,获取业务请求,从依赖项收集数据,构建命令,将其发送给决策者,获取事件或拒绝,执行此决策(存储到存储库等)并生成业务响应 - 这些都是责任应用程序层

我没有描述读取模型,因为只要读取模型的响应来自使用词汇表中的数据类型表示的应用程序层,它们就可以以多种不同的方式实现。

因此,与业务请求/响应相关的有线格式和转换器属于基础结构适配器层。业务请求和响应及其与命令/事件/拒绝的转换器属于应用程序层(以及为决策和执行决策准备数据的任务)。命令/事件/拒绝属于功能核心。

像请求,响应,命令,事件这样的术语不是很有用:它们非常过载而且有点讽刺,我们在非模糊无处不在的语言中使用它们。但我仍然希望这会有所帮助。

© www.soinside.com 2019 - 2024. All rights reserved.