DDD - Il repository di una radice aggregata gestisce il salvataggio di aggregati?


27

Sto usando un approccio simile a DDD per un modulo greenfield di un'applicazione esistente; non è DDD al 100% a causa dell'architettura ma sto cercando di usare alcuni concetti DDD. Ho un contesto limitato (penso che sia il termine corretto - sto ancora imparando a conoscere DDD) costituito da due Entità: Conversatione Message. La conversazione è la radice, poiché un messaggio non esiste senza la conversazione e tutti i messaggi nel sistema fanno parte di una conversazione.

Ho una ConversationRepositoryclasse (anche se è molto più simile a un gateway, uso il termine "repository") che trova le conversazioni nel database; quando trova una conversazione crea anche (tramite Fabbriche) un elenco di messaggi per quella conversazione (esposto come proprietà). Questo sembra essere il modo corretto di gestire le cose in quanto non sembra esserci la necessità di una MessageRepositoryclasse completa in quanto esiste solo quando viene recuperata una conversazione.

Tuttavia, quando si tratta di salvare un messaggio, è questa la responsabilità del ConversationRepository, poiché è la radice aggregata di Message? Voglio dire, dovrei avere un metodo su ConversationRepository chiamato, diciamo, AddMessageche prende un messaggio come parametro e lo salva nel database? O dovrei avere un repository separato per trovare / salvare i messaggi? La cosa logica sembra essere un repository per Entity, ma ho anche sentito "Un repository per Context".

Risposte:


25

Il libro blu merita sicuramente una lettura se vuoi ottenere il meglio dall'approccio DDD. I pattern DDD non sono banali e apprendere l'essenza di ognuno di essi ti aiuterà a riflettere su quando usare quale pattern, come dividere l'applicazione in layer, come definire i tuoi aggregati e così via.

Il gruppo di 2 entità che stai citando non è un contesto limitato, probabilmente è un aggregato. Ogni aggregato ha una radice aggregata, un'entità che funge da punto di accesso singolo all'aggregato per tutti gli altri oggetti. Quindi nessuna relazione diretta tra un'entità e un'altra entità in un altro aggregato che non è la radice aggregata.

I repository sono necessari per acquisire entità che non sono facilmente ottenibili attraverso l'attraversamento di altri oggetti. I repository di solito contengono root aggregati, ma possono esserci anche repository di entità regolari.

Nel tuo esempio, Conversation sembra essere la radice aggregata. Forse le conversazioni sono il punto di partenza della tua applicazione, o forse vuoi interrogarle con criteri dettagliati in modo che non siano accessibili in modo soddisfacente attraverso il semplice attraversamento di altri oggetti. In tal caso, è possibile creare un Repository per loro che fornirà al codice client l'illusione di una serie di conversazioni in memoria da cui eseguire query, aggiungere o eliminare direttamente. D'altra parte, i messaggi sono facilmente ottenuti dall'attraversamento di una conversazione e potresti non volerli ottenere in base a criteri dettagliati, solo tutti i messaggi di una conversazione contemporaneamente, quindi potrebbero non aver bisogno di un repository.

ConversationRepository svolgerà un ruolo nel persistere dei messaggi, ma non un ruolo così diretto come menzionato. Quindi, nessun AddMessage () su ConversationRepository (quel metodo appartiene piuttosto alla Conversazione stessa) ma invece, ogni volta che il Repository persisterà una Conversazione, è una buona idea persistere i suoi Messaggi allo stesso tempo, sia in modo trasparente se usi un framework ORM come (N) ibernazione, utilizzando SQL ad hoc se lo si sceglie, ecc.


1
Se una radice aggregata, come Conversation, contiene al suo interno molti diversi tipi di entità, come Message, Thingies e Wingies, quindi quando salvi una conversazione, ad esempio ConversationRepo.save (conversazione), come fai a sapere quali entità al suo interno hanno bisogno essere salvato? Nell'esempio di poster sopra, è necessario salvare solo le entità messaggio. Attraversi tutte le possibili raccolte all'interno della radice aggregata per trovare entità senza ID?
chris-richards,

3

È possibile creare ConversationService e iniettare IConversationRepository e IMessageRepository nel relativo costruttore. Usa repository per semplici operazioni CRUD e servizi per tutto il resto (memorizzazione nella cache, logica di salvataggio, ecc.)


1
non sta salvando la logica CRUD?
Timothy Groote,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.