Comandi / transazioni interaggregati in modo coerente

1

Sto cercando di modellare una transazione commerciale che opera su due aggregati. Diciamo che abbiamo un tipo di aggregazione Bag che contiene elementi (entità). Mi piacerebbe avere un comando TransferItemToBag (itemName: String, fromBag: BagId, toBag: BagId) che estrae un oggetto dal primo Bag e lo mette al secondo. Quando viene ricevuto questo comando, voglio inviare un comando AddItemToBag (...) al secondo sacchetto e quando risponde con ItemAddedToBag (...) invia RemoveItemFromBag (...).

In altre parole, mi piacerebbe creare un comando nel sistema che faccia ciò che l'utente può fare con gli altri due comandi, inviandoli uno per uno. Pseudocodice:

on(FirstSecondCombinedCommand cmd) {
   eventBus.register(eventType=FirstEvent, {
       aggregate = repository.ofId(cmd.id2)
       aggregate.handle(SecondCommand(...))
   })

   aggregate = repository.ofId(cmd.id1)
   aggregate.handle(FirstCommand(...))   // produces FirstEvent
}

A chi appartiene questa logica? Si prega di notare che non voglio avere una consistenza strong, piuttosto quella finale. Sto anche bene se la transazione è interrotta perché c'era un diverso comando in competizione tra quello che arrivava a uno degli aggregati. Ho preso in considerazione diverse possibilità:

  • Aggregato - il comando riguarda solo un singolo tipo di aggregazione, quindi la regola empirica per la scelta di un luogo per una logica di business (servizio aggregato / entità vs dominio) mi suggerisce di andare con quello. D'altra parte significa che il gestore di comandi nell'aggregato deve essere in grado di produrre comandi. Può violare una regola di singola mutazione aggregata all'interno di una transazione / comando, ma cosa accadrebbe se fosse eseguita in modo asincrono per evitarlo? Intendo postare il comando su una sorta di Command Bus e lasciarlo spedire in seguito, magari con un thread diverso.
  • Saga - la situazione è in realtà una sorta di (lungo) processo in corso e questo mi ha fatto pensare a Sagas per l'implementazione. D'altra parte ho sempre considerato Sagas come qualcosa di stato. Non vedo uno stato esplicito nella mia situazione.
  • Application Service - Ho visto in IDDD che è un posto dove impostare gli ascoltatori e invocare vari comandi, ma la situazione che sto descrivendo fa parte di una logica di business per me e vorrei mantenerla nel dominio .
  • Domain Service - l'ultima possibilità a cui riesco a pensare. Sembra essere un posto ragionevole per cose interglobettotype, ma cosa succede se abbiamo lo stesso tipo di aggregazione?

Per favore non concentrarti su questo esempio concreto di aggregati (è stato ideato). Sono interessato a una risposta generica in cui inserire tale codice "transazione".

    
posta Mequrel 30.10.2014 - 15:34
fonte

1 risposta

2

Non ti piacerà la risposta. Dipende. Nel caso della tua transazione semplice, potresti anche consentire agli Aggregati di interagire insieme.

Ma se è possibile che le interazioni coinvolgano un numero di aggregati (e quindi un numero di comandi ed eventi), la soluzione migliore sarebbe utilizzare una Saga. Ciò consente di mantenere il processo in un'unica posizione, rendendo più semplice l'aggiornamento del flusso di lavoro in caso di necessità. Ciò renderebbe anche più semplice seguire il flusso di lavoro invece di doverlo rintracciare tra diversi aggregati. Microsoft ha lavorato con un sacco di luminari all'interno della comunità DDD / CQRS per creare un bel progetto di approccio, la loro discussione su sagas vale la pena di leggere (che si rinomina process manager).

    
risposta data 30.10.2014 - 23:21
fonte

Leggi altre domande sui tag