Let's take an example: we have two related entities, like Question
and Choice
. This is a poll: it contains of single question that may have 2 or more choices. Each choice can be voted for by users, each vote is stored.
Obviously, on paper, Question
would contain a collection of Choice
s. And probably we would have something like this:
public class Question {
List<Choice> choices;
public void assignChoice(Choice choice) {}
public List<Choice> getChoices();
}
Question
is an Aggregate that contains list of other entity, Choice
.
Now, if the Choice
is a value object, I would be fine. Repository should store the aggregate starting from root, so it would store a root entity and related value objects.
However, here we have aggregate of entities! In that sense I wonder: why do we need to maintain collection in Question at all? I mean, for view, we will have query read-only model. For commands we might not needed it at all.
So we can move from this:
Question question = new Question("Favorite color?");
question.assignAnswer(new Choice("red"));
question.assignAnswer(new Choice("blue"));
questionRepository.store(question);
to:
Question question = new Question("Favorite color?");
Choice c1 = new Choice(question, "red"); // or just: questionId instead of question?
Choice c2 = new Choice(question, "blue");// the same
questionRepository.store(question);
choiceRepository.store(c1, c2);
Now we do not need to 'assign' anything to the Question
and we don't need to maintain the collection. For example, this collection may vary - it may be collection of just approved choices, or voted choices, or top 3 voted choices etc. We are not able to expressed what kind of relationship is that just by having getChoices()
.
So should we even go further to have a rule like:
Don't compose Aggregates with other Entities. Just have a root Entity and value objects. Use reverse relationship to express the connection between aggregate roots.
Make sense?