62 votes

Comment appliquer une commande d'interrogation de commande de commande (CQS) lorsque des données de résultat sont nécessaires à partir d'une commande?

Dans wikipedia, la définition de requête de commande de séparation, il est indiqué que

Plus formellement, les méthodes doit retourner une valeur seulement si ils sont referentially transparent et donc n'ont pas d'effets secondaires.

Si je lance une commande, comment dois-je déterminer ou de rapport si cette commande a été un succès, puisque, de par cette définition, la fonction ne peut renvoyer des données?

Par exemple:

string result = _storeService.PurchaseItem(buyer, item);

Cet appel a à la fois une commande et de la requête en elle, mais la requête de la partie est le résultat de la commande. Je suppose que je pourrais refactoriser cela en utilisant le modèle de commande, comme ceci:

PurchaseOrder order = CreateNewOrder(buyer, item);
_storeService.PerformPurchase(order);
string result = order.Result;

Mais il semble que c'est l'augmentation de la taille et de la complexité du code, ce qui n'est pas une orientation très positive de refactoriser vers.

Quelqu'un peut-il me donner une meilleure façon de réaliser la commande de requête de séparation quand vous avez besoin le résultat d'une opération?

Suis-je manqué quelque chose?

Merci!

Notes: Martin Fowler a ceci à dire à propos des limites de cqs CommandQuerySeparation:

Meyer aime utiliser la commande de requête de la séparation absolument, mais il y a des exceptions. L'affichage d'une pile est une bonne exemple d'un modificateur qui modifie état. Meyer correctement dit que vous pouvez éviter d'avoir cette méthode, mais il est une utile idiome. Donc, je préfère suivre ce principe quand je le peux, mais Je suis prêt à le casser pour obtenir mon pop.

De son point de vue, c'est presque toujours la peine de refactoriser vers la commande/de requête de séparation, à l'exception de quelques petites simple exceptions.

42voto

Johannes Rudolph Points 19845

Cette question est ancienne mais n'a pas reçu une réponse satisfaisante, de sorte que je vais développer un peu sur mon commentaire de près d'un an.

À l'aide d'un événement driven architecture fait beaucoup de sens, non seulement pour la réalisation de clair de commande/de requête de séparation, mais aussi parce qu'elle ouvre de nouveaux choix architecturaux et correspond habituellement à un modèle de programmation asynchrone (utile si vous avez besoin de faire évoluer votre architecture). Le plus souvent, vous trouverez la solution réside peut-être dans la modélisation de votre domaine différemment.

Donc, nous allons jeter votre achat exemple. StoreService.ProcessPurchase il convient de commande pour le traitement d'un achat. Cela permettrait de générer un PurchaseReceipt. C'est une meilleure façon, au lieu de retourner à la réception, en Order.Result. Pour garder les choses très simples, vous pouvez retourner la réception de la commande et de violer CQRS ici. Si vous voulez un nettoyeur de séparation, la commande de soulever un ReceiptGenerated événement que vous pouvez vous abonner.

Si vous pensez au sujet de votre domaine, cela peut effectivement être un meilleur modèle. Lorsque vous êtes arrivée à la caisse, vous suivez ce processus. Avant votre réception est généré, une carte de crédit peut être due. Cela est susceptible de prendre plus de temps. En mode synchrone scénario, vous attendez à la caisse, incapable de faire autre chose.

17voto

2voto

Bryce Wagner Points 1241

J'aime l'événement driven architecture des suggestions d'autres personnes ont donné, mais je veux juste jeter un autre point de vue. Peut-être vous avez besoin de regarder pourquoi vous êtes réellement renvoi de données à partir de votre commande. Avez-vous réellement besoin de l'entraîner hors de lui, ou pourriez-vous en tirer avec le lancement d'une exception en cas de panne?

Je ne dis pas cela comme une solution universelle, mais le passage à une plus forte "exception en cas d'échec" au lieu de "envoyer la réponse" modèle m'a beaucoup aidé à faire de la séparation de fait des travaux dans mon propre code. Bien sûr, alors vous finissez par avoir à écrire beaucoup plus des gestionnaires d'exception, donc c'est un compromis... Mais c'est au moins un autre angle à considérer.

0voto

Jan Jongboom Points 15148

CQS est principalement utilisé lors de la mise en œuvre de la conception pilotée par domaine. Par conséquent, vous devez (comme l'indique également Oded) utiliser une architecture pilotée par événement pour traiter les résultats. Votre string result = order.Result; serait donc toujours dans un gestionnaire d'événements, et pas directement après dans le code.

Découvrez cet article qui montre une combinaison de CQS, DDD et EDA.

0voto

Michael Parker Points 566

Pourquoi avez-vous besoin d'un résultat? Vous violez dites ne demandez pas. Donnez à storeService tous les objets nécessaires pour exécuter des fonctions avec les résultats de sa commande PurchaseItem.

Ne demandez pas le résultat, dites à l'objet ce qu'il doit faire avec le résultat. (et fournir les objets nécessaires comme dépendances)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X