Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Greenfield Development with CQRS


Published on

It's rare that you get a chance to build an applicaton the way you want to, from the ground up. If you did, what architectural choices would you make and why? Command Query Responsibility Segregation (CQRS) is a hot topic and has been described as crack for architecture addicts. This talk will look at why CQRS may be a good architectural choice for your project, how to use the NCQRS framework, and how this framework can be incorporated with ASP.NET MVC on the front-end and Azure on the back-end. This talk will also focus on the learning curve experienced when implementing an architectural style that bends the curve and is out of the mainstream of traditional application development.

Published in: Technology

Greenfield Development with CQRS

  1. 1. Greenfield Development with CQRS<br />David Hoerster<br />Co-Founder and CTO, BrainCredits<br />
  2. 2. About Me<br />C# MVP (April 2011)<br />Co-Founder of BrainCredits (<br />Senior Technical Director for Resources Global Professionals<br />President of Pittsburgh .NET Users Group<br />Organizer of recent Pittsburgh Code Camps<br />Twitter - @DavidHoerster<br />Blog –<br />Email –<br />
  3. 3. Goals<br />Understanding the CQRS Architecture & Benefits (& Drawbacks)<br />Commands<br />Domain Objects<br />Events<br />Handlers<br />Incorporating into Azure<br />Queues and Blobs<br />Fronting it with MVC<br />
  4. 4. Pre-Requisites<br />Some knowledge and familiarity with Domain Driven Design<br />Some knowledge of Azure objects<br />Some knowledge of ASP.NET MVC<br />Leaving the notion that your data store must be normalized to the Nth degree at the door<br />
  5. 5. Backstory<br />Goals for<br />Fast reads<br />Scalable<br />Handle, potentially, large volumes of requests<br />Be able to change quickly<br />Ability to track user in system and events that occur<br />Easy to deploy, manage<br />Inexpensive (FREE????)<br />
  6. 6. Backstory<br />Decided to jump into cloud with Azure<br />BizSparkcompany<br />Hey, it’s the cloud!<br />Scalability<br />Deployment via VS2010<br />Pretty inexpensive – no HW to manage<br />But how to store data and design system?<br />
  7. 7. Backstory<br />I would recommend to start looking along the CQRS style of architectures<br />- RinatAbdullin<br />Articles by Greg Young, UdiDahan, J. Oliver, R. Abdullin<br />
  8. 8. Traditional ArchitectureIssues<br />Get all of the orders for user “David” in last 30 days<br />
  9. 9. Traditional ArchitectureIssues<br />Get all the orders for user ‘David’ in last 30 days<br />SELECT c.FirstName, c.MiddleName, c.LastName, soh.SalesOrderID, soh.OrderDate,<br />sod.UnitPrice, sod.OrderQty, sod.LineTotal,<br />p.Name as 'ProductName', p.Color, p.ProductNumber,<br />pm.Name as 'ProductModel',<br />pc.Name as 'ProductCategory',<br />pcParent.Name as 'ProductParentCategory'<br />FROM SalesLT.Customer c INNER JOIN SalesLT.SalesOrderHeadersoh<br /> ON c.CustomerID = soh.CustomerID<br /> INNER JOIN SalesLT.SalesOrderDetail sod ON soh.SalesOrderID = sod.SalesOrderID<br /> INNER JOIN SalesLT.Product p ON sod.ProductID = p.ProductID<br /> INNER JOIN SalesLT.ProductModel pm ON p.ProductModelID = pm.ProductModelID<br /> INNER JOIN SalesLT.ProductCategory pc ON p.ProductCategoryID = pc.ProductCategoryID<br /> INNER JOIN SalesLT.ProductCategorypcParent ON pc.ParentProductCategoryID = pcParent.ProductCategoryID<br />WHERE c.FirstName = 'David'<br /> AND soh.OrderDate > (GETDATE()-30)<br />
  10. 10. Traditional ArchitectureIssues<br />Wouldn’t it be great if it was something like?<br />SELECT FirstName, MiddleName, LastName, SalesOrderID, OrderDate,<br />UnitPrice, OrderQty, LineTotal, ProductName, Color, ProductNumber,<br />ProductModel, ProductCategory, ProductParentCategory<br />FROM CustomerSales<br />WHERE FirstName= 'David'<br /> AND OrderDate> (GETDATE()-30)<br />
  11. 11. Traditional ArchitecureIssues<br />It seems that many applications cater to fast C-U-D operations, but the Reads suffer<br />Highly normalized databases<br />Updating a Product Name is easy<br />What would make querying faster?<br />Reducing JOINS<br />Flattening out our model<br />Heresy!<br />Business logic and domain objects bleed through layers as a result, too.<br />
  12. 12. What Alternatives Are There?<br />That’s where CQRS may be an option<br />Provides for fast reads at the ‘expense’ of more expensive writes<br />Once the data is read by the client, it’s already old<br />A system that is eventually consistent is usually acceptable<br />EVENTUAL CONSISTENCY!<br />The read model for the system eventually is consistent with the system events<br />Allows for scalability very easily<br />Even in Azure!<br />Encapsulates business logic in the domain<br />Adheres strictly to CQS<br />
  13. 13. What is CQRS<br />Command Query Responsibility Segregation<br />Based upon Bertrand Meyer’s Command Query Separation principle:<br />“every method should either be a command that performs an action, or a query that returns data to the caller, but not both. In other words, asking a question should not change the answer” (Meyer)<br />In essence, commands return acknowledgement; queries return data.<br />
  14. 14. What is CQRS<br />Recipe of CQRS<br />Healthy serving of CQS<br />Equal parts DDD<br />Some denormalization for seasoning<br />Add Event Sourcing to Taste<br />Optionally Add Dash of NoSQL<br />Optionally A Pinch of Cloud<br />
  15. 15. What is CQRS<br />Taking this further, CQRS describes an architecture where <br />commands are messages (possibly asynchronous)<br />queries go against a read model<br />Since commands are returning void, it allows for the message to be transformed into the read model<br />If we’re transforming the message, why not make the read model as fast as possible?<br />Since we’re transforming the message, perhaps we can take a few extra ticks for additional processing<br />This flips the conventional wisdom of fast writes and slow reads<br />Now we have fast reads and “slower” writes (since we’re writing to a denormalized store)<br />
  16. 16. What is CQRS<br />CQRS essentially splits your application into two parts<br />The Read Side<br />The Command Side<br />The Read Side requests data and receives it<br />The Command Side issues commands (inserts, updates, deletes) and receives just an acknowledgment that it was received.<br />
  17. 17. What is CQRS (Simplified)<br />Client<br />Command Side<br />Query Side<br />Data Requested/Returned<br />Command Issued – ack/nack<br />Repository<br />Command Service<br />Domain (ARs)<br />Event Handler<br />Read Model Store<br />Event Store<br />Denormalizer<br />
  18. 18. Getting Started<br />Steps on the Command Side<br />Command is issued<br />Routed to proper Domain object method<br />Domain raises zero, one or more Events<br />Events handled by Denormalizer to persist data to read model<br />Each step is really one or more messages being sent<br />
  19. 19. Getting Started<br />You can roll your own, or use a framework<br />Several out there, including:<br />NCQRS<br />Lokad.CQRS<br />Agr.CQRS on CodePlex (not much activity)<br />Axon (Java)<br />By using a framework, there are “extras”<br />
  20. 20. CQRS Frameworks<br />With NCQRS (, you get:<br />CQRS support<br />Event Sourcing<br />Support for SQL or NoSQL event sourcing<br />Snapshotting<br />Not always good things<br />If you’re doing ‘pure’ or ‘true’ CQRS, then this is good<br />Otherwise, may be overkill<br />Don’t depend on the framework<br />Let the framework help you, not constrict you<br />
  21. 21. Demo – In Which David Turns To A Life-Long Desire – Buzzword Bingo<br />Demo – BuzzyGo<br />
  22. 22. Command Side Flow<br />Event 1<br />Handler 1<br />Read<br />Model<br />Command<br />Event 2<br />Handler 2<br />Domain<br />Event N<br />Handler N<br />
  23. 23. Commands<br />Simple message from the client to the back-end requesting something to be done<br />Imperative tone<br />CreateUser<br />DeleteCard<br />MarkSquare<br />Contains enough information for the back-end to process the request<br />No return value<br />Maps to Aggregate Root’s constructor or method<br />
  24. 24. Domain<br />Command maps to a AR method/ctor<br />Business logic happens here<br />May assume validation done on client, but can be done here<br />Business rules applied here<br />e.g. FREE space is in the middle and is automatically marked.<br />Once business rules applied, data is added to events that are applied.<br />One or more events can be applied<br />Once event is applied, domain updates itself and is added to the event source repository<br />Not exposed to client, generally<br />
  25. 25. Events<br />Simple messages from domain<br />Similar to commands<br />But not the same<br />Semantically different<br />CardCreated; SquareMarked; CardWon<br />Has enough information for event handler to write information to the read model<br />
  26. 26. Denormalizer (Handler)<br />Handles the events applied by the domain<br />Should NOT perform any validation or business rules<br />Its job is to perform minimal projections and transformations of data and then send that data to the repository/datastore<br />Repository/DataStore being updated is the read model<br />
  27. 27. Read Side Flow<br />Request for Data<br />Read<br />Model<br />Query Provider<br />(Repo/WCFDS/etc)<br />Client<br />Query<br />Results<br />DTO<br />
  28. 28. Where Can I Use CQRS?<br />Windows apps<br />Services<br />Web apps<br />Cloud-based apps<br />Really doesn’t matter<br />Just depends on the problem being solved<br />
  29. 29. CQRS in the Cloud<br />Hosting CQRS in Azure<br />Really no different on the web side than a CQRS web app<br />Typically, you’d want 2 roles<br />Web Role for the UI, which also performs querying<br />Worker Role for the Command handling<br />Both roles can scale out as much as needed<br />Multiple web roles with a single worker role, or vice versa or both!<br />
  30. 30. Communication in theCloud<br />How do I issue commands from my web role?<br />2 typical solutions<br />WCF service on the worker role side<br />Use Azure storage features (blobs, queues, tables)<br />Both have advantages and disadvantages<br />WCF is by default synchronous, so you’ll need to design for fire-and-forget<br />But can be easier to get up and running quickly<br />Azure Storage has a lot of moving pieces<br />Watch out for transaction costs!<br />
  31. 31. Using Azure Storage<br />General flow is this<br />Web role issues a command by dropping it in a blob container (name is GUID).<br />Command blob name is then dropped in a queue<br />Worker role monitors queue for work<br />When it finds a message in the queue, it grabs blob from storage based on id in queue message<br />Deserializes command and then sends it through normal CQRS pipeline<br />
  32. 32. CQRS in the Cloud<br />Blob Storage<br />Queue<br />Controller<br />Command Handler<br />Domain<br />Azure Table Storage<br />Event(s)<br />Repository<br />Denormalizer<br />Read Model<br />
  33. 33. CQRS in the Cloud<br />ASP.NET MVC Controller<br />Reading data is no different, going through a Repository<br />Writing data (issuing commands) involves dropping command into Azure Queue<br />CloudHelper class facilitates this<br />Also provides LogMessage facility<br />
  34. 34. CQRS in the Cloud<br />Using Azure Table Storage for logging user actions…<br />Different than events. Want to know user behavior.<br />Storage is huge – just watch transaction costs<br />Consider batching log reads<br />But you can create replays of user interaction<br />Similar to event sourcing’s replay of events<br />Event sourcing doesn’t capture “Cancels” or “Reads”, which may be useful from a marketing perspective<br />
  35. 35. Claim Credit for thisSession<br />BrainCredits<br />
  36. 36. Resources<br />CQRS InfoSite –<br />NCQRS Site –<br />DDD/CQRS Google Group -<br />UdiDahan’s CQRS article “Clarified CQRS” –<br />RinatAbdullin’s CQRS information –<br />Distributed Podcast -<br />