Quelle est la différence entre Command + CommandHandler et Service?

j'ai lu des articles sur l'utilisation d'objets de commande pour représenter des cas d'utilisation que notre domaine expose, et des objets de Handler de commande pour traiter ces commandes.

Par exemple:

  • RegisterUserCommand
  • RegisterUserCommandHandler

Mais c'est exactement la même chose que d'avoir un RegisterUserService, où l'objet de commande représente les paramètres à registerUser() méthode.

Et bien sûr, si la méthode avait trop de paramètres, j'ai créer un objet pour les envelopper et cet objet serait le même que le RegisterUserCommand.

Alors pourquoi avoir un modèle différent pour représenter la même chose? Les services sont répandus, pas les commandes (d'après mon expérience); Quelle est la différence ici que je manque? En bref, pourquoi j'utiliserais l'un plutôt que l'autre?

24
demandé sur Dave Schweisguth 2014-06-29 13:40:01

2 réponses

Avoir des Commandes vous donne les avantages du bon vieux modèle de Commande:

  • vous pouvez paramétrer un objet, par exemple un élément UI, avec une commande pour effectuer
  • vous pouvez stocker une Commande et l'exécuter plus tard, par exemple dans une file d'attente ou un journal de transactions
  • vous pouvez suivre les commandes que vous avez exécutées, vous donnant une base pour la mise en œuvre d'undo

si vos services étaient importants, chacun avec beaucoup de méthodes complexes (et si les méthodes n'étaient pas complexe vous ne devriez probablement pas utiliser DDD ou CQRS), alors déplacer chaque méthode dans un gestionnaire de commandes pourrait améliorer votre application en la rendant plus composable, plus facile à tester, etc. Il ne fait aucun doute qu'il est courant pour les personnes qui se replient directement des grands services vers les gestionnaires de commandes/commandes de considérer cela comme un avantage de ce dernier modèle. Mais vous pourriez obtenir le même avantage en décomposant les grands services en plus petits (comme suggéré par le service très spécifique dans votre exemple), donc strictement parler n'est pas une différence entre les services et les gestionnaires de Commandes/Commandes.

17
répondu Dave Schweisguth 2014-06-29 16:30:48

je pense que vous avez tout à fait raison de remettre en question le fait que ces deux concepts semblent être similaires dans leur contexte. Cela vaut probablement la peine de revenir en arrière et de considérer, pratiquement, ce à quoi ils sont destinés.

DDD Services

dans la conception par Domaine, il existe différents types de services par exemple, les services D'Application (généralement les services D'assurance-chômage), les services D'Infrastructure et les services de domaine.

Jimmy Bogard fait un excellent travail d'explication de ces

En bref:

Services De Domaine

la tâche des services de domaine est d'exécuter des fonctionnalités qui ne conviennent généralement pas à une entité. Pensez à utiliser un service de domaine lorsque vous avez un morceau de fonctionnalité qui nécessite une variété de

entités (objets agrégés / de valeur). Un exemple peut - être: pour calculer une estimation du coût d'une hypothèque, vous avez besoin des détails sur le revenu / l'emploi de l'acheteur. Vous peut exiger l'historique de crédit de l'acheteur et enfin vous pouvez avoir besoin de renseignements sur le bâtiment que l'hypothèque est considérée pour.

pricingService.CalculateMortageEstimate(BuyerIncomingDetails bid, BuyerCreditHistory bch, BuildingOverview bo)

Services D'Application

un exemple peut-être des services utilisés dans le cadre de L'assurance-chômage.

Services D'Infrastructure

Services qui ont tendance à communiquer avec des ressources externes (expéditeurs de courriels, systèmes de fichiers, fichiers xml, ftp, etc...)

Command / CommandHandlers (CQRS)

Commande Interrogation Responsabilité Ségrégation. Comme il est dit sur l'étain; une séparation de l':

  1. lancer des requêtes contre votre source de données
  2. modifier (via des commandes) vos données

l'utilisation du CQRS n'est pas toujours la bonne option, mais d'après mon expérience, les gens ont tendance à l'utiliser lorsque leurs données sont réparties entre plusieurs sources de données.

donc avec les commandes, vous demandez explicitement une unité de travail (ne pas être par exemple, AddFraudRecordCommand ou UpdateNoteCommand.


  1. ai-je même besoin de CommandHandlers / CommandHandlers? Qu'est-ce que je gagne, dois-je aller directement aux services?

  2. Le travail de mon Gestionnaire de Commande est de gérer la logique de mon commande (une commande étant une requête très spécifique). Tandis que les services DDD ont des tâches différentes (services de domaine: coordonner la fonctionnalité de plusieurs entités, services D'Infrastructure: collaborer avec des services externes par exemple email)

  3. Peut-être pensez-y comme ça: CommandHandler Job-exécute le code pour exécuter la commande spécifique (cela peut inclure l'utilisation de plusieurs services). Emploi dans le secteur des services-selon le type de service être.

ce n'est Pas le meilleur exemple, mais j'espère que cela brille la lumière sur ce que je suis en train de dire:

public class CalculateFraudProbabilityCommandHandler : CommandHandler<CalculateFraudProbabilityCommand>
{
         IFraudService _fraudService;
         IEmailNotifier _notifier;
         ICustomerRepository _customerRepo;


  public CalculateFraudProbabilityCommandHandler(ICustomerRepository customerRepo, IFraudService fraudService, IEmailNotifier notifier) 
  {     
        _fraudService = fraudService; //Domain Service  
        _notifier = notifier;         //Infrastructure Service  
        _customerRepo = customerRepo; //Repository
  }

 //Execute Command
 public void Execute(CalculateFraudProbabilityCommand command) {

     Customer customer = _customerRepository.GetById(command.CustomerId);
     FraudHistory fraudHistory = _fraudService.RetrieveFraudHistory(customer);

     //any fraud recently? if so, let someone know!
      if(fraudHistory.FraudSince(DateTime.Now.AddYear(-1)) {
           _notifier.SendEmail(_fraudService.BuildFraudWarningEmail(customer,      fraudHistory));
      }     

   }

}
11
répondu Mike 2018-02-06 09:31:18