什么是 CQRS
CQRS 意思就是命令查询职责分离(Command Query Responsibility Segregation)。很多人认为 CQRS 是一个完整的架构,但是他们错了。它只是一个小小的模式。Greg Young 和 Udi Dahan 首先介绍了这种模式。他们是从 Bertrand Meyer 的 “面向对象的软件结构”一书中得到了 CQS(查询与命令分离( Command Query Separation )) 模式的设计灵感。CQS 背后的主要灵感是:“一个方法更改对象的状态或返回一个结果,但是不能同时包含这两个行为。更正式的说,如果它们之间的引用是透明的且无副作用的,那么这个方法只需要返回一个值。
把方法分为两组
- Commands : 更改一个对象或整个系统的状态。
- Query : 返回结果但并不会改变对象的状态。
在实际使用中很容易分清哪个是 Command 哪个是 Query 。查询将返回一个类型,而命令的返回是 void 类型的。这种模式被广泛使用,它使推理相关对象更容易。另一方面,CQS 仅适用于特定的问题。
许多应用程序使用觉的主流方法,包括模型的读取和写入。同一个模型如果拥有读取和写入的功能,则可能很维护和优化。
这两种模式的真正功能是可以分开改变那些没有状态的方法。这种分享可以在非常方便的情况下处理性能和调优。你可以从写入端单独优化系统的的读取端。写入端称之为领域。领域包含所有行为(业务逻辑)。读取端专门汇报需求。
这种模式的另一个好处是在大型应用程序中。可以将开发者分为较小的团队工作在不同方面的系统(读取或写入)。例如:在读取端的开发人员就不需要了解领域模型。
查询端
查询只包含获取数据的方法。从架构的角度查看这些都会返回 DTO 对象。DTO 对象通常是领域对象。在某些情况下这可能是一个非常痛苦的过程,特别是在获取复杂的 DTO 对象时。
使用 CQRS 可以避免这种情况的发生。相反,它可能介绍一种新的映射到 DTO 的方法。你可以绕过领域模型通过读取端直接从数据存储介质中获取 DTO 对象。当应用程序获取数据时,可以通过读取端调用一个单一的方法来返回一个包含所需数据的 DTO 对象。
读取层可以直接连接数据库(数据模型)而且使用存储过程也不是一个坏主意。直接连接到数据源的查询很容易维护和优化。它就是使用反规范化数据的意义。这样做的原因是:数据查询的次数通常是执行领域模型行为的的许多倍(即领域模型中行为的执行次数比常规的数据查询少很多)。这种反规范化可以提高应用程序的性能。
命令端
由于读取端被分离,所以领域模型只集中处理命令(Command)。现在不再需要公开领域对象的内部状态,仓储(即数据持久化的存储介质)除了GetById方法,只有几个查询方法。
命令由客户端应用程序创建并发送到领域层。命令信息指定一个特定的实体执行某些行为(操作)。命令的命名方法如:ChangeName, DeleteOrder,...。它们指定目标实体执行一些行为返回不同的结果或者执行行为失败收到错误信息。命令通过命令处理程序处理。
客户端通常通过消息传送系统发送命令到域,如一个队列。命令处理程序接受这些命令,并调用域接口的方法。每个命令的粒度被设计成减轻冲突请求的机会。
备注
什么时候使用 CQRS
一般情况下,DDD+CQRS,都会应用到大型系统中,这些系统复杂且需要互相协作。
什么时候不用 CQRS
一般的小项目使用 DDD + CQRS 则没有这个必要,小项目使用简单的数据库驱动开发更来的快。