DDD: gestori di eventi e aggregati nella programmazione funzionale

0

Quando si implementa un sistema basato su DDD (basato sul sourcing di eventi) utilizzando un linguaggio di programmazione funzionale (Clojure), un gestore di eventi separato dovrebbe funzionare da funzioni di aggregazione?

Nella mia ingenua implementazione un aggregato sarebbe uno spazio dei nomi con

  • funzioni per la gestione di comandi che accettano i dati dello stato corrente + dati di comando e restituiscono i dati dell'evento
  • funzioni per l'applicazione dei dati degli eventi allo stato di aggregati

C'è un motivo per avere ulteriori funzioni del gestore di comandi che ottengono i dati di comando e le funzioni di chiamata nello spazio dei nomi aggregato? Cosa metterebbe in questi gestori e non nel complesso? E perché?

    
posta Witek 01.03.2018 - 20:59
fonte

3 risposte

3

Is there a reason to have additional event handler functions which get the command data and call functions on the aggregate namespace?

Sì. Parte della motivazione per un "modello di dominio" è di avere tutto il codice responsabile per garantire la coerenza dei dati in "uno" posto. Evans descrive le soluzioni nel contesto di un'architettura a tre livelli (applicazione, modello di dominio, persistenza), e scoraggiava il modello anti di perdita dei controlli di coerenza nel livello dell'applicazione.

La coerenza, qui, significa che non possiamo modificare ciecamente i dati come descritto dal comando, ma invece apportare modifiche aggiuntive , se necessario, per garantire che la consistenza complessiva sia mantenuta.

In altre parole, i modelli di dominio sono in genere associati ai servizi, nel senso descritto da Udi Dahan . Se non fossimo interessati a garantire la coerenza dei comandi, rimuoveremo completamente il modello di dominio e gestiremo direttamente il database.

Quindi una firma come

f: CommandData -> Events

in genere non è adeguato, perché nel caso generale è necessario comprendere lo stato corrente per consentire al modello di dominio di calcolare le proprie modifiche.

Consideriamo un modello di dominio di un gioco di tic-tac-toe . Possiamo pensare allo stato del gioco come a una rappresentazione di quali parti della griglia sono occupate da simboli, il cui turno è giocare, se la condizione di vittoria è stata soddisfatta.

Se otteniamo un comando "Gioca una X in posizione centrale", quali eventi emettiamo? E la risposta è "che dipende"; non possiamo sapere quali eventi emettere a meno che non sappiamo già "è il turno di X di giocare?", "la posizione centrale è disponibile?" Le risposte a queste domande dipendono dallo stato del gioco, vale a dire gli eventi che sono già accaduti. Abbiamo bisogno di conoscere lo stato attuale del gioco per mappare "Gioca una X in posizione centrale" sul comportamento corretto.

Pertanto, abbiamo bisogno di una firma analoga a

g: History -> CommandData -> Events

con la cronologia dell'aggregato e i dati di comando utilizzati per calcolare i nuovi eventi.

Vedi anche: A Functional Foundation for CQRS / ES , di Mathias Verraes

    
risposta data 02.03.2018 - 05:13
fonte
1

Non penso che tu stia utilizzando il termine funzione di aggregazione nel suo senso classico.

Un comando è qualcosa che può essere rifiutato. Un evento è un rapporto che qualcosa è successo. Non può essere rifiutato. Solo ignorato. Gli eventi non devono generare eccezioni o restituire valori. Accadono e le cose reagiscono a loro.

La differenza è in qualche modo semantica. Un evento descrive qualcosa nel passato. Un comando descrive qualcosa in futuro. È solo perché la previsione del futuro può essere sbagliata che il comando è quello che può essere rifiutato.

Se qualcosa dovrebbe avere un gestore di eventi è interamente sul fatto che a qualcuno importi che l'evento sia successo. Potrebbe cambiare stato. Potrebbe passare l'evento a qualcos'altro, magari in una forma diversa.

    
risposta data 02.03.2018 - 02:24
fonte
0

C'è un'ambiguità nella tua domanda tra eventi e comandi, specialmente quando dici

functions for handling events which accept the command data

Ma sono davvero due cose separate. Nel dominio, preferisco parlare di gestire un comando, con firma:

eventStream -> command -> event

e che applicano un evento:

currentState -> event -> nextState

Non accadono allo stesso tempo - in realtà, l'applicazione dell'evento non può mai essere chiamata anche se a un certo punto hai accettato il comando! Questo perché l'applicazione evento non si verifica fino a quando non riesegui gli eventi per caricare l'aggregato.

Ora potrebbe esserci un terzo tipo di funzione che non appartiene al Dominio - gestori di eventi nel senso di sottoscrittori . Ricevono l'evento e attivano una serie di effetti collaterali basati su di esso.

    
risposta data 02.03.2018 - 12:04
fonte