I'm having my first attempt at DDD and I'm running into a problem with aggregate design.
My application contains 3 Entities; Graph, Node, Link. Each of these entities has a name property which can be modified by the user (which I believe makes 'name' unsuitable as an Entity id). A Graph contains a collection of Nodes and a Node has a collection of outgoing Links (for the purpose of this problem it is safe to ignore incoming links). Each Node can only be associated with one Graph at a time (but can be moved between Graphs) and similarly, each Link can only be associated with one Node at any given time (but can be moved).
The invariant(s) I am attempting to enforce is that all Entity names are unique within their parent collection. With the architecture described above, the invariant is on the actual collections, so I decided that the collection owners (Graph and Node) should both be Aggregate Roots.
The problem I have is how do I now enforce the name invariant on Node? On Link it is easy since it is hidden away inside the Node AR and as such Node can confirm that all Link renames/moves do not break this invariant. But as far as I can see, there is nothing to prevent a direct rename of Node which could break the invariant. Eventual consistency is not an acceptable option here, this must be a true system invariant.
The approach I am considering is to have Node.Rename() actually enforce the invariant, but my concern is that this involves looking inside its parent Graph to check if the rename is valid. This doesn't 'feel' right - it feels like the Graph should be the one to enforce this namespacing constraint and that Node should know nothing about it at all.
I hope this makes sense, and I look forward to hearing peoples thoughts.
Edit: The Domain Model presented above is a simplified subset of the entire Domain. Too complex for all entities to be held within a single AR.......
Graph
as one AR seems the way to go. If you useGraph
as the only AR though, how large can it grow, and how much concurrency do you expect? – Kinslow