В чем разница между Command + CommandHandler и Service?

Я читал об использовании объектов Command для представления вариантов использования, которые предоставляет наш домен, и объектов обработчика команд для обработки этих команд.

например:

  • RegisterUserCommand
  • RegisterUserCommandHandler

но он выглядит точно так же, как RegisterUserService, где объект command будет представлять параметры в registerUser() метод.

и, конечно, если бы метод имел слишком много параметров, я бы закончил до создания объекта, чтобы обернуть их, и этот объект будет таким же, как RegisterUserCommand.

так почему же другой шаблон представляет то же самое? Услуги широко распространены, а не команды (по моему опыту); какая разница здесь, что мне не хватает? Короче говоря, почему я должен использовать одно, а не другое?

2 ответов


наличие команд дает вам преимущества старого доброго шаблона команды:

  • вы можете параметризовать объект, например элемент UI, с помощью команды для выполнения
  • вы можете сохранить команду и выполнить ее позже, например, в очереди или журнала транзакций
  • вы можете отслеживать, какие команды вы выполнили, давая вам основу для реализации отмены

Если ваши услуги были большими, каждый со многими сложными методами (и если методы вы, вероятно, не должны использовать DDD или CQRS), то перемещение каждого метода в обработчик команд может улучшить ваше приложение, сделав его более составным, более легким для тестирования и т. д. Без сомнения, это распространено среди людей, которые рефакторируют прямо из больших служб в команды / обработчики команд, чтобы рассматривать это как преимущество последнего шаблона. Но вы можете получить ту же выгоду, разложив большие службы на меньшие (как это было предложено очень конкретной службой в вашем примере), поэтому строго говоря, это не разница между службами и обработчиками команд/команд.


Я думаю, вы совершенно правы, что эти две концепции кажутся похожими в контексте. Вероятно, стоит вернуться и рассмотреть, практически, для чего они предназначены.

DDD услуги

в дизайне, управляемом доменом, существуют различные типы служб например, службы приложений (обычно службы пользовательского интерфейса), инфраструктурные службы и доменные службы.

Джимми Богард делает отличную работу по объяснению этих

в двух словах:

Доменных Служб

задача доменных служб заключается в выполнении функций, которые обычно не подходят для одной сущности. Рассмотрите возможность использования доменной службы, когда у вас есть функциональность, требующая различных
сущности (объекты aggregate / value). Пример может быть: чтобы рассчитать оценку того, сколько может стоить ипотека, вам потребуется подробная информация о доходе / занятости покупателя. Вы можете требуют кредитной истории покупателя и, наконец, вам может понадобиться информация о здании, что ипотека будет рассмотреть.

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

Услуги Приложение

пример, возможно, службы, используемые как часть пользовательского интерфейса.

Услуги Инфраструктуры

службы, которые имеют тенденцию взаимодействовать с внешними ресурсами (отправители электронной почты, файловые системы, xml-файлы, ftp и т.д...)

Команды / CommandHandlers (С CQRS)

Запрос Команды Разделением. Как говорится на олове; разделение:

  1. выполнение запросов к источнику данных
  2. изменение (с помощью команд) ваших данных

использование CQRS не всегда правильный вариант, но по моему опыту, люди, как правило, используют его, когда их данные распределены по нескольким источникам данных.

таким образом, с командами вы явно просите единицу работы (не быть путать с шаблоном UnitOfWork) для выполнения, например, AddFraudRecordCommand или UpdateNoteCommand.


С этим небольшим обновлением различий между службами DDD и командами CQRS. Я бы отметил следующие вещи:

  1. Я вообще нужна команда / CommandHandlers? Что я получаю, должен ли я просто пойти прямо на службу?

  2. задача моего обработчика команд-обрабатывать логику моей команды (a Команда - очень конкретный запрос). В то время как службы DDD имеют разные задания (доменные службы: координируют функциональность нескольких объектов, инфраструктурные службы: сотрудничают с внешними службами, например, электронной почтой)

  3. возможно, подумайте об этом так: Задание CommandHandler-выполнение кода для выполнения конкретной команды (это может включать использование нескольких служб). Service Job-в зависимости от того, какой тип сервиса это.

не лучший пример, но я надеюсь, что он прольет свет на то, что я пытаюсь сказать:

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));
      }     

   }

}