Event sourcing: applicazione degli eventi prima che il cambiamento sia completato?

6

Quindi ho radice Aggregate che ha alcune sub-entità con alcuni oggetti di sotto-valore (design classico DDD). Volevo anche utilizzare il sourcing di eventi nella progettazione di aggregati. Nel livello AppService ricevo il comando, lo decodifico e il metodo di chiamata sull'aggregato (ho capito che questa è una pratica comune in ES):

public class AgRoot {

    private Int id;
    private List<SomeValueObj> objs;

    public void doSmthn(SomeValueObj arg){
        //check if arg (some logic) can be applied to this aggregate
        for(SomeValueObj o : objs){
            if(!o.canBeUpdatedWith(arg)){ throw Exception(); }
        }
        GenEvent event = constructeventfrom(arg);
        this.causes(event);
    }

    public void when(GenEvent event){
       //set all fields in this aggregate
       for(SomeValueObj o : event.objs){
            o.applyChangeActually(o)
        }
    }

}

Ora, la mia domanda è: perché qui dobbiamo verificare se questo argomento può essere applicato, quindi creare un evento e solo allora applichiamo effettivamente le modifiche (scriviamo fondamentalmente i valori dei dati sull'oggetto). Sembra che stiamo separando la parte in cui controlliamo se il contenuto di arg è valido e può essere applicato da una parte in cui vengono effettivamente copiati valori da arg per aggiornare lo stato dell'oggetto. Nel DDD standard senza ES, passerei solo arg giù il grafico degli oggetti agli oggetti lista objs: essi gestivano tutti i controlli e gli aggiornamenti da soli.

Ho frainteso il concetto di ES?

Aggiorna

Giusto per chiarire un po 'di più: se non devo solo fare dei semplici controlli come se arg! = null (che è la cosa normale che hanno tutti gli esempi ES) - ad es. prima di aggiornare ogni SomeValueObj nell'elenco obj, devo eseguire costosi calcoli e molta logica in ognuno degli oggetti objs - e possibilmente aggiornare parzialmente questi oggetti con nuovi dati per procedere con i calcoli - sembra che quando la funzione (GenEvent event) teoricamente fai ancora la stessa cosa ?? Mi sembra il problema dell'uovo di gallina.

Questa sembra la cosa di cui sto parlando Strutture complesse di aggregazione

    
posta bojanv55 20.12.2016 - 16:15
fonte

1 risposta

2

Now, my question is: why we here have to check if this arg can be applied, then create event and only then we actually apply changes (write basically data values to object).

Il motivo principale: farlo in questo modo garantisce che i contenuti dell'evento e lo stato dell'aggregato rimangano sincronizzati.

In molti casi, semplicemente copia lo stato dall'evento all'entità in memoria e la distinzione non ha molto senso. Ma nel caso più generale, lo stato dell'entità viene derivato dallo stato nell'evento e si desidera assicurarsi di eseguire il calcolo la seconda volta (quando si ricarica l'aggregato dalla sua cronologia) esattamente allo stesso modo che hai fatto la prima volta Il modo più semplice per garantire che ciò accada è utilizzare lo stesso percorso di codice in entrambi i casi.

Se vuoi, puoi pensare all'azione che si svolge in due parti

  • calcola l'evento (questa è una query, il calcolo non cambia affatto lo stato dell'aggregato)
  • applica l'evento (questo è un comando, che non sposta l'entità dallo stato corrente al suo stato successivo).

Quindi prendere in giro queste due azioni è coerente con il principio di Meyer la separazione delle query del comando .

This looks like the thing I'm talking bout Complex Aggregate Structures

Yup.

Trovo che mantenere l'evento che calcola la query separata dall'applicazione di quegli eventi aiuta a mantenere sotto controllo la complessità delle modifiche: nella fase di interrogazione, ogni entità unisce i propri eventi con quelli delle entità subordinate e bolle quelli verso l'alto verso la radice, che a sua volta li spingerà verso il basso sul lato di comando del grafico dell'oggetto.

    
risposta data 20.12.2016 - 18:42
fonte

Leggi altre domande sui tag