Article

CQRS : séparer les décisions métier des vues de lecture

Avec CQRS, réserver une chambre et afficher les disponibilités reposent sur deux modèles adaptés à ces besoins. Deux bases de données ne sont pas obligatoires.

Une page affiche une chambre disponible. Au moment de la réserver, le système doit encore vérifier qu'un autre client ne l'a pas prise. Afficher une information et accepter une réservation demandent des règles différentes. CQRS propose de séparer ces responsabilités dans deux modèles, qui peuvent partager la même base de données.

Une commande demande un changement, une requête demande une information

CQRS signifie Command Query Responsibility Segregation : séparation des responsabilités de commande et de requête.

La commande « réserver cette chambre du 10 au 12 » exprime une intention. Le système peut l'accepter ou la refuser. La requête « quelles chambres sont disponibles ? » demande une information sans modifier l'état métier.

Le modèle de commande, souvent appelé write model, applique les règles nécessaires au changement. Le modèle de lecture, ou read model, prépare les informations attendues par un écran, un rapport ou une API.

Un objet unique mêlant commandes et requêtes est scindé en deux : un côté commande porteur des décisions et des règles, un côté requête porteur de la restitution.
La coupe de CQRS : un objet qui mêlait commandes et requêtes devient deux, un côté qui décide et connaît les règles, un côté qui restitue.

Deux modèles adaptés à deux besoins

Pour réserver, le système a besoin de vérifier les dates, la disponibilité et les conditions du séjour. Pour afficher les résultats d'une recherche, il peut réunir le nom de l'hôtel, une photo, le tarif et les équipements dans une réponse facile à consulter.

Ces représentations n'ont pas besoin de se ressembler. Chercher à utiliser les mêmes objets partout peut compliquer les règles de réservation comme les requêtes d'affichage.

Le raccourci « séparer lecture et écriture » décrit bien une partie de CQRS. Il devient trompeur si l'on en déduit qu'il suffit de créer deux bases. La séparation concerne d'abord les modèles et leurs responsabilités.

Un événement décrit ce qui s'est passé

Si la réservation est acceptée, le système peut produire un événement : « chambre réservée ». Il décrit un fait, tandis que la commande demandait encore une décision.

MessageExempleRôle
CommandeRéserver la chambreDemander un changement qui peut être refusé.
ÉvénementLa chambre a été réservéeInformer d'un changement déjà accepté.
RequêteAfficher les réservationsLire l'état présenté par le modèle de lecture.

Des événements peuvent alimenter une projection, une vue calculée pour la lecture. Ce mécanisme est fréquent, mais CQRS n'impose ni bus de messages ni traitement asynchrone.

Une commande entre dans le write model qui valide et décide, émet un événement ; l'événement alimente par projection le read model, que les requêtes viennent lire.
Dans cet exemple, la commande demande une décision, l’événement en décrit le résultat et la projection prépare les lectures. Cette circulation par événements est un choix de mise en œuvre.

La validation reste du côté de la décision

Une vue de disponibilité peut avoir quelques secondes de retard. Elle aide le client à choisir ; elle ne peut pas garantir, à elle seule, que la réservation sera encore possible lorsqu'il la confirmera.

Le modèle de commande vérifie donc la règle sur les données qui font autorité. Une règle qui doit rester vraie, comme l'absence de double réservation, s'appelle un invariant. La transaction et la gestion de la concurrence doivent réellement la protéger.

Le modèle de lecture peut calculer des totaux, assembler des informations ou préparer des libellés. Il ne doit pas devenir un deuxième endroit qui accepte indépendamment les mêmes décisions métier.

Une base commune peut suffire

Vous pouvez séparer le code qui traite les commandes de celui qui répond aux requêtes, tout en conservant un stockage commun. Cette organisation évite d'ajouter immédiatement une synchronisation entre bases.

Des stockages distincts deviennent intéressants lorsque leurs besoins divergent : recherche spécialisée, très fort volume de consultations ou données préparées pour plusieurs usages. Ils ajoutent aussi du travail : propagation des changements, gestion du retard et réparation des vues.

Une projection ne se reconstruit que si sa source conserve les informations nécessaires. Si elle utilise un historique qui n'existe plus ailleurs, la considérer comme « jetable » serait dangereux.

CQRS, CQS et event sourcing répondent à des questions différentes

Le principe CQS, formulé par Bertrand Meyer, distingue les méthodes qui changent l'état de celles qui renvoient une information. CQRS reprend cette séparation à l'échelle des modèles.

L'event sourcing concerne le stockage : il conserve la suite des événements permettant de retrouver l'état. On peut l'associer à CQRS, mais aucun des deux n'impose l'autre.

Pour un écran simple avec peu de règles, un modèle commun peut rester plus facile à maintenir. CQRS devient utile lorsque les contraintes de décision et de consultation se gênent réellement. Commencez par identifier cette difficulté avant de multiplier les composants.

La suite détaille la transaction qui protège la décision, puis la construction et la mise à jour des vues de lecture.

Sources

Explorer

Sur le même sujet

Choisis dans l’index d’après les étiquettes de cet article — les plus proches d’abord, hors de sa série. Rien n’est écrit à la main : un article publié demain avec les mêmes étiquettes y prendra place.

Comprendre CQRS avec une commande client

Comprendre CQRS avec une commande client

CQRS distingue les règles qui valident une opération des données préparées pour les vues. Une commande client explique les deux modèles et leur synchronisation.

Laisser un commentaire

Elle n'est jamais affichée ni publiée. Elle sert à regrouper vos commentaires et, si vous vous inscrivez un jour avec elle, à vous les rendre.

Votre commentaire sera relu avant d'être publié.