Flash Player 9 (or above) is needed to view presentations.
We have detected that you do not have it on your computer. To install it, go here.

Like this document? Why not share!

Like this? Share it with your network


The CQRS diet



Presented at Conferencia Rails 2010 ...

Presented at Conferencia Rails 2010

You probably follow the motto “skinny controller, fat model”, which is a good thing. Skinny controllers are definitely the way to go but, as your domain logic grows, it’s very easy to end up with a model overweight problem, which is not so good. The issue is that your ActiveRecord objects have to deal with too many different responsibilities: validation, business rules, awareness of its own persistence, filtering…

Command-Query Responsibility Segregation (CQRS) is an architectural pattern that promises to improve the maintainability, performance and scalability of your applications by helping to separate concerns in your system. This pattern, along with Event Sourcing and other Domain-Driven Design ideas, is gaining increased popularity, particularly among developers building solutions for rich / complex domains.

This talk will introduce these concepts and show different ways we can (re)architect our Rails application in order to get their benefits. From a simple implementation using just the “tools in the room” to a implementation “in all its full glory” using NoSQL data stores and messaging queues.

All those who have a Rails projects complex enough to abuse of model callbacks, de-normalize the database or use presenter objects, may get benefits in terms of simplicity and maintainability from implementing the ideas I’ll present in this talk.



Total Views
Views on SlideShare
Embed Views



5 Embeds 27

http://holsee.com 13
https://twitter.com 9
http://www.linkedin.com 2
https://www.linkedin.com 2
https://si0.twimg.com 1


Upload Details

Uploaded via as Adobe PDF

Usage Rights

CC Attribution License

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
Post Comment
Edit your comment

