Torna a tutti gli episodi
Ep.7 - Event Sourcing e CQRS. Scrivere software basandosi sui "FATTI"

Episodio 7

Ep.7 - Event Sourcing e CQRS. Scrivere software basandosi sui "FATTI"

Contattami a:@brainrepo su twitter o via mail a info@gitbar.itGestire la complessità di un dominio complesso, farlo usando il domain driven design ed ereditare i vantaggi di avere una storia con l'event sourcing. In questa puntata parliamo di come gestire le complessita nel nostro software con DDD, ...

14 febbraio 202000:22:36
DesignAIMusic
7

In Riproduzione

Ep.7 - Event Sourcing e CQRS. Scrivere software basandosi sui "FATTI"

0:000:00

Note dell'Episodio

Contattami a:@brainrepo su twitter o via mail a info@gitbar.itGestire la complessità di un dominio complesso, farlo usando il domain driven design ed ereditare i vantaggi di avere una storia con l'event sourcing. In questa puntata parliamo di come gestire le complessita nel nostro software con DDD, ES e CQRS.Alcuni link utili- [https://community.risingstack.com/event-sourcing-vs-crud/](https://community.risingstack.com/event-sourcing-vs-crud/)- [https://github.com/microsoftarchive/cqrs-journey/blob/master/docs/Reference_04_DeepDive.markdown](https://github.com/microsoftarchive/cqrs-journey/blob/master/docs/Reference_04_DeepDive.markdown)- [https://martinfowler.com/eaaDev/EventSourcing.html](https://martinfowler.com/eaaDev/EventSourcing.html)- [https://www.innoq.com/en/blog/domain-events-versus-event-sourcing/](https://www.innoq.com/en/blog/domain-events-versus-event-sourcing/)Le sigle sono state prodotte da MondoComputazionaleRegistrato negli studi di Radio Nuoro CentraleLe musiche da Blan Kytt - RSPN

Descrizione

Dall'in studio di Radio Neurocentrale (con la voce profonda grazie ai microfoni magici), abbiamo aperto il vaso di Pandora dell'Event Sourcing e del CQRS. Invece di salvare gli stati come nel CRUD, salviamo eventi (fatti accaduti al passato) che raccontano tutta la storia: come una nave che invece di dire "sono qui" registra ogni spostamento. Il risultato? Possiamo ricostruire lo stato in qualunque momento, fare audit, correggere la storia senza pasticciare, e rispondere a domande del business che non avevamo previsto.

Takeaway

  • L'event log è una sequenza immutabile di eventi: le scritture sono solo append, mai distruttive, per cui puoi ricostruire ogni stato passato
  • Gli aggregati (es: ordine + voci ordine) hanno una "porta" chiamata aggregate root che maneggia i comandi, verifica le invarianti (regole di business) e genera eventi
  • Il CQRS separa comandi (write model con logica di business) e query (read model ottimizzato per visualizzazione): le projection generano snapshot dello stato per velocizzare le letture
  • Sistemi con cache delle projection: salvano uno stato intermedio e applicano solo gli eventi successivi, evitando di ricalcolare tutto ogni volta
  • L'event sourcing rende il sistema tollerante alla sincronicità: puoi accodare eventi anche offline senza perdere coerenza

Bold Opinion

  • Correggere la storia aggiungendo un nuovo evento compensativo è infinitamente più pulito che fare UPDATE sul database: non perdi traccia dell'errore e della correzione
  • Il "what if" (cosa sarebbe successo se...) è una killer feature per il business: puoi rieseguire la storia con modifiche e vedere scenari alternativi
  • Il CRUD è più efficiente per dati raw senza semantica di business, ma appena hai logica complessa stai solo duplicando la "source of truth" con tabelle di tracking
  • L'event sourcing è overkill per app semplici tipo "quante uova ci sono nello scaffale", ma per un conto corrente è la scelta naturale

Trascrizione

