CQRS, Task Based UIs, Event Sourcing agh!
原文地址:CQRS, Task Based UIs, Event Sourcing agh!
Many people have been getting confused over what CQRS is. They look at CQRS as being an architecture; it is not. CQRS is a very simple pattern that enables many opportunities for architecture that may otherwise not exist. CQRS is not eventual consistency, it is not eventing, it is not messaging, it is not having separated models for reading and writing, nor is it using event sourcing. I want to take a few paragraphs to describe first exactly what CQRS is and then how it relates to other patterns.
许多人已经搞不清是什么CQRS。他们看cqrs作为架构,但是它不是。CQRS是一个非常简单的模式,使得很多的机会可能不存在的架构。CQRS不是最终一致性,它不是事件,它不是消息,它不具有读写分离的模式,也不是使用事件源。我想把几段描述什么是第一CQRS然后如何涉及到其他模式。
CQRS Command and Query Responsibility Segregation CQRS命令和查询职责分离
Starting with CQRS, CQRS is simply the creation of two objects where there was previously only one. The separation occurs based upon whether the methods are a command or a query (the same definition that is used by Meyer in Command and Query Separation, a command is any method that mutates state and a query is any method that returns a value).
从CQRS,CQRS仅仅是两个对象那里以前只有一个创作。根据是否发生分离的方法是命令或查询(相同的定义是由Meyer在命令和查询,命令任何方法改变状态和查询使用的是任何返回值的方法)。
When most people talk about CQRS they are really speaking about applying the CQRS pattern to the object that represents the service boundary of the application. Consider the following pseudo-code service definition.
当大多数人谈论cqrs他们确实说的是关于应用CQRS模式的对象,代表应用程序的服务边界对象。考虑下面的伪代码服务定义。
CustomerService 客户服务
void MakeCustomerPreferred(CustomerId)
Customer GetCustomer(CustomerId)
CustomerSet GetCustomersWithName(Name)
CustomerSet GetPreferredCustomers()
void ChangeCustomerLocale(CustomerId, NewLocale)
void CreateCustomer(Customer)
void EditCustomerDetails(CustomerDetails)
Applying CQRS on this would result in two services 应用CQRS这将导致两个服务
CustomerWriteService
void MakeCustomerPreferred(CustomerId)
void ChangeCustomerLocale(CustomerId, NewLocale)
void CreateCustomer(Customer)
void EditCustomerDetails(CustomerDetails)
CustomerReadService
Customer GetCustomer(CustomerId)
CustomerSet GetCustomersWithName(Name)
CustomerSet GetPreferredCustomers()
That is it. That is the entirety of the CQRS pattern. There is nothing more to it than that… Doesn’t seem nearly as interesting when we explain it this way does it? This separation however enables us to do many interesting things architecturally, the largest is that it forces a break of the mental retardation that because the two use the same data they should also use the same data model.
这就是,cqrs模式的整体性。没有什么比这更有趣的了,当我们解释它的时候,似乎没有什么有趣的事吗?这种分离而使我们的建筑做很多有趣的事情,最大的是它强制分离,因为两使用也应该使用相同的数据模型相同的数据。
The largest possible benefit though is that it recognizes that their are different architectural properties when dealing with commands and queries … for example it allows us to host the two services differently eg: we can host the read service on 25 servers and the write service on two. The processing of commands and queries is fundamentally asymmetrical, and scaling the services symmetrically does not make a lot of sense.
最大可能的好处是,在处理命令和查询时可具有不同的架构特性,例如它允许我们host这两项不同的服务:我们可以在25个服务器上进行读写服务,并在2个服务器上进行写服务。命令和查询的处理是从根本上是不对称的,缩放服务对称的不做很多的意义。
Task Based UI 基于任务的用户界面
A task based UI is quite different from a CRUD based UI. In a task based UI you track what the user is doing and you push forward commands representing the intent of the user. I would like to state once and for all that CQRS does not require a task based UI. We could apply CQRS to a CRUD based interface (though things like creating separated data models would be much harder).
基于任务的用户界面是一个CRUD为基础的用户界面完全不同。在任务为基础的用户界面中,您可以跟踪用户正在做的事情,然后向用户推送命令,表示用户的意图。我想一劳永逸,CQRS并不需要一个基于任务的用户界面。我们可以运用CQRS到CRUD界面(尽管诸如创建独立的数据模型会更难)。
There is however one thing that does really require a task based UI… That is Domain Driven Design.
然而有一件事需要一个基于任务的用户界面……这是域驱动设计。
The Application Service Layer in Domain Driven Design represents the tasks the system can perform. It does not just copy data to domain objects and save them… It should be dealing with behaviors on the objects… Before going further let’s look at what happened if we did; there would be no verbs in our ubiquitous language except for “Create”, “Delete”, and “Change”. While there exist many domains where this is what the Ubiquitous Language is actually like, you probably should not be using Domain Driven Design for such systems.
应用服务层在域驱动设计中表示系统可以执行的任务。它不只是复制数据到域对象,并保存它们……它应该处理的对象上的行为……然后再让我们看看发生了什么,如果我们做了,我们无处不在的语言,除了“创建”,“删除”,和“变化”。虽然存在许多领域,这是无处不在的语言实际上是一样的,你可能不应该使用域驱动的设计,这样的系统。
The concept of a task based UI is more often than not assumed to be part of CQRS, it is not, it is there so the domain can have verbs but also capturing the intent of the user is important in general. Was this a managerial override or a normal update? Does it make a difference? It depends on what question you want to ask …
一个基于用户界面为基础的任务的概念的往往不认为是CQRS的一部分,它不是,它是那么的域可以有动词也捕捉用户的意图,总的来说是重要的。这是一个管理覆盖或正常更新吗?它有区别吗?这取决于你想问的是什么问题…
Moving on to the next pattern that gets confused into CQRS
Event Sourcing 事件源
For this I want to be clear, when I use this term I am not encompassing all of what is written on the bliki. I am referring to storing current state as a series of events and rebuilding state within the system by replaying that series of events.
这个要想清楚,当我用这个词我不包括所有写在bliki是什么。我指的是存储当前状态的一系列事件和重建状态在系统内的这一系列事件的回放。
On the command side of the equation, since reads are no longer on the domain, storing events can be a great way of keeping the current state. The value increases more if you decide to have two separate models (a write model and a read model) and you have a need to integrate between the two of them as you will likely be doing that through events. Since you are building the eventing anyway, why not just use the one model to manage your state?
在命令方式这一边上,因为读取不再是在域上,存储事件可以是一个伟大的方式来保持当前状态。如果你决定要有2个独立的模型(一个写模型和一个读模型),你就有了一个需要在两者之间进行整合,因为你很可能会通过事件来做这些事情。既然你要构建事件,为什么不只是使用一个模型来管理状态?
Messaging Patterns 消息模式
There is no need to use messaging patterns with CQRS. That said, if you separate your data models you will more likely than not use messaging in the integration between the models because it offers interesting possibilities.
没有必要使用消息模式与CQRS。也就是说,如果你将你的数据模型分离,你将更可能比不使用消息传递的模型,因为它提供了有趣的可能性。
Finally I come to the last “pattern” I hate to call it a pattern when it is really a concept that people tend to put into their definitions of CQRS and it goes hand in hand with messaging.
最后我到了最后的“模式”,我讨厌把它称为一个模式时,这是一个真正的概念,人们往往更倾向于定义为CQRS,并消息齐头并进。
Eventual Consistency 最终一致性
Eventual consistency is also quite often introduced between the services. It is done for many architectural reasons but the largest is that it allows you to increase your scalability and availability. If you remember CAP theorem consistency if given up allows increases in the other two. Eventual consistency is extremely useful in between the models if you have them in a separated fashion but is in no way a property of CQRS itself.
最终的一致性也很经常被介绍的在两个服务之间。它是服务于许多架构的原因,但最大的理由是,它允许您增加可扩展性和可用性。如果你还记得CAP定理的一致性,如果放弃允许增加其他两个。最终一致性是在模型之间是非常有用的,如果你在分离方面使用他们,但绝不是CQRS本身属性。
Going through all of these we can see that CQRS itself is actually a fairly trivial pattern. What is interesting around CQRS is not CQRS itself but the architectural properties in the integration of the two services. In other words the interesting stuff is not really the CQRS pattern itself but in the architectural decisions that can be made around it. Don’t get me wrong there are a lot of interesting decisions that can be made around a system that has had CQRS applied … just don’t confuse all of those architectural decisions with CQRS itself.
通过这些我们可以看到,CQRS本身其实是一个相当普通的模式。有趣的是在CQRS不CQRS本身,但在这两个服务集成架构的特性。换句话说,有趣的东西是不是真的CQRS模式本身,可它周围的建筑的决定。不要误会我有很多有趣的决定,可以在一个系统,有CQRS应用…只是不要把所有这些建筑的决定cqrs本身。
On a personal note it feels so weird to be writing to a blog again. Writing for a book is hard, writing for a blog is easy. Pages in the book average me an hour or more while this took me just over 30 minutes to write. The less formal style allows one to write in a more stream of consciousness manner. Anyways, hope everyone enjoys the blog posts that will be pouring in over the next short period.
在个人笔记上,写博客感觉很奇怪。写一本书很难,写博客很容易。这本书平均每小时我一个小时或更多,而这只花了我30分钟的时间写。不太正式的风格让人在意识的方式上写下更多的意识。不管怎样,希望大家都喜欢在下一个短时期内就可以投入的博客文章。