Le CQRS n'est-il pas une ingénierie excessive?

15

Je me souviens encore du bon vieux temps des référentiels. Mais les référentiels devenaient laids avec le temps. Ensuite, le CQRS s'est généralisé. Ils étaient gentils, ils étaient une bouffée d'air frais. Mais récemment, je me suis demandé à maintes reprises pourquoi je ne maintiens pas la logique dans la méthode Action d'un contrôleur (en particulier dans Web Api où l'action est une sorte de gestionnaire de commandes / requêtes en soi).

Auparavant, j'avais une réponse claire à cela: je le fais pour les tests, car il est difficile de tester Controller avec tous ces singletons immuables et la laideur globale de l'infrastructure ASP.NET. Mais les temps ont changé et les classes d'infrastructure ASP.NET sont beaucoup plus conviviales pour les tests unitaires de nos jours (en particulier dans ASP.NET Core).

Voici un appel WebApi typique: la commande est ajoutée et les clients SignalR en sont informés:

public void AddClient(string clientName)
{
    using (var dataContext = new DataContext())
    {
        var client = new Client() { Name = clientName };

        dataContext.Clients.Add(client);

        dataContext.SaveChanges();

        GlobalHost.ConnectionManager.GetHubContext<ClientsHub>().ClientWasAdded(client);
    }
}

Je peux facilement le tester / me moquer. De plus, grâce à OWIN, je peux configurer des serveurs WebApi et SignalR locaux et faire un test d'intégration (et assez rapide d'ailleurs).

Récemment, j'ai ressenti de moins en moins de motivation pour créer des gestionnaires de commandes / requêtes encombrants et j'ai tendance à conserver le code dans les actions Web Api. Je ne fais une exception que si la logique est répétée ou si c'est vraiment compliqué et je veux l'isoler. Mais je ne sais pas si je fais la bonne chose ici.

Quelle est l'approche la plus raisonnable pour gérer la logique dans une application ASP.NET moderne typique? Quand est-il raisonnable de déplacer votre code vers des gestionnaires de commandes et de requêtes? Y a-t-il de meilleurs modèles?

Mise à jour. J'ai trouvé cet article sur l'approche DDD-lite. Il semble donc que mon approche consistant à déplacer des parties compliquées de code vers des gestionnaires de commandes / requêtes puisse s'appeler CQRS-lite.

SiberianGuy
la source
1
Je ne vois pas comment CQRS rend les choses plus testables / est d'une quelconque aide avec les singletons / contrôleurs / etc. Ils sont largement indépendants. De plus, vous créez toujours une commande dans votre exemple (compteur?), Ce qui est étrange.
guillaume31
Si vous conservez votre code avec le code d'infrastructure (c'est-à-dire obtenir l'adresse IP du client), il est difficile à tester. Si vous isolez la logique dans une requête / commande, c'est beaucoup plus facile. L'exemple de code était un peu déroutant, donc je l'ai mis à jour.
SiberianGuy
1
Les requêtes et les commandes n'ont aucune logique. Ce sont des DTO stupides. Ensuite, vous avez vos gestionnaires de commandes / requêtes , mais ils sont exactement les mêmes que les services d'application, les interacteurs, les services métier, vous l'appelez ... dans un contexte non CQRS. Placer la logique d'application / cas d'utilisation dans un objet distinct de celui du contrôleur n'est pas une chose spécifique au CQRS.
guillaume31
De plus, la question de la dépendance entre Singleton et la dépendance injectée est complètement orthogonale au CQRS. Vous pourriez avoir un contrôleur appelant un singleton CommandHandler qui appelle un singleton de référentiel ...
guillaume31
1
@ guillaume31, CQRS a tendance à être plus lourd que les appels de service de référentiel / aplication. Ils ont généralement besoin de 2-3 classes (c.-à-d. Requête, gestionnaire de requêtes, résultat de requête), infrastructure, etc.
SiberianGuy

Réponses:

17

Le CQRS est-il un modèle relativement compliqué et coûteux? Oui.

Est-ce une ingénierie excessive? Absolument pas.

Dans l' article d'origine où Martin Fowler parle du CQRS, vous pouvez voir de nombreux avertissements concernant la non-utilisation du CQRS là où il ne s'applique pas:

Comme tout modèle, le CQRS est utile à certains endroits, mais pas à d'autres.

Le CQRS est un saut mental important pour toutes les parties concernées, donc ne devrait pas être abordé à moins que l'avantage en vaille la peine .

Bien que j'ai rencontré des utilisations réussies du CQRS, jusqu'à présent, la majorité des cas que j'ai rencontrés n'ont pas été aussi bons ...

Malgré ces avantages, vous devez être très prudent quant à l'utilisation du CQRS .