Benvenuti su GITBAR, il podcast dedicato al mondo dei full stack developer, i mezzo artigiani, i mezzo artisti che ogni giorno infilano le mani nel fango per creare nel modo più efficace possibile quei prodotti digitali che quotidianamente utilizziamo.Settima puntata di GITBAR, io sono BrainRep e stiamo trasmettendo dagli studi di Radio centrale per un'altra puntata, un'altra puntata che ci introduce nel mondo dell'event sourcing.Un saluto infatti a Giovanni che là dietro la regia sta appigiando tutti i bottoni per permettere alla mia voce di arrivare nel miglior modo possibile.Infatti solitamente non sentite una voce con questa profondità.Tranquilli, non è la mia voce, sono le magie dei microfoni della radio.Comunque, torniamo a noi e torniamo ai contenuti che è il motivo per cui questo podcast esiste.Oggi parliamo di event sourcing.Per parlare di event sourcing dobbiamo in qualche modo immaginare una situazione.Abbiamo appena sviluppato il nostro e-commerce, abbiamo il nostro carrello, i nostri prodotti, possiamo inserirli e a quel punto finalizzare l'ordine.Ebbene il nostro sistema va in produzione e dopo qualche settimana veniamo contattati dalla business unit.Business unit che ci chiede la possibilità di avere accesso a tutte le volte che il nostro potenziale cliente inserisce o elimina dei prodotti da carrello.La prima cosa che ci viene in mente è quella di creare una nuova tabella e memorizzare questo tipo di transizioni.Ma la domanda ci deve sorgere spontanea.Lo stiamo facendo nel modo corretto? Beh, uno degli elementi che ci in qualche modo suggeriscono, che ci dicono che non lo stiamo facendo nel modo corretto è che in realtà stiamo duplicando la source of truth, la sorgente della verità.Infatti l'insieme degli inserimenti e delle rimozioni da carrello e lo stato del carrello, quindi l'elemento dei prodotti, sono due verità che noi dobbiamo in qualche modo interpretare all'interno del nostro sistema.Ma la domanda, ripeto, è lo stiamo facendo nel modo corretto? Il paradigma che stiamo utilizzando infatti è il paradigma chiamato CRUD.CRUD sta per create, read, update and delete.Crea, leggi, modifica ed elimina.Questo tipo di paradigma va ad agire sullo stato utilizzando dei pattern chiamati o active record o data mapper.Però la mia domanda è posso farli in un modo diverso? Sì! Il modo diverso per poterlo fare si chiama event sourcing.E come funziona? La base dell'event sourcing sono gli eventi.Gli eventi non sono altro che rappresentazioni di fatti.Vengono descritti al passato e raccontano tutte le modifiche degli elementi di dominio.Elementi di dominio che sono in qualche modo creati e distrutti proprio da questi eventi.Eventi legati alla logica di business.Questi eventi vengono raggruppati in sequenze e vanno a creare l'event log che non è altro come vi dicevo di una serie di eventi.La lettura e l'analisi di questa serie di eventi vanno a creare uno stato.Cosa ci permette di fare questo event log? Beh la prima cosa che ci permette è quella di non perdere stratti e livelli di informazione.Infatti, leggendo gli eventi, tutti gli stati nei tempi che vanno dal primo event all'ultimo vengono memorizzati.Gli stati, infatti, non sono altro che interpretazioni di sequenze di eventi fino a un certo punto.Per cui le letture e le scritture, specialmente scritture all'interno dell'event log non possono e non devono essere distruttive per cui sono accodamenti di event per esempio possiamo immaginare questa situazione siamo all'interno di una nave e noi possiamo agire in due modi o dire io sono qui quindi salvare la posizione e in questo caso io sto salvando uno stati oppure nel mio percorso posso salvare una serie di eventi che possono essere per esempio nella data tale dell'ora tale io mi trovavo in questa posizione e a seguire nella data tale dell'ora tale mi trovavo in quest'altra posizione in questo caso io avrò una serie di eventi questa serie di eventi mi permette di ricostruire l'intera storia per cui mi permette di conoscere lo stato in qualunque istante della barra dei tempi.Un altro concetto importante è quello dell'aggregato.Che cos'è l'aggregato? L'aggregato è rappresentato da una serie di concetti che tendono a raggrupparsi naturalmente per formare delle unità concettuali.Prima parlavamo di unicommerce, l'esempio più semplice è la coppia ordine e voce ordine.Entrambi vanno a creare, a completare il concetto ordine, per cui l'aggregato non è altro che un insieme di classi del nostro dominio che si raggruppano naturalmente e vanno a formare un insieme coeso e consistente dal punto di vista funzionale.E' l'esempio appunto dell'ordine e della voce ordine e eloquente.Naturalmente tutte le modifiche che vanno ad agire all'interno delle classi del nostro aggregato, che siano entità di modello oppure value object, corrispondono a una transazione e la cancellazione di un elemento all'interno dell'aggregato implica la cancellazione di tutti gli altri elementi dello stesso aggregato.Cioè se io vado a cancellare l'aggregato a quel punto cancello tutti gli oggetti che lo compongono.Naturalmente un'altra particolarità dell'aggregato è che può essere trasportato.Questo è particolarmente utile nel momento in cui ragioniamo in termini di architetture distribuite quindi di microservizi cioè l'aggregato può essere in qualche modo compattabile trasferito da una parte all'altra.L'aggregato però ha una porta che si chiama "aggregate root".Questa porta per l'esecuzione di certi comandi e ne gestisce la consistenza.Un aggregato maneggia i comandi e applica gli eventi.Ma a questo punto è importante sapere cosa sono i comandi e cosa sono gli eventi.I comandi sono le azioni, quindi sono tutte quelle azioni che noi possiamo in qualche modo fare verso quell'elemento del dominio per esempio l'ordine noi possiamo creare un ordine possiamo eliminare un ordine possiamo aggiornare un ordine e fino a qua può ritornarci un po l'immagine del crude ma se vi dico che possiamo inoltrare un ordine spedire un ordine oppure possiamo preparare un ordine per la spedizione possiamo annullare un ordine tutte queste informazioni tutti questi comandi vengono passati attraverso l'aggregato root che li trasforma in eventi che poi vengono in qualche modo salvati all'interno del nostro event log e è che in un secondo momento possono essere presi, applicati al nostro aggregato per permettere la verifica delle invarianti.Cosa sono le invarianti? Le invarianti sono le regole di business di un certo aggregato.Vi faccio l'esempio.Io non posso inserire un prodotto nell'ordine se questo ordine è stato annullato.Questo è un invariante.Per verificare se l'ordine è stato annullato io devo leggere tutti gli eventi relativi a quell'ordine applicarli a un certo aggregato e a quel punto posso sapere se quella quell'azione ha consistenza e quindi viene appunto verificata la consistenza.naturalmente tutto il discorso che ho fatto fino a questo punto è strettamente legato al domain driven design infatti quando parlo di aggregato parlo di entità e parlo di questi elementi sto parlando di una rappresentazione del mondo reale in codice quindi dove il mio codice è strettamente legato alla logica di business in realtà però l'event sourcing può anche essere applicato in domini in situazioni dove diciamo la verifica e la generazione degli eventi non è strettamente legata alla logica di business e quindi in contesti non legati a un dominio stringente in quel caso la trasformazione tra comando ed evento viene fatta in qualche modo da una transazione di tipo procedurale.A questo punto il ragionamento da fare è bene io ho una serie di eventi questi eventi mi compongono uno stato nel momento in cui devo applicare un comando lo applica un aggregato che in qualche modo verifica le invarianti caricandosi se ne ha bisogno naturalmente gli eventi e verificando se quell'azione che io sto andando a fare su quell'aggregato è consistente ma fin'ad ora abbiamo parlato di azioni all'interno del dominio ma sappiamo che il nostro sistema ha bisogno anche di letture cioè di accesso all'informazione per avere l'accesso all'informazione dobbiamo scomodare un altro concetto si chiama cqrs command and query responsibility segregation.cosa vuol dire? che i comandi e le query quindi le azioni e le letture hanno due responsabilità differenti e trattano l'aggregato in modo completamente differente.per esempio le query potrebbero non essere strettamente legate alla logica di business perché io voglio un report della lista degli ordini delle dati degli ordini a me dei delle modalità di spedizione di quell'ordine potrebbe in quel caso non interessarmi più di tanto per cui perché devo andare a portarmi dietro una logica di business articolata quando in fase di lettura.Io ho bisogno solo di un'informazione.E se lo stato di quell'elemento è figlio di una serie di eventi la cui lettura, analisi e generazione è complessa perché è figlia di un'applicazione di una serie di eventi ad un certo aggregato, tutto questo si complica.E qui appunto viene in aiuto il CQRS che non fa altro che semplificare la fase di ricalcolo dello Stato, che è un processo particolarmente lento, specialmente quando ci sono un sacco di eventi.A quel punto entra in gioco un concetto che si chiama "projector".Cos'è il projector? Il projector non è altro che un event handler, quindi un maneggiatore di eventi, che non fa altro che andare a leggere gli eventi, creare degli stati, ma che sono strettamente legati alla logica di visualizzazione di lettura che noi abbiamo.Facendo così noi riusciamo ad avere da una parte una serie di comandi strettamente legati alla logica di comando quindi strettamente legati all'azione che sto andando a fare.Dall'altra parte abbiamo invece una serie di dati di stati pensati e strutturati con il concetto della lettura.questo ci è particolarmente utile nel momento in cui le nostre applicazioni diventano complesse certo è un po sovradimensionato se la nostra applicazione è una semplice applicazione di magazzino che ci deve dire quanti quante uova ci sono in quella linea di scaffale però nel momento in cui agisco e sviluppo per esempio un'app del conto corrente beh avere la mia schermata che mi dice il saldo e può essere figlia di un'analisi di una lettura di un'applicazione degli eventi collafata con la finalità appunto di andare a generare quella schermata per cui anche lato user interaction il concetto che sto applicando è completamente diverso.naturalmente cosa fanno le projection? generano delle snapshot quindi generano calcolano e disegnano delle fotografie dello stato a un certo momento.queste snapshot hanno diciamo la generazione di queste snapshot ha un certo come vi posso dire un certo peso un certo costo in termini computazionali e quindi a questo punto entrano in gioco tutta un'altra serie di strumenti che ci semplificano la generazione.Un esempio è per esempio un sistema di cache che ci permette di salvare uno stato a un certo punto, memorizzarlo, ok? memorizzare questa proiezione e a quel punto quando devo rigenerare lo stato in un momento successivo non faccio altro che applicare tutti gli eventi successivi allo stato che ho già generato.In questo caso io ottimizzo la generazione appunto della proiezione.Naturalmente possiamo farlo in background anche perché il fatto che non ci sono modifiche, non ci sono alterazioni di dati, rende il nostro sistema tollerante alla sincronicità per cui io questo questo questo questa generazione di di di di snapshot di proiezione posso farla anche in background e magari dire al nostro utente si non l'ho ancora giornata dammi qualche istante è un po quello che succede con i nostri sistemi bancari no quando vediamo il saldo disponibile sì ma poi vediamo il saldo contabile e non è sempre aggiornato all'ultimo istante questo perché appunto lo stato deve essere generato deve essere generato dalla lettura degli eventi.Quali sono i vantaggi di un sistema che si basa sull'event sourcing? beh è possibile in qualunque momento fare un audit quindi andare a vedere cos'è successo in un dato momento.È possibile anche fare attività di riavvolgimento, chiamiamole così, e anche attività che l'analisi che si chiama "what if", cosa se.Quindi se fosse successo questo cosa ci saremmo trovati? E per esempio più facile capire quale evento ha scatenato una certa situazione.Rende il nostro sistema tollerante al fatto che possa mancare e di apparire la connessione quindi a dei sistemi che sono occasionalmente connessi questo perché non ci può non possiamo perdere la coerenza accodando semplicemente dei dati non andiamo a modificare gli stati per cui il nostro sistema è tollerante alla sincronicità e quindi è anche tollerante alle connessioni asincrone.è possibile correggere la storia quindi io ho una serie di eventi ho sbagliato qualcosa perché il mio sistema ho introdotto un bucco nel mio sistema e mi ha generato un errore in un certo evento esiste un modo semplicissimo per correggere la storia senza pasticciare lo stato così come facciamo quando abbiamo un'applicazione che utilizza il crude per esempio.Posso farlo semplicemente inserendo un altro evento.Questo nuovo evento va in qualche modo a correggere la storia e a riportarmi a uno stato in qualche modo veritiero.Non perdo dati, quindi non perdo situazioni in certi punti del tempo e posso, cosa molto importante, reinterpretare il passato.Ritorniamo al ragionamento che ho fatto prima.Prima ho detto io ho sviluppato il mio e-commerce e poi è arrivato il marketing e mi ha chiesto "Ehi Brain Repo voglio sapere chi inserisce e elimina elementi nel carrello".Se avessi ragionato in ottica di event sourcing applicando l'event sourcing nel mio sistema io avrei potuto rispondere senza nessun tipo di problema alla business unit così come se domani la business unit mi chiede di leggere delle situazioni particolari se io salvo tutti gli eventi io ho una visione ho quasi la registrazione video di quello che è successo e quindi posso a posteriori cercare delle informazioni che invece non potrei trovare nel momento in cui vado o vado a salvare lo stato.naturalmente non tutto viene solo con vantaggi ci sono anche degli svantaggi quali sono? beh senza dubbio il primo è che overkill è per applicazioni semplici cioè il fatto di utilizzare l'event store generare le proiezioni, nel caso le vogliamo generare, le volessimo generare e fare tutte queste azioni, beh, moltiplica le righe di codice e quindi questo se vogliamo fare una semplice applicazione come vi dicevo prima è, non so, in qualche modo sovradimensionato.La seconda è che potrebbe non essere sincrono o comunque per renderlo sincrono abbiamo dei costi perché? Perché gli eventi possono essere tanti e la generazione di uno stato potrebbe richiedere risorse, queste risorse potrei non averle tutte a disposizione quindi questo mi porta in una condizione tale per cui il mio sistema non è sincrono.Quindi in qualche modo esistono dei limiti per esempio il CRUD si dimostra molto più efficiente quando vado a salvare dei dati raw e quindi quando i dati non hanno delle semantiche o dei processi particolari di business e quindi il salvataggio lato crud è molto più semplificato così come più semplificata la ricerca perché perché se io vado a cercare cerco su uno stato solitamente quando faccio una ricerca all'interno della mia applicazione cerco su uno stato dico solitamente perché in realtà mi potreste dire sì vabbè ma io voglio cercare anche sugli eventi vabbè ma se non vuoi cercare sugli eventi solitamente tu vai a cercare su uno stato quando vai a cercare su uno stato tu cerchi su una conseguenza cerchi su una conseguenza questa conseguenza deve essere generata quindi in qualche modo tu devi generare tutta una serie di stati figli di un evento che vuol dire utilizzare delle risorse e questo ha ha dei costi e col crude no non ha dei costi perché tu hai già lo stato stai salvando già lo stato quindi questo questo questo doppio passaggio lo salti e poi naturalmente in questo caso col crude tu hai una serie di indici che ti possono essere utili appunto per velocizzare il processo di ricerca.Bene mi rendo conto che ho buttato tanta carne al fuoco io spero di avervi in qualche modo interessato e introdotto anche un po' in modo un po' caotico nel mondo dell'event sourcing e del cqrs non volevo essere esaustivo ma in qualche modo mi piaceva proprio mettervi la pulce nell'orecchio noi ci sentiamo la prossima settimana ringraziamo Giovanni e tuta Radio Neurocentrale che si sono dimostrati molto disponibili a darci appunto in uso gli studi della radio e nulla l'unica cosa che vi chiedo è quella di se vi fa piacere iscrivetevi al podcast con la vostra applicazione questo è Gitbar dalla settima puntata da Brain Repo è tutto un saluto alla prossima settimana Gitbar il circolo dei full stack developer una volta a settimana ci troviamo davanti a due birre e con Brain Repo parliamo di linguaggi e tecniche di sviluppo web, di metodologie e di strumenti immancabili nella cassetta degli attrezzi dei full stack dev web.!