Immagina di progettare un'applicazione per organizzare seminari. Lo stesso workshop è piuttosto complicato: agisce come una macchina a stati con più stati possibili e transizioni tra di essi.
Utilizziamo DDD, CQRS e Event Sourcing.
E ora, i casi d'uso:
1) si dovrebbe essere in grado di assegnare TodoItem ad un Workshop ed eseguire su di essi operazioni CRUD
2) si dovrebbe essere in grado di inviare risorse aggiuntive per un determinato workshop (diapositive, foto, archivi zip / tar.gz ecc.) ed eseguire anche operazioni CRUD su di esse
3) si dovrebbe essere in grado di aggiungere un PossibleTerm (con un Docente, una Data e una Stanza specificati) ad un Workshop. Inoltre, dovrebbe esserci un modo per modificarli / eliminarli.
Più tardi c'è una votazione su questi termini, il sistema cerca di prenotare una stanza per pochi termini (diciamo, per due termini) che ha vinto Voto e utenti dovrebbero essere divisi tra questi Termini.
Ecco le seguenti soluzioni:
1) Modello TodoItems, Resources e PossibleTerms come parte di un Workshop.
Pro:
- tutto è dove concettualmente appartiene a
- nessuna consistenza finale (probabilmente non un grosso problema ...)
Contro:
- Gli aggregati di workshop sono ingombri di tutti quei metodi CRUD per tutte le cose.
- Secondo Implementing Domain Driven Design di Vaughn Vernon, la creazione di enormi radici aggregate è un antipattern
2) Crea radici aggregate per contenere tutti quegli "articoli" (ad esempio TodoItemList, PossibleTermList, Resources o qualsiasi altra cosa li chiamerai).
Pro:
- L'aggregato del seminario è più piccolo, non è correlato a tali elenchi (l'unica connessione sarebbe che ad esempio PossibleTermList abbia un riferimento a WorkshopId)
Contro:
- quando arriva CreateWorkshopCommand, sei costretto a creare non solo un workshop, ma anche aggregati aggiuntivi che devono esistere dopo la creazione del workshop. Per evitare questo, potrebbe esserci qualche tipo di CreationSaga, ascoltare WorkshopCreatedEvent e produrre comandi appropriati per creare parenti, ma non penso che sia una buona idea.
3) Model PossibleTerms, Resource, TodoItem as aggregate roots stesso
Pro:
- nessuna necessità di creare 'aggregati wrappers' (come in 2))
Contro:
- di nuovo, stai ingombrando Workshop con almeno i metodi di fabbrica
- è difficile per me implementare funzionalità di scelta del termine - per il conteggio dei voti e in seguito assegnando l'utente a un determinato termine è necessario interrogare il repository per tutti i termini che corrispondono all'ID del workshop e così via - questo porta a operazioni su più aggregati all'interno di una transazione.
Domanda: quale soluzione suona meglio per te? Forse hai idee diverse?
(domanda bonus: ho bisogno di eseguire operazioni CRUD su singole risorse / TodoItem, preferisco modellare come oggetti valore, ma come vengono identificati?)