在进入 CQRS 部分之前,我想花一点时间谈谈 REST 的优缺点。在我们就何时以及为何使用 REST 达成共识之前,我认为不可能回答这个问题。
休息
与大多数其他技术选项一样,REST 也不是灵丹妙药。它有优点也有缺点。
我喜欢使用Richardson's Maturity Model, with Martin Fowler's additional level 0,作为思考工具。
0级
Martin Fowler 也将级别 0 称为 POX 的沼泽,但我认为真正区分此级别的只是使用 RPC over HTTP。它不一定是 XML;也可以是 JSON。
此级别的主要优势是互操作性。大多数系统可以通过 HTTP 进行通信,大多数编程平台可以处理 XML 或 JSON。
缺点是系统难以独立于客户端发展(见第 3 级)。
这种风格的一个显着特点是所有通信都通过一个端点。
1 级
在第 1 级,您开始将 API 的各个部分视为单独的资源。每个资源都由一个 URL 标识。
一个优势是您现在可以开始使用现成的软件(例如防火墙和代理服务器)来控制对系统各个不同部分的访问。您还可以使用 HTTP 重定向将客户端指向不同的端点,尽管在这方面存在一些缺陷。
我想不出任何缺点,除了0级。
2级
在这个级别,你不仅有资源,而且还使用HTTP动词,如GET、POST、DELETE等。
一个优势是您现在可以开始更多地利用 HTTP 基础架构。例如,您可以指示客户端缓存对GET 请求的响应,而其他请求通常不可缓存。同样,您可以使用标准 HTTP 防火墙和代理来实现缓存。您可以免费获得“网络规模”缓存。
级别 2 建立在级别 1 之上的原因是您需要将每个资源分开,因为您希望能够彼此独立地缓存资源。如果无法区分各种资源,或者无法区分读取和写入,则无法做到这一点。
缺点是它可能需要更多的编程工作来实现它。此外,所有先前的缺点仍然适用。客户端与您发布的 API 紧密耦合。如果您更改 URL 结构,客户端会中断。如果您更改数据格式,客户端就会中断。
尽管如此,许多所谓的 REST API 都是在此级别设计和发布的,因此在实践中,许多组织似乎认为这是在优缺点之间进行很好的权衡。
3 级
这是我认为真正 REST 的 REST 设计级别。这与以前的级别完全不同;这是一种完全不同的 API 设计方式。在我看来,0-2 级和 3 级之间有很大的区别。
3 级的一个显着特征是you must think content negotiation into the API design。但是,一旦有了这些,选择这种 API 设计风格的理由就会变得更加清晰。
对我来说,第 3 级 API 的主要优势是您可以独立于客户端来发展它们。如果您小心,您可以在不破坏现有客户端的情况下更改 API 的结构,甚至导航图。如果您需要引入重大更改,您可以使用内容协商来确保客户端可以选择加入重大更改,而旧客户端将继续工作。
基本上,当我被要求编写一个我无法控制客户端的 API 时,我的默认选择是级别 3。
设计 3 级 REST API 要求您以一种对许多人来说不寻常且陌生的方式进行设计,因此这是一个缺点。另一个缺点是客户端开发者经常觉得这种风格的 API 设计不熟悉,所以they often try to second-guess, or retro-engineer, your URL structure。如果他们这样做,您将不得不付出一些努力来阻止他们这样做,因为这将阻止您发展 API。
换句话说,3 级 API 需要大量的开发工作,尤其是在服务器端,但客户端也变得更加复杂。
不过,我要重申其优势:您可以独立于客户端发展 3 级 REST API。如果您不控制客户端,则向后兼容性至关重要。第 3 级使您能够在保持兼容性的同时发展 API。我不知道您可以通过任何其他样式实现此目的。
CQRS
现在我们已经确定了 REST 的一些优点和缺点,我们可以开始讨论它是否适用于 CQRS。
Greg Young 和 Udi Dahan 就 CQRS 达成的最基本协议是it's not a top-level architecture。
简而言之,其原因是构成 CQRS 系统的消息(命令和事件)和查询对解释很敏感。为了做某事,客户端必须知道要发出哪个命令,而服务器必须知道如何解释它。因此,该命令是系统的一部分。
系统可能分布在客户端和服务器之间,但消息和数据结构是相互耦合的。如果您更改服务器解释给定消息的方式,该更改将影响您的客户端。您无法在 CQRS 架构中独立发展客户端和服务器,这就是它不是顶级架构的原因。
因此,鉴于它不是顶级架构,传输架构变得相当无关紧要。从某种意义上说,为了发送消息,您唯一需要的是一个“服务总线”端点,如果您需要的只是互操作性,它很容易成为 0 级端点。毕竟,您唯一要做的就是将消息放入队列中。
那么,最终的答案一如既往:视情况而定。
交货速度是最重要的标准吗?您能否同时控制所有客户端和服务器?那么,也许 0 级就是您所需要的。或许2级就可以了。
另一方面,如果您有无法控制的客户端(移动应用程序、硬件 (IoT)、使用您的公共 API 的业务合作伙伴等),您必须考虑如何处理向后和向前兼容性,在这种情况下,需要 (IMO) 级别 3。不过,在这种情况下,我建议保留 CQRS 的实现细节。