web-dev-qa-db-fra.com

Pourquoi Séparez la classe Commandhandler avec la poignée () au lieu de la manipulation de la méthode dans la commande elle-même

J'ai une partie du modèle CQRS mis en œuvre en utilisant S # ARP Architecture comme ceci:

public class MyCommand
{
    public CustomerId { get; set; }

    // some other fields
}

public class MyCommandHandler<MyCommand> : ICommandHandler<MyCommand, CommandResult>
{
    Handle(MyCommand command)
    {
        // some code for saving Customer entity

        return CommandResult.Success;
    }
}

Je me demande pourquoi pas seulement avoir la classe Command contenant les deux données et Méthode de manutention? Est-ce une sorte de prestation de testabilité, où vous devez tester la logique de manipulation de la commande séparément des propriétés de la commande? Ou est-ce une exigence fréquente de l'entreprise, où vous devez avoir une commande traitée par différentes implémentations de ICommandHandler<MyCommand, CommandResult>?

13
rgripper

Drôle, cette question me rappelait simplement la même conversation que j'avais avec l'un de nos ingénieurs sur la bibliothèque de communications que je travaillais.

Au lieu de commandes, j'avais demandé des cours et j'avais demandé à Realhandlers. La conception ressemblait beaucoup à ce que vous décrivez. Je pense qu'une partie de la confusion que vous avez est que vous voyez le mot anglais "commandement" et pense instantanément "verbe, action ... etc.".

Mais dans cette conception, pensez à la commande (ou à la demande) comme une lettre. Ou pour ceux qui ne savent pas ce qu'est un service postal, pensez à l'e-mail. Il s'agit simplement de contenu, découplé de la manière dont ce contenu devrait être agi.

Pourquoi voudriez-vous faire cela? Dans la plupart des cas simples, du modèle de commande, il n'y a aucune raison et vous aurez peut-être que cette classe fonctionne directement. Cependant, faire le découplage comme dans votre conception a du sens si votre action/commande/demande doit parcourir une certaine distance. Par exemple, à travers, des prises ou des tuyaux, ou entre domaine et infrastructure. Ou peut-être dans votre architecture que vos commandes doivent être persistantes (E.g. Command Handler peut effectuer une commande à la fois, en raison de certains événements système, 200 commandes arrivent et après l'arrêt du premier produit obtiennent une fermeture). Dans ce cas, avoir une classe de messages simples, il devient très simple de sérialiser uniquement la partie de message dans JSON/XML/BINARY/WHOINT et transmettez-la dans le pipeline jusqu'à ce que son gestionnaire de commande soit prêt à le traiter.

Un autre avantage de la commande de découplage de Commandhandler est que vous avez maintenant la possibilité d'une hiérarchie de héritage parallèle. Par exemple, toutes vos commandes pourraient tirer parti d'une classe de commandes de base qui prend en charge la sérialisation. Et peut-être que vous avez 4 manipulateurs de commandement sur 20 qui ont beaucoup de similitude, vous pouvez désormais dériver ceux de la classe de base du gestionnaire. Si vous deviez manipuler des données et des commandes dans une classe, ce type de relation serait rapidement en colère contre le contrôle.

Un autre exemple pour le découplage serait si votre commande nécessitait très peu d'entrée (par exemple 2 entiers et une chaîne), mais sa logique de manipulation était suffisamment complexe dans laquelle vous souhaitez stocker des données dans les variables d'éléments intermédiaires. Si vous faites une file d'attente de 50 commandes, vous ne souhaitez pas attribuer la mémoire pour tout ce stockage intermédiaire, de sorte que vous séparez la commande de Commandhandler. Vous devez maintenant faire la queue 50 structures de données de poids léger et plus de stockage de données complexes ne sont attribuées qu'une seule fois (ou N fois si vous avez N manipulateurs) par le commandhandler qui traite les commandes.

14
DXM

Normal modèle de commande est d'avoir les données et le comportement en classe unique. Ce type de "modèle de commande/gestionnaire" est légèrement différent. Le seul avantage par rapport au modèle normal est ajouté à l'avantage de ne pas avoir que votre commande dépend de des cadres. Par exemple, votre commande peut avoir besoin d'un accès à la DB afin de disposer d'une sorte de contexte ou de session de DB, ce qui signifie qu'il dépend des cadres. Mais cette commande peut faire partie de votre domaine, de sorte que vous ne voulez pas que cela dépend de des cadres selon principe d'inversion de dépendance . Séparer les paramètres d'entrée et de sortie du comportement et d'avoir un répartiteur pour les câbler peut résoudre ce problème.

D'autre part, vous perdrez à la fois l'héritage et la composition des commandes. Ce que je pense, c'est que c'est vrai pouvoir.

Aussi, mineur Nitpick. Juste parce que la commande de nom ne fait pas partie des CQRS. C'est à peu près quelque chose de beaucoup plus fondamental. Ce type de structure peut servir à la fois de commandement et d'une requête même en même temps.

2
Euphoric