... l'ajout de CQRS à un tel système peut ajouter une complexité importante .

Je souligne ci-dessus.

Si votre application utilise CQRS pour tout, ce n'est pas CQRS qui est sur-conçu, c'est votre application. Il s'agit d'un excellent modèle pour résoudre certains problèmes spécifiques, en particulier les applications hautes performances / volume élevé où la simultanéité en écriture peut être une préoccupation majeure.

Et ce n'est peut-être pas la totalité de l'application, mais seulement une petite partie.

Un exemple vivant de mon travail, nous utilisons CQRS dans le système de saisie des commandes, où nous ne pouvons perdre aucune commande, et nous avons des pics où des milliers de commandes proviennent en même temps de différentes sources, à certaines heures spécifiques. CQRS nous a aidés à maintenir le système en vie et réactif, tout en nous permettant de bien dimensionner les systèmes backend pour traiter ces commandes plus rapidement en cas de besoin (plus de serveurs backend) et plus lentement / moins cher lorsqu'ils ne sont pas nécessaires.

CQRS est parfait pour le problème où plusieurs acteurs collaborent dans le même ensemble de données ou écrivent sur la même ressource.

En dehors de cela, la propagation d'un motif conçu pour résoudre un seul problème à tous vos problèmes ne fera que créer plus de problèmes pour vous.


Quelques autres liens utiles:

http://udidahan.com/2011/04/22/when-to-avoid-cqrs/

http://codebetter.com/gregyoung/2012/09/09/cqrs-is-not-an-architecture-2/

Machado
la source
3
Mettez-vous d'accord sur tout sauf la partie "modèle relativement compliqué et coûteux". Le CQRS sépare simplement les lectures des écritures. Vous pouvez le faire avec du ruban adhésif, sans middleware / outillage compliqué et en conservant la même base de données qu'auparavant, pour tout ce qu'il vous faut.
guillaume31
@ guillaume31, c'est un bon point. Je pense que cela correspond assez bien à l'idée de la question d'origine: "dans Web Api où l'action est une sorte de commande / requête en soi". Mais avez-vous vu des échantillons CQRS fonctionnant (github de préférence) qui n'utilisent pas de classes distinctes pour les commandes et les requêtes? C'est ce que je trouve lorsque j'essaie de voir comment d'autres personnes implémentent CQRS dans .NET.
SiberianGuy
Oui, mais ce n'est pas une ingénierie excessive. C'est la prémisse de base du modèle - séparer les requêtes des écritures, lire le modèle du modèle de domaine.
guillaume31
L'approche CQRS est peut-être excessive dans de nombreux contextes, mais c'est une tout autre histoire. Ce n'est pas exagéré à cause de tous les petits détails techniques que vous attribuez à tort au CQRS dans votre Q, c'est exagéré parce que vous n'avez pas toujours besoin de ce que le CQRS vous apporte.
guillaume31
Je pense que le point de Fowler n'est valable que jusqu'à un certain point. Les vues SQL sont un type de CQRS et elles sont avec nous depuis des lustres et personne ne dit qu'elles sont très complexes. Puisqu'il existe de nombreuses variantes du CQRS, c'est-à-dire des projections de sourcing d'événements, cela peut être considéré comme complexe dans certains domaines, alors qu'il peut être trivial dans un autre.
Alexey Zimarev
3

CQRS n'est pas un remplacement un pour un pour les référentiels, exactement parce que c'est un modèle complexe et coûteux qui n'est utile que dans certains cas.

Voici ce que Udi Dahan a à dire au mérite:

La plupart des gens utilisant CQRS (et Event Sourcing aussi) n'auraient pas dû le faire.

[...]

Je suis désolé de dire que la plupart des exemples d'applications que vous verrez en ligne qui montrent que CQRS sont incorrectes sur le plan architectural. Je me méfierais également beaucoup des cadres qui vous guident vers un modèle CQRS racine agrégé de type entité.

( source )

Martin Fowler:

[...] vous devez être très prudent lorsque vous utilisez CQRS . De nombreux systèmes d'information cadrent bien avec la notion de base d'informations qui est mise à jour de la même manière qu'elle est lue, l'ajout de CQRS à un tel système peut ajouter une complexité importante.

( source )

Enfin, Greg Young:

CQRS peut être appelé un modèle architectural.

[...]

Ceci est très important pour comprendre que la plupart des modèles architecturaux ne sont pas bons à appliquer partout. Si vous voyez des modèles architecturaux dans une directive architecturale, vous avez probablement un problème

[...]

Le plus grand échec que je constate chez les personnes utilisant le sourcing d'événements est qu'elles essaient de l'utiliser partout.

( source )

Sklivvz
la source