We are converting over a existing system to DDD and are struggling to wrap our head around a few concepts.
We have an aggregate root called Animal
, which has properties such as Status
and Source
. Currently the database has two tables called StatusHistory
and SourceHistory
, which stores information about the animal when the status is changed. These tables sometimes have records deleted, and rarely need to be retrieved when getting an Animal
from the AnimalRepository
.
So the big question is where do they belong? Here are a couple of ideas we have:
Have them both as different entity objects as part of the animal aggregate. And have corresponding methods which allow them to be updated eg: Animal.UpdateStatus(newStatus)
, which would add to the collection with a new StatusHistory(this)
object. But as mentioned above these are rarely required when get an existing animal for the repository, so we don't wan't the repository loading them. We are currently not using an ORM and are manually mapping using a table data gateway inside the repositories.
Make each of the history entities an aggregate root. We are not a fan of this , as it feel like we aren't really modelling the domain and just drifting towards an Active Record Pattern
. Also the task of updating these for the animal with have to lie outside of the animal entity.
We could try combining these histories into another aggregate root called AnimalHistory
whose whole purpose is to maintain the history of the animal. But again it would be moving logic about storing the history into something other then the animal. Possibly a service like AnimalProcessingService
, which feel like we might be heading toward an anemic design.
I'm hoping there is another option which will provide us with a much cleaner design.
This is an interesting article by Martin Fowler recently that might address some of your concerns about not needing some things on retrieval, called Command Query Responsibility Segregation. The basic concept is that you can use a different "model" for "query" (reading) than "command" (saving).
http://martinfowler.com/bliki/CQRS.html
Just because you are doing DDD doesn't mean that everything needs to be contained in proper domain objects. Designing your domain is just as much about design of services and events, etc. My point in saying that is to let your domain come out more naturally by focusing on what the "domain" requires and what the solutions are to deliver those requirements. There is no strict methodology with DDD, it's more of a choice in perspective than a formal design pattern. So having your history objects as entity roots isn't necessarily bad if they are only really used in saving. Have your services related to "commands" compose the correct logic flow for saving animals and histories.
I'd also like to point out that stuff like Animal.UpdateStatus(newStatus)
is quite Active Record-ish, which you seemed like you wanted to avoid.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With