ConstructiCat Logo
CodeBust.
Browse section ▾

CQRS.

Also known as — Command Query Responsibility Segregation

Séparer le modèle qui modifie l'état (commandes) du modèle qui lit l'état (requêtes), afin que chaque côté puisse être modélisé, mis à l'échelle et optimisé indépendamment.

##Intent

Utiliser un modèle pour mettre à jour l'information et un modèle différent pour la lire. Les commandes expriment l'intention de modifier l'état ; les requêtes renvoient des données mises en forme pour l'affichage. Les deux n'ont plus à faire de compromis sur une représentation partagée unique.

##Problem

Dans une conception traditionnelle, un seul modèle sert à la fois les écritures et les lectures. Les écritures ont besoin d'une validation riche et d'invariants ; les lectures ont besoin de formes dénormalisées, prêtes à l'affichage — souvent plusieurs différentes pour différents écrans et rapports.

Forcer les deux à passer par les mêmes objets et tables conduit à des compromis maladroits : surchargement (over-fetching), mappages ORM complexes, contention de verrous, et un modèle bon à aucune des deux tâches.

##Solution

CQRS scinde le système en deux. Le côté écriture traite les commandes au moyen de gestionnaires qui chargent un agrégat, font respecter les invariants et persistent le changement (en émettant éventuellement des événements). Le côté lecture sert les requêtes depuis un ou plusieurs modèles de lecture mis en forme spécifiquement pour les vues qui les consomment.

Les deux côtés peuvent partager une base de données ou utiliser des magasins séparés. Lorsqu'ils sont séparés, les modèles de lecture sont tenus à jour en projetant les événements du côté écriture, acceptant une cohérence à terme en échange d'une mise à l'échelle indépendante et de requêtes plus simples.

##Structure

  • Commande — une requête de modification de l'état, nommée selon l'intention (PlaceOrder).
  • Gestionnaire de commande — valide et applique la commande au modèle d'écriture.
  • Modèle d'écriture — des agrégats qui font respecter les invariants ; peuvent émettre des événements.
  • Modèle de lecture / projection — des vues dénormalisées construites pour les requêtes, mises à jour à partir des événements.
  • Requête & gestionnaire de requête — des demandes en lecture seule servies depuis le modèle de lecture.

##Applicability

  • Utilisez-le là où les lectures et les écritures ont des formes ou des charges très différentes — de nombreuses vues de lecture, des rapports volumineux, ou un fort ratio lectures/écritures.
  • Utilisez-le pour les interfaces orientées tâches et les domaines collaboratifs, où il s'associe naturellement à la conception pilotée par le domaine (DDD) et à l'event sourcing.
  • Évitez-le pour du CRUD simple ; un modèle unique est plus simple et la séparation ajoute un coût sans contrepartie.

##How to Implement

  1. Modélisez les commandes comme des intentions explicites plutôt que comme des mises à jour génériques.
  2. Acheminez chaque commande vers un gestionnaire qui charge l'agrégat concerné et fait respecter ses invariants.
  3. Persistez le changement et, si vous utilisez des événements, publiez ce qui s'est produit.
  4. Construisez des modèles de lecture taillés pour vos vues ; s'ils sont séparés, mettez-les à jour en projetant les événements.
  5. Servez les requêtes directement à partir des modèles de lecture — aucune logique métier du côté lecture.

##Pros & Cons

Pros
  • Les côtés lecture et écriture peuvent être modélisés, optimisés et mis à l'échelle indépendamment.
  • Chaque modèle reste petit et concentré sur une seule tâche.
  • Convient aux interfaces orientées tâches et se combine bien avec l'event sourcing et le DDD.
  • Les modèles de lecture peuvent être taillés par vue, éliminant les jointures maladroites.
Cons
  • Plus de pièces mobiles et plus de code qu'un modèle CRUD unique.
  • Les magasins de lecture séparés introduisent une cohérence à terme (eventual consistency), que l'UX doit gérer.
  • Facile à sur-concevoir ; rarement justifié pour des domaines simples.
  • Charge opérationnelle des projections et de la plomberie de messagerie.