I’ve just spent the day implementing a very simple system to convert numbers to words. I’ve used the CQS pattern, and domain driven design constructs, TDD, and lots of other good stuff. I’ll upload the code to github tomorrow, probably, and you can see it. I did this because my client needs an introduction to this approach.
After implementing the system I thought I’d take a look at some cqrs frameworks, to see if they’d actually make my life easier. Of the bunch, Axon is probably the best at the moment, but it isn’t a framework so much as a tool. The difference is that a framework isn’t referenced from your code, but a tool is, and your code has to interact quite strongly with Axon. I’ve knocked up an approach to using axon that uses compile-time-weaving of aspectj advice onto my domain model in order to provide the interaction with the event bus, but because of the way the framework is implemented I’m having trouble removing it’s dependence on inheritance, so for now I’m going to use the framework raw.
To be clear, I’m only really complaining about the intrusion of the framework into the domain model. Anywhere else and I’m fine with it, but I like the domain model to consist purely of pojos, which makes it cleaner, easier to read and understand, easier to maintain, and more reusable.
Thanks to Vaughn Vernon’s excellent book on DDD I have recently come to appreciate referencing objects by id, so I’m willing to accept an ID as a necessary evil within some domain objects, but deep down I’m still not convinced — I prefer to directly reference objects in a simple navigable way, but I’m willing to accept that a lot of problems are solved if you use an ID as a reference, rather than a direct reference.
I grow concerned when I hear people talking about injecting repositories into domain objects. It’s bad enough that some people annotate them with jpa annotations (see how far that gets you when you have to write your objects to two different database schema simultaneously). In CQRS you have at least two persistence mechanisms. The first is the event source, which stores the business events generated by your model. The second is the query-side database, which I am calling the reporting database. The reporting database is structured to meet the specific needs of agents at the periphery of your domain model (most often, a GUI). This database is populated in response to business events. Note that the event source is not a mapping of you domain model to the DB, and neither is the reporting database. Your domain model doesn’t map to a database (typically).
Perhaps the domain itself should be persisted? But, a 3NF DB schema should not be dictating the structure of your domain model. We’re doing OO, our modeling capabilities are constantly hamstrung by the constraints of mapping to a relational db. You could use something to generate storage objects to store, and have something capable of restoring the domain from the storage objects, but most event sourcing frameworks are capable of doing that through simply replaying the event source, so why would you bother?