Panoramica
Sto cercando di comprendere il modo migliore per collegare Aggregate Roots insieme senza trasferire gran parte della logica di business dalle Entità / AR a Servizi , mentre continui ad aderire al suggerimento di Vaughn Vernon per:
Prefer references to external Aggregates only by their globally unique identity, not by holding a direct object reference (or “pointer”) .....
Dettagli
Prendiamo ad esempio un semplice sistema di ricerca. Questo sistema di ricerca consente agli utenti di eseguire una ricerca indipendente per un cliente contro un elenco di persone sospette.
Permette anche di eseguire Ricerche Batch che è semplicemente una raccolta di Ricerche contro un elenco di Clienti
Ho modellato quanto sopra in questo modo.
Insostanzail
- Cerca
- Ricercabatch
sonoentrambiRootsaggregati.Unaricercapuòessereeseguitainmodoindipendentemapuòancheessereeseguitacomepartediunaricercabatch,nelqualcasolaricercabatchcreataconterràRicerche.
Lacodificaèabbastanzasemplice
class BatchSearch {
constructor(customers) {
this.searches = []
this.customers = customers
}
run() {
for (customer of this.customers) {
const search = new Search(customer)
search.run()
this.searches.push(search)
}
this.markAsCompleted()
}
...
}
Tuttavia, Vaughn Vernon afferma che mantenere un riferimento diretto tra le Radici complessive è un cattivo progetto.
Da, Disegno aggregato efficace Parte II: Aggregazione degli aggregati ":
Prefer references to external Aggregates only by their globally unique identity, not by holding a direct object reference (or “pointer”) ..... Use a Repository or Domain Service (7) to look up dependent objects ahead of invoking the Aggregate behavior
A quanto ho capito, sostiene le interazioni in movimento tra gli Aggregati nei Servizi in questo modo:
class BatchSearchService {
constructor() {
}
createBatchSearch(customers) {
let searches = []
const batchSearch = new BatchSearch()
for (customer of customers) {
const search = new Search(customer)
// We link this Search with this Batch Search by ID only, here
search.setBatchSearchId(batchSearch.getId())
search.run()
searches.push(search)
}
batchSearch.markAsCompleted()
batchSearchRepo.save(batchSearch)
searchRepo.save(searches)
}
}
Questa raccomandazione non porta inevitabilmente a un modello di dominio anemico ?
AFAIK OOP è fondamentalmente l'accoppiamento di dati e operazioni in una classe, ma da quello che ho capito in questo scenario le operazioni vengono spostate dalla classe di ricerca in batch al servizio di ricerca batch invece, lasciando la Classe di ricerca batch solo per contenere i dati