The CQRS diet Document Transcript

  • 1. the CQRS diet Make your models lose weight By Luismi Cavallé 1 Hello, everyone! Tonight I’d like to talk you about CQRS…
  • 2. COMMAND-QUERY RESPONSIBILITY SEGREGATION the CQRS diet 2 CQRS stands for Command-Query Responsibility Segregation which is a design pattern behind a really…
  • 3. Simple Idea the CQRS diet 3 …simple idea. Let’s take for instance a typical Rails model…
  • 4. save find delete scoped Project Project Report the CQRS diet 4 In Rails any request regarding Projects is handled by the same ActiveRecord model Be that request a find, a filter, a save or a delete, the same model will be used..
  • 5. save find delete scoped Project Project Report COMMANDS QUERIES the CQRS diet 5 Well, the idea behind CQRS is the creation of two objects were there was previously one. The separation occurs based upon whether the methods are a query, meaning that they ask to read data, or a command, meaning that they ask to change the state of the system.
  • 6. Simple idea that enables interesting things architecturally the CQRS diet 6 As you can see, the idea is quite simple and not especially interesting in itself What makes it interesting is the architectural possibilities that it opens.
  • 7. Simple idea that enables interesting things architecturally the CQRS diet 7 Some months ago, observing how these ideas were gaining traction in other development communities, particularly among developers that call themselves “architects” and work in the enterprise, which I thought it was really cool… or maybe not… well!, anyway, the thing is that I became interested and started a personal research about these topics. This talk is about sharing my findings. We will explore this pattern along with a few related concepts and discuss some different implementations with their benefits and pitfalls.
  • 8. WHY SHOULD I CARE? ™ the CQRS diet 8 So, let’s start with the motivations…
  • 9. Are you happy with your Rails app? ★ Models clean and straightforward ★ No need to deal with complex domain logic ★ No scalability or performance issues ★ No maintainability problems the CQRS diet 9 The question to ask here is “Are you happy with your Rails app?”. Because if your models are clean and straightforward –probably because you don’t deal with complex business logic–, if you haven’t got important scalability or performance issues and you don’t feel like there’s too much technical debt in your code. Then you probably don’t need to care about separating reads and writes or any other architectural alternative. But…
  • 10. Some smells… ★ Denormalized database ★ Complex caching ★ Overweighted models ★ Presenter pattern ★ Increasingly complex infrastructure ★ Considering NoSQL the CQRS diet 10 …if you’ve got a denormalized database, or there’s caching logic spread all around your app, or your models are way too big and complex, or you are using the presenter pattern, or your infrastructure is becoming increasingly complex, or you are considering NoSQL solutions. Then, chances are that you’ll find CQRS ideas interesting.
  • 11. E THE SINGL SIBILITY RESPON PLE “ There PRINCI should never be more than one reason for a class to change ” the CQRS diet 11 You know? There’s this Object-Oriented Design better practice that you may already know. It is called “The single responsibility principle” and it states that one object should only have one responsibility (or, put otherwise, just one reason to change). But if you look at an ActiveRecord model you see a totally different story…
  • 12. Model Responsibilities ★ Validation ★ Domain Logic methods & callbacks ★ Structure associations ★ Filtering scopes ★ Presentation helper methods ★ Persistence the CQRS diet 12 In Rails, every of your models has to take care of: Validation, Domain logic (typically hooked to persistence callbacks), Structure (every model declares its associations), Filtering, Presentation (sometimes its convenient to put that presentation logic in the model instead of in a helper) and, last but not least, every model is aware of its own Persistence. Wow! definitely our models got more than one reason to change. Which is ok, as we mentioned earlier, when there’s no much complexity to deal with. But when that’s not the case, this Rails’ monolithic approach makes hard to partition our problem.
  • 13. the CQRS diet the CQRS diet 13 I think it is clear that we need to put our models on a diet. The CQRS diet!
  • 14. QUERIES COMMANDS Project Project Report the CQRS diet 14 Let’s take it from where we left it. The idea was quite simple: Commands & Queries are handled separately by different objects. The interesting part is the architectural decisions that this enables. So let’s explore those interesting things.
  • 15. QUERIES COMMANDS Project Project Details List Project the CQRS diet 15 The first and one of the most interesting things you can do in a CQRS architecture is having two separated data models and making different choices on each of them regarding things like how data is structured or where and how it is stored. It turns out that, given the different purposes of each data model, these choices can be quite different.
  • 16. DOMAIN READ DATA MODEL DATA MODEL ★ Validation ★ Filtering CONCERNS ★ Business Logic ★ Data presentation OBJECT DENORMALIZED NORMALIZED ATRIBUTTES ORIENTED DATA ORIENTED INDEXABLE CONSISTENT TRANSACTIONAL EVENTUALLY CONSISTENT PERSISTENCE BASE ACID IGNORANT the CQRS diet 16 The main concerns of a domain model are mainly about business logic validation and enforcing business rules and domain invariants. So we might decide that the most important attributes for our domain model and its repository are like to be normalized, transactional or consistent. As for the Read model, concerns are different It only cares about presenting data to the user so, in this case, other attributes could be more convenient, like to be denormalized (so data access is faster), indexable or eventual consistent (it’s not a big deal if data is stale some times) These attributes may or may not the best choice for any given system, but the point is that different trade-offs apply and now we can make totally different choices for each model.
  • 17. READ QUERIES COMMANDS DOMAIN MODEL MODEL Project Project Project Task Details List EVENTS UPDATES Event Handler the CQRS diet 17 So now we have two different models: A domain model, responsible of commands, and a read model, responsible of queries. Each of them with totally different attributes. But there’s something missing here, as you’ve probably noticed. In order for this to work at all, we need to keep both models consistent and, preferably, uncoupled as well. So, in order to get that, the piece that we need to add to the system is some kind of syncing mechanism that listens to the changes happening in the domain model and updates the read model accordingly. This agent, ensures consistency and, since its based on events, it keeps both models unaware of each other.
  • 18. Simple example using just the tools in the box (i.e. Rails) 18 To better illustrate this, we’re gonna see a very simple implementation using anything else but Rails.
  • 19. INITIAL MODEL class Project < ActiveRecord::Base # t.string :name # t.text :notes # t.datetime :deadline # t.boolean :active has_many :tasks scope :active, where(:active => true) validates_presence_of :name def status active? ? "Active" : "Inactive" end end the CQRS diet 19 We have this initial model. No CQRS here, yet, ok? It’s an ActiveRecord model which has four attributes: a name, some notes, a deadline, and a flag that indicates whether the project is active or not A project has many tasks It seems that it needs to be filtered by the active flag The presence of a name is necessary for a Project to be valid And finally, we’ve got this handy method that returns a user-friendly string denoting the status of the project. How about our controller?…
  • 20. CONTROLLER class ProjectsController < ApplicationController QUERY def index @projects = ProjectReport.active Project.active end COMMAN D def create project = Project.create!(params[:project]) redirect_to(project, :notice => 'Project created.') end COMMAND def destroy project = Project.find(params[:id]) project.destroy redirect_to(projects_url) end end the CQRS diet 20 …Nothing unexpected here either. We’ve got a nice, skinny controller which deals with two commands (create and destroy) and one query (the index action). All three actions are using the same Project model we saw in the previous slide. And that’s what we’re going to change. Queries and Commands should use different models so, for our index action we’re replacing Project with a new read model we call ProjectReport. Now let’s see how ProjectReport looks like…
  • 21. READ MODEL class ProjectReport < ActiveRecord::Base # t.string :name # t.string :status # => “Active” or “Inactive” # t.integer :project_id scope :active, where(:status => "Active") end the CQRS diet 21 First thing to notice here is that we are using ActiveRecord, but we could be using anything else. From a more lightweight ORM like Sequel, to any NoSQL database, like Redis, CouchDB or MongoDB. Whatever we think that will work better for our read model which only purpose is, I remind you: populating views with data as fast and as conveniently as possible. So, it is just for the sake of the example that we stick to ActiveRecord here. What have here? First thing are the attributes. We’ve got only those that are shown to the user, like the name, the status, which it’s handy that it stores the string to be shown to the user (not a boolean flag that we’d need to transform later) And a reference to the Project in the domain model, that will help us keep track of its changes. Besides attributes, we’ve moved here the “active” scope. Filtering is part the read model so this scope belongs to here. Let’s go back to our domain model now...
  • 22. DOMAIN MODEL class Project < ActiveRecord::Base # t.string :name # t.text :notes # t.datetime :deadline # t.boolean :active has_many :tasks scope :active, where(:active => true) validates_presence_of :name def status active? ? "Active" : "Inactive" end end the CQRS diet 22 Our initial model used to look like this. But now, we have a Read Model which frees this one from a couple of its responsibilities Like filtering, this scope is no longer being used (controllers use the one in the read model) so, let’s get rid of it…
  • 23. DOMAIN MODEL class Project < ActiveRecord::Base # t.string :name # t.text :notes # t.datetime :deadline # t.boolean :active has_many :tasks validates_presence_of :name def status active? ? "Active" : "Inactive" end end the CQRS diet 23 What else? The status. Now it is stored in the read model and our domain logic doesn’t need it for anything. So let’s remove it too…
  • 24. DOMAIN MODEL class Project < ActiveRecord::Base # t.string :name # t.text :notes # t.datetime :deadline # t.boolean :active has_many :tasks validates_presence_of :name end the CQRS diet 24 Nice! Removing code is one of the great joys of being a programmer, don’t you think? So, we end up with this two models…
  • 25. READ MODEL DOMAIN MODEL class Project < ActiveRecord::Base class ProjectReport < ActiveRecord::Base # t.string :name # t.string :name # t.string :status # t.string :status # t.datetime :deadline # t.integer :project_id # t.boolean :active scope :active, where(:status => "active") has_many :tasks end validates_presence_of :name end the CQRS diet 25 …that we need to keep consistent. We need something that listens to the Domain Model and updates the Read Model accordingly. For that, one of the simplest tool we can use, right out of Rails box, is…
  • 26. OBSERVER class ProjectObserver < ActiveRecord::Observer def after_save(project) report = ProjectReport.find_or_create_by_project_id(project.id) report.update_attributes! :name => project.name, :status => project.active ? "Active" : "Inactive" end def after_destroy(project) ProjectReport.destroy_all(:project_id => project.id) end end the CQRS diet 26 …An observer. By definition, observers listen to changes in other objects and do something about them. So they seem exactly what we need Every time a Project is saved in the Domain, we will find or create a related ProjectReport in the Read Repository and update the name and the status accordingly. Note that for the status, we made here the transformation from the active flag in the domain model to the string we store in the read model. Besides that when a Project is removed from the domain repository, we want any related ProjectReport to be removed from the read model as well. And that’s all about the observer…
  • 27. READ MODEL DOMAIN MODEL class Project < ActiveRecord::Base class ProjectReport < ActiveRecord::Base # t.string :name # t.string :name # t.string :status # t.string :status # t.integer :project_id # t.datetime :deadline # t.boolean :active scope :active, where(:status => "active") end has_many :tasks validates_presence_of :name end class ProjectObserver < ActiveRecord::Observer def after_save(project) report = ProjectReport.find_or_create_by_project_id(project.id) report.update_attributes! :name => project.name, :status => project.active ? "Active" : "Inactive" end def after_destroy(project) ProjectReport.destroy_all(:project_id => project.id) OBSERVER end end the CQRS diet 27 We are quite done with this example. This slide summarizes what we ended up with. You know, the problem with examples is they have to be simple to avoid distraction, but, just because of that, often they don’t justify the technique you’re showing. Our initial model had no “overweight” problem to begin with. But, still, the point is that the example helps you understand the pattern. If that’s not the case just raise your hand and ask.
  • 28. Similar, real-world example* ★ MongoDB for the Read Model (Presenters Silos) ★ Asynchronous Observers with RabbitMQ (Silovators) * Denormalizing Your Rails Application by Daniel Lucraft & Matt Wynne Scottish Ruby Conference 2010 the CQRS diet 28 Ok, before moving on to something else, I just want to point out an interesting real-world example of this approach It was presented by Daniel Lucraft and Matt Wynne in the latest Scottish Ruby Conf and there’s a video available in the internet. In the talk they describe the architecture of songkick (a social website about music and concerts) which is very similar to what we’ve just seen / They use MongoDB for the Read Model, using Presenters and what they call, “Silos”, and, the other interesting thing is that their observers work asynchronously (which is very typical) using RabbitMQ queues. So, this is an interesting resource if you want to dig deeper into this basic approach to CQRS.
  • 29. EVENTS the CQRS diet 29 So, let’s move on to the next big topic of the talk: Events. And I don’t mean last night’s event which was awesome. I mean…
  • 30. DOMAIN EVENTS the CQRS diet 30 …Domain Events.
  • 31. READ REPO DOMAIN SITORY EVENTS EVENT HANDLERS the CQRS diet 31 Let’s say that we are sold to CQRS and now we have a whole system that segregates reads and writes. Even in colors! We’ll soon realize that domain events have become a critical part our system.
  • 32. Why events are key? ★ Events keep models consistent ★ Events keep models loosely coupled ★ Events keep track of all changes the CQRS diet 32 Why? Well they keep our data models consistent, we already know that. But there’s more. They also keep our data models loosely coupled. This is very important. We could try to keep our models consistent in different ways like, for instance, by asking the domain model about its state. However, doing that we would be adding coupling into the system, making it brittle (you know, changes in one part of the system would cause other parts of the system to break). So instead of that, we use events. Events don’t expose the state of the domain but only the *changes* in the domain. That maintains the domain model isolated from the outside world, which is nice to make changes without affecting other parts of the system. And there’s one more important thing about events They keep track of absolutely any change that happens in the domain. And that could make events no less than...
  • 33. The Source ofTruth the CQRS diet 33 …The Source of Truth! And we would have new ways to add value to our system. Let’s see them.
  • 34. READ REPO DOMAIN SITORY EVENTS EVENT HANDLERS EVENT STORE the CQRS diet 34 Ok, there we are. The first further step we can take is to store every event that the domain publishes. If domain events are going to be our source of truth, we definitely need to store them. This will give us some immediate value…
  • 35. Event store ★ Comprehensive audit log ★ Ability to replay events the CQRS diet 35 First of all we’ve got the most comprehensive audit log, which for some domains (like Accounting) is a must, and for the rest, it can provide a great business value. This is not the same as any other infrastructure log, this events has meaning to the domain, to the business. Think about diagnosing problems or giving customer support. The value of such a log could be huge. And with an event store, we got this value virtually for free. Besides that we have now the ability to replay events. Let’s say that we find a bug in one of our event handlers that makes one of our views to show incorrect data. When we fix the bug, we also need to fix the corrupt data in the read repository. Normally you would do it kind of manually: you’d run a script over the read repository that fixes the data. But now, thanks to our shiny event store, we could do something else, we could just replay all the related events over the, now fixed, event handler so that the correct dataset will be generated. Nice, but there’s more…
  • 36. Domain Persistence the CQRS diet 36 …and it has to do with Domain Persistence. We want our events to be our source of truth. So let’s say that we implement in our Domain objects the ability to apply events to them. With that, we have now the capacity to re- construct any Domain object up to its latest state just by applying its event stream to it. And, if we have this capacity, we no longer need any persistence solution for our domain other than…
  • 37. Domain Persistence Event Store the CQRS diet 37 The event store.
  • 38. READ REPO DOMAIN SITORY EVENTS EVENT HANDLERS EVENT STORE the CQRS diet 38 That’s it. Every time we need a certain domain object to process a command the Domain Repository will get the stream of events related to that object from the Event Store. Then, it will instantiate a new object and it’ll apply the events to it. That way we get the object in its current state, ready to process the next command. We won’t need any other persistence mechanism. We won’t ever “save” domain objects, we will just *publish* events. We’re gonna see an example of this. But first let me just point out that all this approach around events has a name which is…
  • 39. EVENT SOURCING the CQRS diet 39 “Event Sourcing”, and it is a design pattern in its own right that happens to work very well with CQRS. So now that we have a name, let’s see an implementation example of a CQRS system with Event Sourcing
  • 40. github.com/cavalle/banksimplistic the CQRS diet 40 The example is extracted from a sandbox application that I use to experiment with different implementations of these ideas. It is called BankSimplistic, it’s about banking (not surprisingly), and you can find the code in github if you want to check it out.
  • 41. FEATURE feature "Deposit cash", %q{ In order to have money to lend to other clients As a banker I want clients to deposit cash into their accounts } the CQRS diet 41 In our bank we want our clients to be able to deposit cash into their accounts, so that we have money to invest in subprime mortgages, right? So, “Deposit cash” is the functionality we’re looking into in this example.
  • 42. CONTROLLER class DepositsController < ApplicationController # POST /accounts/23/deposits def create account = Account.find(params[:account_id]) account.deposit(params[:deposit][:amount]) redirect_to account end end the CQRS diet 42 We start with the controller. Let’s say that we receive a POST request to make a deposit into a given account. First thing we do is to fetch the Account from the Domain Repository, finding it by id. Then we invoke its deposit method passing it through the amount of money. Finally we just redirect the user to the Account page. And that’s all. Two things to note here: 1st, the deposit method sounds like a command (it is quite clear what we’re doing, we’re not updating attributes or anything like that). And the 2nd thing is that we’re not saving the account. And this is not because the save call is inside the deposit method as we’re going to see right now. It is because we don’t have to save anything. So let’s see the model
  • 43. DOMAIN MODEL class Account include AggregateRoot def initialize @balance = 0 end def deposit(amount) # Do some validation new_balance = @balance + amount publish :deposit_made, :amount => amount, :new_balance => new_balance, :account_uid => uid end the CQRS diet 43 Ok, the Account model includes a module called AggregateRoot. Don’t worry very much about this name. All you need to know is that it provides the necessary infrastructure logic. So our model has an initialize method that sets the balance of the account to zero. Makes sense that new accounts has no money, of course. Then we have our deposit method. The first thing you put in a method like this is some kind of validation logic related to the command being processed. You would check here things like deposit limits or whether the account is open, for instance. Next, if validation is ok, the new balance is calculated, just by adding the amount to the current balance. That’s our domain logic. And, finally, the method publishes an event called “deposit_made” that includes the amount of the deposit, the new balance, and the id of the account where it has been made. And that’s all. The interesting thing here is that we’re not updating the balance of the account inside this method. We’re just calculating the new balance and then publishing the event.
  • 44. DOMAIN MODEL class Account include AggregateRoot def initialize @balance = 0 end def deposit(amount) # Do some validation new_balance = @balance + amount publish :deposit_made, :amount => amount, :new_balance => new_balance, :account_uid => uid end def on_deposit_made(event) @balance = event.data[:new_balance] end the CQRS diet 44 To update the balance of the account we have this “on_deposit_made” method that will receive the event that the command generates and will update the balance. And, why is that? you may ask. Well, good question. We need this “on” methods because, as I mentioned earlier, we need to be able to reconstruct a domain object just by applying its events. That’s why any logic that updates the state of the object needs to be inside one of these event handling methods. That’s what these methods are: internal event handlers. To understand this better, let’s take a look one level down at the infrastructure logic. To begin with, what does the `publish` method do?
  • 45. THE MAGIC def publish(name, attributes) event = Event.new(:name => name, :data => attributes) do_apply event event.aggregate_uid = uid published_events << event end def do_apply(event) method_name = "on_#{event.name}" method(method_name).call(event) end the CQRS diet 45 It starts by creating a new event with its name and data. Good Then it calls a method called “do_apply” and what that method does is precisely calling the internal event handler we saw earlier. Makes sense? Then the id of the object is added to the event data and finally the event is added to a published_events collection from where it will be finally published to the external world and, also, saved to the event store.
  • 46. THE MAGIC def find(klass, uid) events = Event.find(:aggregate_uid => uid) klass.build_from(events) end def build_from(events) object = self.new events.each do |event| object.send :do_apply, event end object end the CQRS diet 46 Some other magic you might find interesting is the find method we used from the controller to get the Account object It first gets all the events related to the requested object, and then it calls the build_from method in the Account class, passing it through the event stream. That build_from method will initialize a new instance of the class and then it will apply each event to the object using the same “do_apply” method we saw before. And then the object will be ready for the next command. And that’s pretty much all about this example
  • 47. DOMAIN MODEL class Account include AggregateRoot def initialize @balance = 0 end def deposit(amount) # Do some validation new_balance = @balance + amount publish :deposit_made, :amount => amount, :new_balance => new_balance, :account_uid => uid end def on_deposit_made(event) @balance = event.data[:new_balance] end the CQRS diet 47 I’ve skipped the part of updating the read model since it would be quite similar to what I showed you in the first example. Summarizing: In this example the command method does three things: first it validates that the command is ok to be processed (no domain invariant is broken, and so on and so forth). Second it applies the necessary business logic required by the command. And third it publishes an event. But it doesn’t change the state of the object. This is done in an internal handler for that event just published. That way, the domain repository will be able to restore domain objects just from their events.
  • 48. TIME FOR A WEIGHT CHECK the CQRS diet 48 At the beginning of the talk we decided to put our models on a diet. Now I think it’s time for a weight check
  • 49. Validation Domain Logic methods & callbacks Structure associations Filtering scopes Presentation helper methods Persistence the CQRS diet 49 We started with models which had all these responsibilities. The first we did was creating a separated read model. That freed our domain model from Presentation and Filtering. We can also say that those associations used only for filtering could be removed from the domain as well. Then, in the second part of the talk, we saw the value of using an Event Store as the source of truth of the system and decided to use it also as the only persistence mechanism of the domain. So our models no longer need to worry about persistence. We end up with a nice, thin Domain model that now, can focus in its most important responsibilities: validation and domain logic. It’ll be more about behaviours rather than structure. By the way, talking about responsibility…
  • 50. There will be (some) dragons ★ More complex architecture than Rails’ MVC ★ More “moving parts” in the infrastructure ★ Distributed and asynchronous world is chaotic ★ Problems that used to be trivial no longer are the CQRS diet 50 It wouldn’t be very responsible of me to let you go from these talk thinking we’ve got a silver bullet. I’m sorry to say there is no such a thing as a silver bullet. Everything has trade-offs. So, I should mention that with CQRS the simplest case, say the “Hello world” app, is more complex than with Rails MVC. We have two models instead of one and we have to coordinate them. We saw it in the first example: we finished with more lines of code than we started. We’ll also have more “moving parts” in our infrastructure. You know? It is very nice to only have to worry about one database and one web server. That’s happiness! But with CQRS it is easy to end up with several different databases, one messaging queue, not to mention caching or text indexing. Be careful with that. More “moving parts” means more things that can stop working so more things to monitor, and it becomes more difficult to diagnose problems. Also as soon as you decide to handle your events asynchronously, you will enter to the distributed world which could be kind of chaotic: messages arrive out-of-order or duplicated, everything is asynchronous, consistency in the read model is eventual so you have to deal with this in the User Interface, etc. This is a new world and it requires you to change your mindset, which is not always easy. Related to this you’ll find that some problems that used to be trivial, no longer are. For instance validating the uniqueness of a value might not be as simple as it used to. Again, you have to change your mindset, think differently, constraints have changed.
  • 51. You need a good reason ★ Complex domain logic ★ Complex existent infrastructure ★ Complex scalability needs the CQRS diet 51 So, since there will be dragons you need a good reason to get into CQRS. I’d mention three: A complex domain logic (separating responsibilities makes things simpler), an existing complex infrastructure (CQRS would give you a framework to organize it better) or complex scalability needs (with CQRS, you are partitioning your system at application level and that makes it quite scalable). In all, you need to have...
  • 52. Complex Problem the CQRS diet 52 a complex problem to be solved for CQRS to pay off
  • 53. FINAL THOUGHTS the CQRS diet 53 So, we’re almost done. Some final thoughts.
  • 54. Separating reads & writes is not new ★ Databases ★ HTTP ★ Infrastructure level ★ Performance or Scalability the CQRS diet 54 The idea of separating reads & writes in your system isn’t new at all. We’ve been doing that with databases for ages (you don’t need to look at NoSQL databases like CouchDB where this is pretty explicit, you just need to look at the classic master-slave schema with mysql, where one database is only used for reading) One of the key points of HTTP (and the REST philosophy) is that it segregates reads and writes with its four verbs, so that any proxy can take advantage of knowing whether a request is a GET or not, and do interesting things about it (like caching) However, the segregation in these cases is made at infrastructure level and because of performance or scalability reasons.
  • 55. Separating by function is not new ★ Big systems (e.g. Amazon, Ebay) partition its functionality at application level ★ But again the motivation is scalability the CQRS diet 55 Separating by function isn’t new either Big systems like Amazon’s or Ebay’s partition its functionality at application level. Although there’s only one user interface, they have separated systems for Orders, Billing or Shipping. That way it is easier for them to scale the system But again, that’s the motivation, scalability
  • 56. Separate reads & writes at application level the CQRS diet 56 In my opinion, what makes CQRS interesting is that it takes the idea of separating reads & writes and applies it at application level
  • 57. Benefits in terms of maintainbility the CQRS diet 57 And because of that you get benefits in terms of maintainability. It makes easier for you to write a beautiful, expressive domain model
  • 58. Benefits in terms of maintainbility Performance and scalability as a side effect VERY NICE the CQRS diet 58 And yes, as a nice side effect, your system will perform and scale quite well
  • 59. the CQRS diet THANKS! Luismi Cavallé @cavalle 59
  • 60. Resources ★ github.com/cavalle/banksimplistic ★ cqrsinfo.com ★ groups.google.com/group/dddcqrs the CQRS diet 60
  • 61. This slide is intentionally left blank 61