为什么我热爱CQRS

10-01-20 banq
                   

命令查询职责分离模式Command Query Responsibility Segregation (CQRS),也就是命令查询分离Command Query Separation [Young]有很多好处,Why I Love CQRS一文从与传统的ActiveRecord和ORM等方面进行了详细分析。

ActiveRecord是 Ruby on Rails(RoR)强大的快速的技术,它的特点是解决了与关系数据库的阻抗问题,从而避免了不必要的技术复杂性。

ActiveRecord的致命缺陷是:当业务逻辑复杂到一定程度,它开始崩溃,业务逻辑很难维护,一致性保证很困难,更进一步说:实际上是关系数据库掌管了业务状态,关系数据库成为单点风险和性能瓶颈,只能走数据库sharding 等路线进行伸缩(本站有更多关于关系数据库问题的文章)。

传统的领域模型也有其问题:

当发现随着业务复杂,难于发掘正确的领域模型,这是应该使用领域驱动设计DDD。在传统领域模型实践中,有一个现象,使用ORM对象和关系数据库映射框架,或者一种叫做数据访问技术(DAO),这时领域模型就未必是真正的POCO或POJO了,比如在C#中,你必须将你方法声明为virtual或构造一个不用的protected 构造器,一些ORM框架甚至要求你的领域模型继承一个基类(继承基类就不是POJO了,依赖这个框架了)。

很多DDD粉丝DDDers通过查询Repository返回领域模型的DTO实现查询或报表输出,因为查询显示的缘故,会导致领域模型附加一些字段专门用于显示或报表输出,领域对象不是用来显示的,他们有行为,而且行为更重要与他们的属性特征,因为这个领域模型对象被用于显示和查询增加了更多耦合性,难于重构。

CQRS风格编程能够更好地隔离业务逻辑的复杂性,它的强项在于行为,并不暴露任何状态,方法返回类型都是Void。

CQRS有下列好处:

1.分布式系统能力,通过消息能够让应用跨多个物理服务器。

2.高可靠性:因为分布的,每台功能服务器失败不会影响其他。

3.外部系统整合能力:可以把领域事件Domain Events作为消息和外部系统交互。

4.NoSQL:CQRS 并不需要关系数据库来支持领域模型,如果你希望输出报表,那就选择一个关系数据库.

5.跟踪审计,因为事件被记录,我们可以回溯事件,将数据返回以前状态,进行问题跟踪或审计。

6.一个repository,有一种观点是不能用repository实现所有查询,只能用根据ID实现返回一个领域对象的查询,这是对的,当我们需要更多查询和显示时,直接向数据库要数据,这方面工具很多。

7.查询报表纯洁性,CQRS倡导查询报表直接基于数据库,甚至可以做些基于查询的DTO。

                   

2
oojdon
2010-01-20 17:08

2010年01月20日 15:38 "banq"的内容
因为查询显示的缘故,会导致领域模型附加一些字段专门用于显示或报表输出,领域对象不是用来显示的,他们有行为,而且行为更重要与他们的属性特征,因为这个领域模型对象被用于显示和查询增加了更多耦合性,难于重构。

开发的时候不觉得,现在我知道我错了,为了解决UI显示问题我在jivejdon的ForumThread里置入了一个丑陋的sticky boolean值,UI强奸了domain,所以面壁思过,重构中......

private boolean sticky;
public boolean isSticky() {
	return sticky;
}
public void setSticky(boolean sticky) {
	this.sticky = sticky;
}
<p>

[该贴被oojdon于2010-01-20 17:11修改过]

bosslee
2010-01-20 18:22

最主要的问应该在是否有效的传递Event的问题。

特别是在中国网络环境不太好的情况下。

有很多Event通过网络传递的时候怎么样有效的处理。

这个应该是关键。

而且利用JMS传递的时候的时间和客户再次查询过来之前怎么保证有效的处理掉这个Event。

在局域网之内应该不会太难实现。

打算在公司内部用。

最担心的还是Event的处理部分

arden
2010-01-27 18:47

repository

这个东西是用来干嘛用的?用来缓存Command?