CQRS / Event Sourcing par l'exemple.

Julien Vinber

  • Junior depuis plus de 20 ans
  • Lead dev / Architect pour Maline Immobilier
  • Un peu, mais plus trop organiser les Meetups
  • Adorateur sataniste de Merise et CURL
  • LinkedIn : @julienVinber

Attention

Il ne faut pas prendre tout ce que je vais dire pour vérité absolue et immuable.

Ce que je vais présenter est un point de vue. À vous d'en retirer ce dont vous avez envie.

Petits sondages pour commencer

  • Qui a déjà eu des problèmes de performance avec une Base de données ?
  • Qui a déjà eu des problèmes de conception ?
  • Qui a déjà eu des problèmes de consistance ?
  • Qui a déjà été bloqué par la structure de la base ?
  • Qui ne comprend pas pourquoi je pose ces questions ?

Je m'avance en prédisant qu'à part des étudiants, personne ne devrait avoir levé la main à la dernière question.

Un peu de contexte

Depuis toujours, on utilise fondamentalement 3 piliers pour la conception des bases de données :


Pourquoi ?

  • Cela marche.
  • C'est simple.
  • On peut faire à peu près tout avec.
  • C'est ce que l'on a appris et que tout le monde applique depuis 50 ans.

Grand principe

1) La conception

Actor
Actor
Actor
Actor
Actor
Actor
Actor
Actor
Besoin 1
Besoin 1
Besoin 2
Besoin 2
Besoin 3
Besoin 3
Besoin 4  
Besoin 4  
EntityPKUniqueIDFKUniqueID+Attribute1+Attribute2+Attribute3EntityPKUniqueID+Attribute1+Attribute2+Attribute3EntityPKUniqueID+Attribute1+Attribute2+Attribute3
Text is not SVG - cannot display

Grand principe

2)L'exploitation

EntityPKUniqueIDFKUniqueID+Attribute1+Attribute2+Attribute3EntityPKUniqueID+Attribute1+Attribute2+Attribute3EntityPKUniqueID+Attribute1+Attribute2+Attribute3
Besoin 6
Besoin 6
Besoin 7
Besoin 7
Besoin 5
Besoin 5
Besoin 8
Besoin 8
SQL
SQL
CRUD
CRUD
Text is not SVG - cannot display

Problèmes :

  • Quand on peut tout faire, on est souvent mauvais partout.
  • La complexité de l'écriture des règles de gestion est exponentielle avec la complexité du modèle.
  • Dans les faits, les règles sont incomplètes, les utilisateurs pouvant tout modifier vont créer de l'inconsistance.
  • Plus c'est gros, plus cela sera lent.
  • Modèle souvent rigide, et peu compatible avec la notion l'évolution permanente.

Face à ce constat, je vous propose une autre façon de voir :

CQRS et Event Sourcing

CQRS

Command and Query Responsibility Segregation

https://martinfowler.com/bliki/CQRS.html

Une autre façon de voir CQRS

C'est le besoin qui pilote la technique.

Il peut y avoir autant de réponses techniques que de besoins.

Commande 1
Commande 1
Commande 2
Commande 2
BD
Commande
BD...
Query1
Query1
Query 2
Query 2
Query 3
Query 3
BD
Besoin 1
BD...
Data
Besoin 2
Data...
Commande Bus
Commande Bus
Temporisation
Temporisation
Text is not SVG - cannot display

Event Sourcing

Capturez toutes les modifications apportées à l'état d'une application sous la forme d'une séquence d'événements.

https://martinfowler.com/eaaDev/EventSourcing.html

Concrètement :

Les "Command"
  • 1 besoin = 1 commande
  • Toute commande DOIT être validée.
  • 1 commande validée et complétée = 1 Event
  • Les évents sont sauvegardés ET envoyés pour traitement.

Concrètement :

Préparation des data coté "Query"
  • Des "dispatcher" reçoivent l'ensemble des événements.
  • En fonction du type d'évent, il appelle le bon "handler".
  • Les "handler" mettent à jour leurs bases de données.

Concretement :

Les "Query"
  • Accès aux data normales.
  • Au détail presque les bases sont plus adaptées au besoin...

Un "Event"

Un event est la pour répondre à plusieurs questions :

  • Qui ?
  • Quand ?
  • Quoi ?
  • Avec quoi ?
Commande
Commande
Controler
Controler
Validation Droit
Validation Droit
Validation Data
Validation Data
Traitement 
Traitement 
Persistance
Persistance
Propagation
Propagation
Event
Event
Event
Event
Event
Event
Event
Event
Event
Event
Event
Event
Commande Bus
Commande Bus
Commande
Commande
Dispatcher
Dispatcher
Handler
Event 1
Handler...
Handler
Event 2
Handler...
Handler
Event 3
Handler...
Handler
Event 4
Handler...
Dispatcher
Dispatcher
Handler
Event 3
Handler...
Handler
Event 4
Handler...
SGBDR 1
SGBDR 1
Base document 2
Base document 2
Query1
Query1
Query 2
Query 2
Query 3
Query 3
Text is not SVG - cannot display

Avantages

  • Aucune perte d'information.
  • Introduction de la notion d'intention.
  • On peut à tout moment TOUT reconstruire.
  • Grande tolérance à l'erreur.
  • L'inconsistance n'est plus qu'un simple bug.
  • Règles métiers simples à spécifier.
  • Pas besoin d'ajouter des exceptions dans le code.
  • Facile à s'adapter pour les problèmes de performance.
  • Par nature, le code est découpé et organisé.
  • Possible de reproduire en local.

Inconvénients

  • Difficile de mettre cela en place après.
  • C'est plus "naturel", mais moins intuitif.
  • Le code est simple, mais l'architecture complexe.
  • Cette approche pose les bases, mais tout reste à faire.
  • Attendez-vous à devoir traiter des problèmes que vous n'auriez pas eus sans.
  • Problème du temps de déploiement si reconstruction.

Conseils

  • Ne pas remettre à demain la qualité et le refactoring.
  • Prenez le temps de poser les bases.
  • Tolérance 0 sur les bugs "handler".

Un peu de pratique

https://gitlab.com/julienVinber/addressbook-cqrs-eventsourcing-symfony-demo