Si vous pouvez le calculer, ne le stockez pas

Quelque part dans la plupart des systèmes de gestion il y a un nombre auquel personne ne fait confiance. Le stock disponible. Le solde d'un compte. Les points accumulés. Les postes utilisés. C'est en général une colonne dans laquelle le code écrit, et à la deuxième année elle est fausse quelque part, et personne ne peut dire quand elle est devenue fausse ni pourquoi.

La solution n'est pas une meilleure validation. C'est d'arrêter de le stocker.

Stocké ou dérivé

Un total stocké est une affirmation. Quelque chose l'a calculé une fois et l'a écrit, et à partir de cet instant il peut s'écarter des événements qui l'ont produit - un retry appliqué deux fois, une transaction qui a échoué à moitié, une correction manuelle bien intentionnée, une race condition entre deux requêtes.

Un total dérivé est une question posée aux événements eux-mêmes. Il ne peut pas s'écarter, parce qu'il n'existe rien de séparé dont il pourrait s'écarter. Reposez la question et vous obtenez la réponse d'aujourd'hui à partir des faits d'aujourd'hui.

À quoi cela ressemble en pratique

Au lieu d'une colonne quantity, vous tenez une table de mouvements : chacun signé, immuable, indiquant qui l'a fait, quand, et sur quelle référence. Le stock d'un entrepôt est la somme des mouvements qui le touchent. Une correction est un nouveau mouvement en sens inverse, jamais une modification.

Trois choses en découlent immédiatement, et c'est là le vrai gain :

  • Le rapprochement cesse d'être une tâche. Le solde et son explication sont le même objet, donc ils ne peuvent pas se contredire. Il n'y a plus d'exercice mensuel pour trouver où le nombre a dérapé.
  • « Pourquoi en avons-nous onze ? » a toujours une réponse. Pas en général. Toujours. L'historique complet est le nombre.
  • L'annulation devient sûre. Ajouter l'inverse laisse la piste d'audit intacte, alors que supprimer l'original détruit la preuve de ce qui s'est passé.

Il y a une petite version fonctionnelle de cette idée sur l'étude de cas des cliniques - enregistrez un mouvement et regardez les totaux se recalculer à partir du journal, sans que rien, nulle part, ne stocke une quantité.

L'objection, et la réponse honnête

« Additionner chaque mouvement à chaque lecture, ce sera lent. »

En général, non. Quelques milliers de mouvements ne représentent rien pour une base de données avec le bon index, et la plupart des systèmes qui s'en inquiètent ont bien moins de lignes que leurs auteurs ne l'imaginent.

Quand cela devient vraiment lent, la réponse est un snapshot périodique - une ligne de checkpoint qui dit « à cette date le solde était X » - et vous recalculez à partir du plus récent. C'est un cache, et il est sûr précisément parce qu'il est reconstructible : supprimez tous les snapshots et le système connaît toujours toutes les bonnes réponses. Au moment où vous ne pouvez plus le reconstruire à partir des événements, vous êtes revenu à un total stocké, et vous retrouvez le problème initial, avec de la mécanique en plus.

Où ne pas l'utiliser

C'est pour les choses qui se comptent et qui doivent pouvoir être expliquées. C'est inutile pour une préférence d'affichage, pour un brouillon, ou pour tout ce dont personne ne se souciera jamais que de la valeur actuelle. Faire de l'event sourcing sur le thème choisi par un utilisateur n'est pas de la rigueur, c'est du formalisme.

Décider dans laquelle des deux catégories tombe un chiffre donné se fait pendant le cadrage, pas pendant le développement - et c'est en partie pourquoi le premier prix qu'on vous annonce est généralement faux. C'est l'objet de la note sur ce que coûte vraiment une plateforme.