How Add/Create* commands should be handled in CQRS + Event Sourcing architecture

cqrsdomain-driven-designevent-sourcingrepository

I want to implement my first application using CQRS pattern along with Event Sourcing. I am wondering how creation of aggregate roots should be handled properly. Let's say someone sends CreateItem command. How it should be handled? Where the event ItemCreated should be stored? As first event of a new Item? Or should I have some kind of ItemList entity that aggregates all items and its event list consists only of ItemCreated events?

Udi Dahan suggests not to create aggregate roots and always use instead some kind of fetch method. But how I can fetch something that is new and certainly does not have any ID assigned. I understand the idea behind and it is pretty reasonable to think that a new object is an object that has its state composed of zero events replied on it. But how should I use it? Should I have a distinct method in my Repository like getNewItem() or make my get(id) method accepting Optional<ItemId> instead?

Edit: After some time of digging I found really interesting implementation of the aforementioned patterns using actors. The author instead of creating the aggregate, retrieves it from some kind of repository with newly created UUID. The drawback of this approach is he allows for a temporary inconsistency state. I am also wondering how I can implement delete method with such approach. Simply add Deleted event to the event list of the aggregate?

Best Answer

The idea in Udi's post, as I gather, is that no kind of item appears out of thin air. There is (almost) always something, or more specifically, some domain operation, which caused the item to be created. Just like Udi's example of a user actually being born out of a visitor registering to the site. At that point and at that bounded context Visitor is the aggregate root, which is retrieved by his IP address. This Visitor then creates the new "item", a user at this point, through a domain operation called Register. Same goes for the step before, which is another bounded context: Referrer is the AR, which is retrieved by the URL and that has a domain operation called BroughtVisitorWithIp, where the visitor is born.

Udi writes very nicely on deletion as well: http://www.udidahan.com/2009/09/01/dont-delete-just-dont/. Main idea is, that you don't delete anything, ever. There's always a domain operation behind, which we want to capture. Like an order being cancelled, rather than deleted. Read it, it's a very good post.

The main point here on both accounts, doing DDD and especially Event Sourcing, is that you should never do straight CRUD-operations. If you find yourself in a situation where you really need to just insert, update or delete some data, and there truly is no domain operation behind it, then maybe DDD and Event Sourcing is not a good fit for that bounded context. You are free to combine these two as you wish as long as a single bounded context adheres to one principle. This way the CRUD-style bounded context might create some row in the database, that becomes an entity and an Aggregate root in another bounded context, where you now can retrieve the AR and not have to create it.

Related Topic