Super Simple CQRS Example

Under 500 lines of code before the client

http://github.com/gregoryyoung/m-r

 

I will write a blog post about some of the stuff in it but its pretty straight forward.

This entry was posted in Uncategorized. Bookmark the permalink. Follow any comments here with the RSS feed for this post.

28 Responses to Super Simple CQRS Example

  1. Pingback: 04×02 [Screencast] CQRS con Andrea Magnorsky (aka roundcrisis) | 32minutos.net

  2. Van Thoai Nguyen says:

    I’m stupid but couldn’t figure out the QUERY part in the example.
    Event and Command seem to be similar, could someone explain about them?

  3. Pingback: CQRS Examples and Screencasts

  4. Aaron says:

    Greg, thanks for this. I’ve been hearing the theory behind CQRS for so long, but have yet to see a code sample that puts it all together. You rock, man!

  5. mh says:

    I notice in this example the client is responsible for generating inventory-item IDs. How might one go about implementing non-GUID domain-generated IDs? For instance, it would be nice to have a NewInventoryItemCommand(name) that results in an InventoryItemCreatedEvent(id, name) where id is a simple sequentially-assigned integer.

  6. Olav Rask says:

    Great stuff!

    +1 what Ross asked / some more thoughts on eventual consistency

  7. av says:

    inconsequential detail but wondering whats the motivation for constructors on dtos?

  8. Nick says:

    when I add an item and press “Submit” nothing happens, the [HttpPost] Add method isn’t fired.
    I wonder what I’m doing wrong here, theoretically it should just work

  9. Mitch says:

    Greg,

    Seriously awesome post. 2 questions:

    1) I wonder why you chose to implement ICommandSender and IEventPublisher in the same class. They seem like related but ultimately separate concerns.

    2) I wonder how the FakeBus would look like if commands were getting queued to a durable message store for async processing?

  10. Greg,

    I have same question as Ross above – how are you handling this scenario?

  11. Dan Martin says:

    Nice post, thanks!

  12. name says:

    comment

  13. Greg says:

    @Alex you would do a merge … maybe I will implement that in the solution as its not a lot of code and is valuable :)

  14. Alex Simkin says:

    Not sure if my question passed through the “moderation”. How should one change this example to allow for concurrent Check Ins without ConcurrencyException?

  15. Alex Simkin says:

    Now, if I try to check in the same item from different browsers, I get ConcurencyException. What if it is allowed to check in items concurrently (several receivers scan items at the receiving dock for the same order). How would you modify your example to allow for some operations to be executed concurrently?

  16. Sebastian says:

    Thanks a lot Greg.
    Keep the good work :)

  17. Justin says:

    As aspect of CQRS, really more the event sourcing, that I don’t feel entirely comfortable with yet is the versioning of the events. Would you consider doing a post describing how the event versioning works conceptually, or is there already a good break down of this I have missed along the way?

    In your aggregate root, using the AsDynamic().Apply(event) is such a cool idea instead of having the AggregateRoots explicitly register handler methods.

    I think you’ve hit a homerun here with this simple solution as a learning tool for CQRS. There is clearly attention to detail around the “teachable” areas of the solution which is evident even in the way the command handlers are registered in the web application. As someone who would be using an example like this to lead lunch-and-learn discussions I can’t thank you enough for taking the time to do it!

  18. Ross says:

    Hi Greg,

    I added a Thread.Sleep(5000) in the async callback of the publish method on the bus to simulate an eventual consistency scenario. This changes the behavior such that when a user adds an item and gets redirected to the item list page, the user will not see the item that has just been added. If the page were to be refreshed after 5 seconds the user would then see his entry.

    So I guess the question is how would you handle this sort of scenario? I assume that this blog has a similar mechanism which is what is causing Rocco such distress. In my opinion a message to the user is sufficient, but as Rocco has shown it is not always the case. Do you know of any other ways of dealing with these inconsistency issues on the UI?

    To add, Udi Dahan wrote an intersting article on race conditions which could be used to explain how to deal with eventual consistency, http://www.udidahan.com/2010/08/31/race-conditions-dont-exist/?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed:+UdiDahan-TheSoftwareSimplist+(Udi+Dahan+-+The+Software+Simplist)

    And to add even further I am aware that CQRS does not have to be synonymous with eventual consistency, but it is a topic which puzzles me…

  19. @Greg, thanks for this, I have been looking for something like this for some reason my brain can

  20. Ross says:

    Thanks for the post. Have you seen what some guys are doing with the NCQRS framework for .net – http://ncqrs.org/ If you have, do you have any thoughts on it?

    @Roco – chillax man

  21. Functional Illiterate says:

    Great example and at the right time. Recently, I’ve been reviewing Marc Nijhof’s implementation derived from convo’s with yourself. His example is a bit more complicated; this one is, as you stated, super simple(or as simple as it can get).

    So, this example exercises the Command and Eventing aspects of the architecture quite well. But seeing the domain entity, InventoryItem, like this makes my stomach turn a bit. It definitely forces me to think about the domain “entity” much differently…the best way I can describe this model is that it adds a new dimension to the domain entity and makes the DTO/core object/etc–what I normally think of as a domain entity– a projection of that entity.

    A quick question, in this example, the only attributes of the InventoryItem being changed are the Name and Count. If the AggregateRoot had actual child entities/value objects would the Command/Events pass around these core objects or would we see events for each attribute of the child?

  22. Greg, I reviewed this – and really like what you have here.

    Perhaps you could touch on this subject at some point in time:

    small/medium size implementation:

    What sort of project structure would you setup in a small size and then in a medium size implementation?

    In case it’s not clear,I’m thinking from a VS solution/class library.

    Thanks again and I enjoy learning more.

  23. Thanks Greg for posting this – helps to see these examples to get the head around the concepts

  24. David says:

    Thanks for posting this. There aren’t too many DDD (etc) examples floating around, so it’s great to see this.

    I noticed that Commands, Command Handlers and Events are separate from the domain, and that the Domain seems to be aware of Events, but not Commands. (ie, it takes strongly-typed events, but command handlers extract data from commands and pass the data into the appropriate domain methods). Is that something you’d advocate in general?

  25. Greg says:

    Roco I will assume that your first comment was written with about the same amount of thought as the second. You might notice that it says “comments may not appear right away … due to caching, moderation etc”

    If you would like to point out where complexities are I would be happy to discuss them. It is often important to keep in mind that what appears simple on a small scale is very complex on a larger and vice versa.

  26. Roco says:

    Not posting someone’s comment because it doesn’t agree with the author’s style of architecture? Lame!

  27. Scooletz says:

    My favourite class of the example: BullShitDatabase :]

  28. Roco says:

    I’m sorry, but the over-architected nature of this so called “Super Simple” example speaks volumes about CQRS. I fail to see when this would be appropriate for 99% of the readers of this blog.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>