8

I have an entity that is called Master which is composed of a number of Slave entities.

There can only be one Master in my database and I want to query repositories to get the Slave for a given id.

I initially created a SlaveRepository and queried that by id. That seems fine and works and other developers could use my repository.

Then I thought about aggregate roots and created a MasterRepository and returned the Master and then did a loop on that to get the required Slave entity. The problem I felt here is once I expose this to other developers they would have to do the same, so I through about having a method on the MasterRepository called GetSlaveByID(string id) and then I could get the Slave directly (hides the loop functionality).

Now, should my repository return a Slave even though it is called a MasterRepository? And more importantly which is the right way to go?

I am in the early stages of trying to apply DDD and TDD so there are probably lots of things I need to think about before deciding which is the correct way I guess.

2 Answers 2

10

According to Eric Evans way of Domain Driven Design, you should avoid repositories for non aggregate roots.

He clearly states:

Only Aggregate Roots can be obtained directly with database queries. Everything else must be done through traversal.

But it also means, that the repository for the root has to fullfill all requirements. If you need direct access to parts of the aggregate, then an aggregate root object or its repository is responsible for doing so.

So it's perfectly fine to have methods like the following in an aggregate root repository:

Slave GetSlave(string id)

But this signature is a bit dangerous, as identities of children in DDD only make sense in the context of an actual root object and are shallow without the root.

This leads us to a better and more DDD like approach for an implementation in a repository:

Slave GetSlaveOfMaster(Master master, string slaveId)
// or
Slave GetSlaveOfMaster(Identity masterId, Identity slaveId)

But I probably wouldn't even have this method on the repository but on the master entity itself to quickly access the slaves. Possibly even exposed as a hashtable. That's the cleanest approach I can think of.

//within the Master entity
Slave GetSlave(Identity slaveId);

Hold on, this is not the end of the story. If you need to fetch slaves without knowledge of the master, then you should think about your aggregates and your object model. Perhaps you need a second aggregate where the slave is a root and then you should have a custom repository for them. The slave is then not only a child of the master, but a separate hierarchy that probably holds a reference to a master as well. It's important to know whether a slave object can exist without a master at all. If it can, then a separate aggregate is probably the way to go.

5
  • Thank you so very much for all the information. I will try to get hold of Eric's book to understand more.
    – JD01
    Commented Dec 10, 2011 at 16:33
  • you mentioned a second aggregate, is this possible? Are you saying we have master as a root aggregate and also slave in the same model?
    – JD01
    Commented Dec 10, 2011 at 16:37
  • 1
    @JD01: Absolutely. You can have a separate slave aggregate where the slave is the root. This conforms with DDD as long as you keep in mind that only root objects are exposed. That means you cannot have a third class that is not a root and is part of multiple aggregates. But you can have a slave aggregate which is also referenced from the master aggregate as a child. However, this is often where things get complicated (complex relationships etc.). We try to simplify that here by just referencing DTO objects when some root needs to reference another root. DTOs are readonly and cannot be changed.
    – Falcon
    Commented Dec 10, 2011 at 19:36
  • 1
    @JD01: Those DTOs references can of course be exchanged, but the DTOs themselves are immutable. So if I get my SlaveDto from a Master, I cannot change it. When I want to change it I gotta fetch its own aggregate and alter it in there. Those DTOs just contain flat data, no hierarchies and only what is necessary.
    – Falcon
    Commented Dec 10, 2011 at 19:38
  • 1
    @JD01: Also you should ask yourself if a slave can exist without a master. If it cannot, then it is not an aggregate root. See my small update.
    – Falcon
    Commented Dec 10, 2011 at 19:46
2

In general, within the aggregate boundary there should be only one repository. And - as Falcon said - you might end up with two separate aggregates, master and slave.

However looks like the primary focus in your question is data retrieval, while in DDD it should be behavior. Aggregate boundaries are a consequence of constraints imposed by behavior (things that change together and invariants to be enforced), the internal structure of the aggregate is a consequence of that choice.

For example, if you group things correctly according to the need of change together, there's not so much of a need to call an external Repository. Most of the cases, the needed data for a business operation in the Aggregate should already be within the aggregate boundaries, the need to access different aggregates it's probably a smell of an inconsistent boundary.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.