Se puoi ricavarlo, non salvarlo

Da qualche parte, nella maggior parte dei sistemi aziendali, c'è un numero di cui non si fida nessuno. Lo stock in magazzino. Il saldo di un conto. I punti accumulati. I posti occupati. Di solito è una colonna in cui scrive il codice, e verso il secondo anno è sbagliata da qualche parte e nessuno sa dire quando è andata storta o perché.

La soluzione non è una validazione migliore. È smettere di conservarlo.

Conservato contro derivato

Un totale conservato è un'affermazione. Qualcosa l'ha calcolato una volta e l'ha scritto, e da quell'istante può allontanarsi dagli eventi che l'hanno prodotto - un retry applicato due volte, una transazione fallita a metà, una correzione manuale in buona fede, una race condition tra due richieste.

Un totale derivato è una domanda posta agli eventi stessi. Non ha modo di allontanarsi, perché non esiste niente di separato da cui allontanarsi. Chiedi di nuovo e ricevi la risposta di oggi dai fatti di oggi.

Come si presenta nella pratica

Invece di una colonna quantity, tieni una tabella di movimenti: ciascuno con segno, immutabile, con chi l'ha fatto, quando e su quale riferimento. Lo stock di un magazzino è la somma dei movimenti che lo toccano. Una correzione è un movimento nuovo in senso inverso, mai una modifica.

Tre cose ne seguono immediatamente, e sono il guadagno vero:

  • La riconciliazione smette di essere un compito. Il saldo e la sua spiegazione sono lo stesso oggetto, quindi non possono contraddirsi. Non esiste più l'esercizio mensile di trovare dove il numero è andato storto.
  • "Perché ne abbiamo undici?" ha sempre una risposta. Non di solito. Sempre. Lo storico completo è il numero.
  • L'undo diventa sicuro. Aggiungere l'inverso lascia intatta la traccia di audit, mentre cancellare l'originale distrugge la prova di quello che è successo.

C'è una piccola versione funzionante dell'idea nel caso studio delle cliniche - registra un movimento e guarda i totali ricalcolarsi dal log, senza che niente, da nessuna parte, conservi una quantità.

L'obiezione, e la risposta onesta

"Sommare ogni movimento a ogni lettura sarà lento."

Di solito non lo è. Qualche migliaio di movimenti non significa niente per un database con l'indice giusto, e la maggior parte dei sistemi che se ne preoccupano ha molte meno righe di quante ne immaginino i loro autori.

Quando diventa davvero lento, la risposta è uno snapshot periodico - una riga di checkpoint che dice "a questa data il saldo era X" - e derivi in avanti dal più recente. Quella è una cache, ed è sicura proprio perché si può ricostruire: cancella tutti gli snapshot e il sistema sa ancora tutte le risposte giuste. Nel momento in cui non lo puoi più ricostruire dagli eventi, si torna a conservare, e ti ritrovi con il problema iniziale, più un po' di meccanica in più.

Dove non usarlo

È per le cose che si contano e che devono poter essere spiegate. È inutile per una preferenza di visualizzazione, per una bozza o per qualsiasi cosa in cui il valore corrente è l'unica cosa a cui qualcuno terrà mai. L'event sourcing per il tema scelto da un utente non è rigore, è cerimonia.

Decidere quale delle due categorie sia un certo numero avviene durante la discovery, non durante la costruzione - ed è in parte per questo che il primo prezzo che ti danno è di solito sbagliato. È l'argomento della nota su quanto costa davvero una piattaforma.