logo le blog invivoo blanc

Le pattern CQRS

18 janvier 2023 | Java | 0 comments

Aller jusqu’au bout dans l’organisation du code et surtout séparer le deux parties Lecture et Ecriture dans une application ou même un micro service.

Dans l’architecture micro-service on rencontre et on utilise plusieurs concepts et patrons de conceptions, principalement on peut citer CQRS et Event sourcing.

Remarque : ces deux concepts sont souvent utilisés ensemble.

Dans cet article, nous ferons une présentation de CQRS ainsi qu’un exemple d’implémentation.  

1-    Définition CQRS

CQRS, est un Patron de Conception, il est aussi un model d’architecture qui sépare les deux parties de traitement (Écriture) et de réponse (Lecture) :

  • C : Command
  • Q : Query
  • R : Responsabilty
  • S : Separation

CQRS est basé sur le principe Command & Query séparation (CQS) qui a été proposé par Bertrand Meyer dans le cadre de ses travaux sur le langage de programmation Eiffel ~Wikipedia~.

2-    Architecture globale

  • Query : opération de lecture seule : aucun état n’est mis à jour après l’exécution de Query.
  • Command : opération d’écriture/mis à jour modifiant les données sans retour.

3-    Implémentation

3.1- Model de Lecture (Query) vs Model d’Ecriture (Command)

Pour conclure sur cette partie :

  • Query est une opération de lecture qui ne change pas l’état de l’application. C’est au composant de lecture (Reading Component) d’interagir avec la Base de Données (Source de données). Il y aura un traitement et une analyse de résultats retournés par la source de données BD et la transformation vers un DTO pour renvoyer le résultat attendu à l’utilisateur.
  • Command : C’est une action par laquelle l’utilisateur souhaite changer l’état de l’application, soit via une mise à jour ou une insertion. La partie command contient une couche de traitement permettant de faire aboutir les actions de mise à jour, insertion, en d’autres termes permettant de modifier l’état de l’application selon la spécification.

3.2- Exemple d’implémentation

3.2.1- Présentation de l’exemple

Il s’agit d’une application de création & récupération des utilisateurs.

          

Remarque : s’il s’agissait d’une application de CRUD complète, il faudrait penser à implémenter les actions de mise à jour et suppression en tant que commandes, les actions de récupération ou de recherche seront comme des Queries.

Stack Technique :

  • Spring boot
  • H2
  • Lombok
  • Swagger
  • JPA

L’application est générée avec Spring Initializr : https://start.spring.io/

3.2.2- Implémentation

  • Arborescence :
  • Swagger :
  • Create Users :
  • Get Users :

Remarques :

  • Il sera plus intéressant d’implémenter CQRS avec l’Event sourcing car il y aura moins de duplication ainsi il y aura un couplage faible entre les deux parties Query et Command.
  • CQRS rajoute de la complexité (multiplication des classes) en cas de projets simples comme une application de CRUD, … è il sera plus intéressant d’utiliser CQRS dans un contexte métier complexe.

4-    Avantages et inconvénients de CQRS

4.1 Avantages CQRS :

  • Pas de risque d’effets de bord : dans la partie Query(Lecture) tous les services et leurs méthodes ne changent pas l’état de l’application, donc il est possible de manipuler cette partie sans crainte vue qu’elle ne sera pas la cause d’une régression ou d’un comportement anormal sur l’application.
  • Isolation importante et Couplage Faible : Avec la séparation de l’application en deux parties (Query et Command) on aura une isolation des deux actions Lecture et Ecriture. D’autre part l’utilisation de services spécifiques pour chaque partie garantit un couplage faible vers 0% surtout avec l’utilisation d’Event Sourcing.
  • Respecter plus la règle de Single Responsability (Responsabilité Unique) de principe SOLID : On parle des bouts de codes plus fins et des services ayant une seule responsabilité. D’autre part la taille des classes est moins importante, vu qu’on a la possibilité de créer un Handler par commande 
  • Avec CQRS on peut implémenter l’asynchronisme simplement : avec le principe de séparation de la lecture de l’écriture et en utilisant l’Event Sourcing on peut implémenter simplement des actions asynchrones surtout dans le cas des applications ayant des traitements prenant trop de temps ou dépendantes d’autres applications.

4.2 Inconvénients CQRS :

  • Coût de Refactoring :

Tout changement de la partie commune de la couche de données nécessite une mise à jour dans Query et Command à la fois (exemple : le changement de nom d’une colonne exige la mise à jour des objets et leur mapping de Command (Write) ainsi que l’action de lecture dans Query (requête SQL)).

  • Mapping obligatoire avec les DTOs :

Un mapping entre les Objets et les DTOs (Pour les résultats de lecture (IHM)) est obligatoire en cas d’utilisation d’une couche supplémentaire des DTOs.