Dacă îl poți deriva, nu-l stoca

Undeva în majoritatea sistemelor de business există un număr în care nu are nimeni încredere. Stocul din depozit. Soldul unui cont. Punctele acumulate. Locurile ocupate. De obicei e o coloană în care scrie codul, iar prin al doilea an e greșită pe undeva și nimeni nu poate spune când a luat-o razna sau de ce.

Rezolvarea nu e o validare mai bună. E să nu-l mai stochezi.

Stocat față de derivat

Un total stocat e o afirmație. Ceva l-a calculat o dată și l-a scris, iar din clipa aia poate să se depărteze de evenimentele care l-au produs - un retry aplicat de două ori, o tranzacție care a eșuat pe jumătate, o corecție manuală bine intenționată, un race între două cereri.

Un total derivat e o întrebare pusă chiar evenimentelor. Nu are cum să se depărteze, pentru că nu există nimic separat de care să se depărteze. Întrebi din nou și primești răspunsul de azi din faptele de azi.

Cum arată asta în practică

În loc de o coloană quantity, ții un tabel de mișcări: fiecare cu semn, imutabilă, cu cine a făcut-o, când și pe ce referință. Stocul unui depozit e suma mișcărilor care îl ating. O corecție e o mișcare nouă în sens invers, niciodată o editare.

Trei lucruri urmează imediat, și ele sunt câștigul real:

  • Reconcilierea încetează să fie o sarcină. Soldul și explicația lui sunt același obiect, deci nu au cum să se contrazică. Nu mai există exercițiul lunar de a găsi unde a luat-o numărul razna.
  • „De ce avem unsprezece?” are mereu răspuns. Nu de obicei. Mereu. Istoricul complet e numărul.
  • Undo devine sigur. Adăugarea inversului lasă traseul de audit intact, în timp ce ștergerea originalului distruge dovada a ceea ce s-a întâmplat.

Există o mică versiune funcțională a ideii pe studiul de caz al clinicilor - postează o mișcare și uită-te cum se recalculează totalurile din log, fără ca nimic, nicăieri, să stocheze o cantitate.

Obiecția, și răspunsul cinstit

„Să aduni fiecare mișcare la fiecare citire o să fie lent.”

De obicei nu e. Câteva mii de mișcări nu înseamnă nimic pentru o bază de date cu indexul potrivit, iar majoritatea sistemelor care își fac griji pentru asta au mult mai puține rânduri decât își imaginează autorii lor.

Când chiar devine lent, răspunsul e un snapshot periodic - un rând de checkpoint care spune „la data asta soldul era X” - și derivezi mai departe de la cel mai recent. Ăsta e un cache, și e sigur tocmai pentru că se poate reconstrui: șterge toate snapshot-urile și sistemul tot știe toate răspunsurile corecte. În clipa în care nu-l mai poți reconstrui din evenimente, te-ai întors la stocare, și ai din nou problema inițială, plus niște mecanică în plus.

Unde să nu folosești asta

E pentru lucruri care se numără și care trebuie să poată fi explicate. E inutil pentru o preferință de afișare, pentru o ciornă sau pentru orice unde valoarea curentă e singurul lucru de care îi va păsa vreodată cuiva. Event-sourcing pentru tema aleasă de un utilizator nu e rigoare, e ceremonie.

Care dintre cele două e un anumit număr se decide în discovery, nu în timpul construcției - și ăsta e unul dintre motivele pentru care primul preț pe care ți-l dă cineva e de obicei greșit. Despre asta e nota despre cât costă de fapt o platformă.