Facciamo un esempio: abbiamo due entità correlate, come Question
e Choice
. Questo è un sondaggio : contiene una sola domanda che può avere 2 o più scelte . Ogni scelta può essere votata dagli utenti, ogni voto è memorizzato.
Ovviamente, su carta, Question
conterrà una raccolta di Choice
s. E probabilmente avremmo qualcosa di simile:
public class Question {
List<Choice> choices;
public void assignChoice(Choice choice) {}
public List<Choice> getChoices();
}
Question
è un aggregato che contiene un elenco di altre entità , Choice
.
Ora, se Choice
è un oggetto valore, starei bene. Il repository dovrebbe memorizzare l'aggregato a partire da root, in modo da memorizzare un'entità root e oggetti valore correlati.
Tuttavia, qui abbiamo aggregato di entità! In questo senso mi chiedo: perché abbiamo bisogno di mantenere la raccolta in questione ? Voglio dire, per la visualizzazione, avremo il modello di sola lettura della query. Per i comandi potremmo non averne affatto bisogno.
Quindi possiamo spostarci da questo:
Question question = new Question("Favorite color?");
question.assignAnswer(new Choice("red"));
question.assignAnswer(new Choice("blue"));
questionRepository.store(question);
a:
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);
Ora non è necessario "assegnare" nulla a Question
e non è necessario mantenere la raccolta. Ad esempio, questa collezione può variare - può essere raccolta di scelte appena approvate, o scelte votate, o 3 scelte votate più ecc. Non siamo in grado di esprimere quale tipo di relazione è che solo avendo getChoices()
.
Quindi dovremmo andare oltre per avere una regola del tipo:
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.
Ha senso?