Sto cercando di imparare DDD / CQRS in un progetto di hobby. E non avere precedenti esperienze. In questo progetto utilizzo MongoDb come db di lettura e EventStore come db di scrittura.
Sto costruendo una semplice applicazione 'Sprint board'. (Mi piace JIRA / Asana)
Modello
- Sprint
- Biglietti
Ho deciso di modellarlo come due aggregati separati. Perché volevo mantenere i miei aggregati piccoli e mantenere i 'confini transazionali' il più scalabili possibile. (Riferimento: Vaughn Vernon )
Una delle mie funzionalità che vorrei creare in questo sistema è che uno sprint può essere chiuso solo quando ogni ticket è chiuso.
Mi è sembrato un cattivo progetto caricare ogni ticket in memoria al momento di decidere se uno sprint poteva essere chiuso.
Quindi stavo pensando a un sistema in cui uno sprint tiene traccia della quantità di "biglietti creati" e "biglietti chiusi"
-
CreateTicketCommand (from FrontEnd)
- Crea l'aggregazione del ticket
- Fires TicketCreatedEvent
- Crea l'aggregazione del ticket
-
TicketCreateEvent viene gestito da un
ProcessManager
- Crea un comando AddTicketToSprint
-
Il comando AddedTicketToSprint viene gestito (viene recuperato l'aggregato Sprint)
- TicketId viene aggiunto in un campo di ticket List nell'aggregato sprint.
il tempo passa ...
-
CloseTicketCommand (from FrontEnd)
- Recupera aggregazione ticket + evento Fire TicketStatusChanged
-
TicketStatusChanged viene gestito da un
ProcessManager
- Esegue un comando CloseSprintTicket
-
Commandhanlder - > Recupera aggregato sprint
- Imposta un campo intero 'closedTicketAmount' ++
Ora, quando un oggetto CloseSprintCommand viene attivato da FrontEnd, posso verificare se closedTicketAmount
è uguale alla quantità di ticket nella mia lista di ticket.
Se così non fosse, non dovrei essere in grado di chiudere lo sprint.
Quindi ho ottenuto ogni logica che volevo. Ma mi sembra un po 'sporco. Che cosa succede se in futuro voglio uno stato 'Archivio' sui miei biglietti. Di quanto dovrei controllare (e così via ...)
if (tickets.Count > closedTicketAmount + archivedTicketAmount)
throw new ApplicationException("Sprint cannot be closed when not every ticket is closed");
E si ha la sensazione che sia probabilmente più corretto caricare tutti gli aggregati dei biglietti in memoria attraverso un servizio di dominio. Ma non ho idea di quale sia un buon modello per caricare più aggregati contemporaneamente. (Tranne che per foreach(){ _repository.Get(a.Id)}
)
Mi piacerebbe sentire l'esperienza di altre persone.
Quindi la mia domanda attuale è: Sto pensando in modo completamente sbagliato? Invitando il mio anti-modello. Dovrei semplicemente smettere di pensare e iniziare a leggere più libri.
A proposito:
- Ho ordinato il "libro rosso di DDD". Forse questo mi darà ulteriori informazioni su problemi correlati.
- Questa non è una domanda in cui sono bloccato nei miei compiti / lavoro. Il codice non finito corrente è open-source.
Cordialmente, Brecht