Upgrade to Pro — share decks privately, control downloads, hide ads and more …

CQRS for Great Good

CQRS for Great Good

4bdec7992496d7711705c62db45726b4?s=128

Oliver Wolf

April 30, 2015
Tweet

More Decks by Oliver Wolf

Other Decks in Technology

Transcript

  1. CQRS for Great Good Oliver Wolf

  2. Oliver Wolf @owolf www.innoQ.com @innoQ

  3. CQRS Command Query Responsibility Segregation

  4. The default architecture for enterprise apps Domain Model User Interface

    Remote Facade Application Services DTO DTO ORM DB findCustomers()
 getCustomer()
 updateCustomer()
 <customer> <name>John Doe</name> <address>...</address> ... </customer>

  5. The default architecture for enterprise apps Domain Model User Interface

    Remote Facade Application Services DTO DTO ORM DB GET /customers?filter=...
 GET /customer/{id}
 PUT /customer/{id}
 { "name": “John Doe”, "address": { ... } }
  6. The default architecture for enterprise apps Domain Model User Interface

    Remote Facade Application Services DTO DTO ORM DB GET /customers?filter=...
 GET /customer/{id}
 PUT /customer/{id}
 { "name": “John Doe”, "address": { ... } } Anything wrong 
 with this?
  7. Maybe not.

  8. Scalability?

  9. Domain Model?

  10. “The features that characterize a class are divided into commands

    and queries. A command serves to modify objects, a query to return information about objects.” Bertrand Meyer
 ETH Zurich 
 cited from: Object-Oriented Software Construction, second edition, 1997
  11. CQS Command Query Separation

  12. Part of the Design-by-Contract 
 methodology First demonstrated in the

    object-oriented EIFFEL programming language
  13. class Foo { void command(); Result query(); } Mutates state

    Returns a value without causing side effects
  14. CQRS = CQS in the large Scope is a single

    class Scope is a Bounded Context
  15. interface CustomerService { void updateCustomer(Customer); CustomerList findCustomers(CustomerQuery); Customer getCustomer(ID); void

    deleteCustomer(ID); }
  16. interface CustomerQueryService { CustomerList findCustomers(CustomerQuery); Customer getCustomer(ID); }
 interface CustomerCommandService

    { void updateCustomer(Customer); void deleteCustomer(ID); }
  17. The default architecture for enterprise apps Domain Model User Interface

    Remote Facade Application Services DTO DTO ORM DB
  18. The default architecture for enterprise apps Domain Model User Interface

    Query Facade Query Services DTO DTO ORM DB Command Facade Command Services CQRS PATTERN APPLIED
  19. That’s it?
 You serious???

  20. Yes, sorry.

  21. The interesting thing about CQRS is not the pattern itself.

  22. It’s damn simple, actually.

  23. But it encourages you to challenge established assumptions and opens

    up new architectural options!
  24. Unlearn what you have learned you must.

  25. 
 assumptions
 we often take for granted

  26. Assumption 1: Reads and writes are strongly cohesive, so they

    must be part of the same Bounded Context. FALSE
  27. The default architecture for enterprise apps Domain Model User Interface

    Query Facade Query Services DTO DTO ORM DB Command Facade Command Services CQRSified
  28. The default architecture for enterprise apps CQRSified User Interface Query

    Facade Query Services DTO DTO ORM DB Command Facade Command Services Domain Model ORM Domain Model Query Facade Query Services ORM Domain Model Query Facade Query Services ORM Domain Model Command and query parts can scale independently, 
 e.g. to accommodate highly asymmetric load.
  29. Assumption 2: Reads and writes use the same data, so

    they must be served from and applied to the same domain model. FALSE
  30. Queries can benefit from a specialized query model, optimized for

    quick data retrieval (de-normalized, pre-aggregated,...) User Interface Query Facade Query Services DTO DTO ORM DB Command Facade Command Services Command Model ORM Domain Model Query Facade Query Services ORM Domain Model Query Facade Query Services ORM Query Model The default architecture for enterprise apps CQRSified
  31. Queries can benefit from a specialized query model, optimized for

    quick data retrieval (de-normalized, pre-aggregated,...) User Interface Query Facade Query Services DTO DTO ORM DB Command Facade Command Services Command Model ORM Domain Model Query Facade Query Services ORM Domain Model Query Facade Query Services ORM Query Model ‣ validate and process commands ‣ keep data consistent ‣ guarantee ACID properties ‣ behaviour part of domain model ‣ relatively difficult to scale out ‣ rich query capabilities ‣ short response times ‣ different views on data ‣ potentially denormalized ‣ relatively easy to scale out The default architecture for enterprise apps CQRSified
  32. Assumption 3: Even for queries, we have to go through

    the domain model to abstract from the underlying database model. FALSE
  33. Query Services Query Services Thin Read Layer User Interface Query

    Facade Query Services DTO DTO ORM DB Command Facade Command Services Command Model Query Facade Query Services Query Facade Query Services SELECT … FROM … WHERE ... Queries are just dealing with data, not with behaviour. 
 What’s the value of having objects then? The default architecture for enterprise apps CQRSified
  34. Query Services Query Services Thin Read Layer User Interface Query

    Facade Query Services DTO DTO ORM DB Command Facade Command Services Command Model Query Facade Query Services Query Facade Query Services SELECT … FROM … WHERE ... Queries are just dealing with data, not with behaviour. 
 What’s the value of having objects then? Introduce thin read layer that makes optimized use of the database’s query capabilities No ORM, no fuss – just plain SQL (SQL happens to be really good at queries, you know...) The default architecture for enterprise apps CQRSified
  35. Assumption 4: We must use the same database for queries

    and commands to make sure that data is consistent. FALSE
  36. In many cases, eventual consistency is sufficient. 
 The data

    users are looking at in the UI is always stale to some extent. Query Services Query Services Thin Read Layer User Interface Query Facade Query Services DTO DTO ORM DB Command Facade Command Services Command Model Query Facade Query Services Query Facade Query Services SELECT … FROM … WHERE ... Query DB Query DB Query DB Event Handler Event Handler Event Handler Events Write The default architecture for enterprise apps CQRSified
  37. In many cases, eventual consistency is sufficient. 
 The data

    users are looking at in the UI is always stale to some extent. Query Services Query Services Thin Read Layer User Interface Query Facade Query Services DTO DTO ORM DB Command Facade Command Services Command Model Query Facade Query Services Query Facade Query Services SELECT … FROM … WHERE ... Query DB Query DB Query DB Event Handler Event Handler Event Handler Events Write Separate query DB, not necessarily relational Command model emits events when data changes Event handlers process events and update query DB asynchronously The default architecture for enterprise apps CQRSified
  38. Assumption 5: Commands must be processed immediately to ensure data

    consistency. FALSE
  39. In many cases, users don’t care if their actions have

    immediate effect – 
 as long as they eventually do (and as long as they get feedback). Query Services Query Services Thin Read Layer User Interface Query Facade Query Services CMD DTO ORM DB Command Facade Command Services Command Model Query Facade Query Services Query Facade Query Services SELECT … FROM … WHERE ... Query DB Query DB Query DB Event Handler Event Handler Event Handler Events Write Command Queue Commands The default architecture for enterprise apps CQRSified
  40. In many cases, users don’t care if their actions have

    immediate effect – 
 as long as they eventually do (and as long as they get feedback). Query Services Query Services Thin Read Layer User Interface Query Facade Query Services CMD DTO ORM DB Command Facade Command Services Command Model Query Facade Query Services Query Facade Query Services SELECT … FROM … WHERE ... Query DB Query DB Query DB Event Handler Event Handler Event Handler Events Write Command Queue Commands Decouple user interaction and command processing Give visual feedback and allow users to check processing progress (and result) The default architecture for enterprise apps CQRSified
  41. Assumption 6: The current state of domain objects must be

    persistent. FALSE
  42. Query Services Query Services Thin Read Layer User Interface Query

    Facade Query Services CMD DTO DB Command Facade Command Services Command Model Query Facade Query Services Query Facade Query Services SELECT … FROM … WHERE ... Query DB Query DB Query DB Event Handler Event Handler Event Handler Events Write Command Queue Commands Processor CQRS plays well with an event sourcing architecture – 
 you just store events and re-create the state of domain objects as needed. The default architecture for enterprise apps CQRSified
  43. Query Services Query Services Thin Read Layer User Interface Query

    Facade Query Services CMD DTO DB Command Facade Command Services Command Model Query Facade Query Services Query Facade Query Services SELECT … FROM … WHERE ... Query DB Query DB Query DB Event Handler Event Handler Event Handler Events Write Command Queue Commands Processor CQRS plays well with an event sourcing architecture – 
 you just store events and re-create the state of domain objects as needed. Events can always be replayed from event store Model is strictly in- memory DB holds events, not state The default architecture for enterprise apps CQRSified
  44. ‣ capture each update to application state in an event

    ‣ a domain object’s state is the result 
 of applying a chain of events ‣ events are immutable ‣ events are a representation of what has happened 
 at a specific time Event Sourcing in a nutshell
  45. ‣ allows you to rebuild application state at any point

    in time just by replaying events from t0 up to that point in time ‣ allows you to analyse historic data based on detailed events that would have been lost otherwise ‣ gives you an audit log “for free” ‣ you can add new, optimized read models (potentially in-memory) later 
 as requirements for new types of queries come up What’s so great about Event Sourcing?
  46. http://www.flickr.com/photos/kaptainkobold/5170454747/ How do I convince my boss that we’ll have

    to rewrite our application with CQRS???
  47. Chances are you don’t.

  48. CQRS is not a silver bullet and doesn’t apply everywhere.

    Beware of the added complexity!
  49. Don’t do CQRS… …if your application is just a simple

    CRUD-style app. …if you don’t have scaling issues. …if it doesn’t help improve your domain models.
  50. Consider doing CQRS… …if your read/write load ratio is highly

    asymmetrical. …if scaling your application is difficult. …if your domain model is bloated by complex domain logic, making queries inefficient. …if you can benefit from event sourcing.
  51. Frameworks, any?

  52. Axon Framework (Java)
 http://ww.axonframework.org Piotr Wyczesany Ncqrs (.NET)
 https://github.com/pjvds/ncqrs Piotr

    Wyczesany …and some more Piotr Wyczesany Jdon (Java)
 http://en.jdon.com Piotr Wyczesany
  53. www.axonframework.org

  54. Apache 2 license Version 2.4 released in January Maintained by

    Trifork Netherlands Commercial support offering available
  55. Distributed Event Bus, based on ‣ JGroup ‣ Disruptor ‣

    AMQP ‣ Spring Integration ‣ File system ‣ JPA ‣ MongoDB ‣ Cassandra ‣ Redis ‣ Google App Engine DataStore Supports both state persistence (via JPA) and event sourcing
  56. ‣ relatively unobtrusive, commands and events are just Java objects

    ‣ Event sourcing is not mandatory, state persistence is still supported ‣ Support for multiple EventBus and EventStore implementations ‣ Integrates nicely with Spring ‣ supports complex business transactions (“sagas” in DDD parlance) Things I like about Axon
  57. ‣ requires some familiarity with DDD terms (you should at

    least know what an Aggregate is) ‣ Axon doesn’t try to hide CQRS from developers – whether this good or bad depends on experience and knowledge about CQRS Things I’m not quite sure about
  58. That’s all I have.
 Feel free to ask me anything!

    @owolf