Jaka jest różnica między Command + CommandHandler a Service?

Czytałem o używaniu obiektów poleceń do reprezentowania przypadków użycia, które wystawia nasza domena, oraz obiektów obsługi poleceń do przetwarzania tych poleceń.

Na przykład:

  • RegisterUserCommand
  • RegisterUserCommandHandler

Ale wygląda dokładnie tak samo jak posiadanie RegisterUserService, gdzie obiekt command reprezentowałby parametry metody registerUser().

I oczywiście, gdyby metoda miała zbyt wiele parametrów, w końcu stworzyłbym obiekt do zawinięcia ich i tego obiektu będzie taka sama jak RegisterUserCommand.

Więc dlaczego mają inny wzór, aby reprezentować to samo? Usługi są powszechne, a nie polecenia (z mojego doświadczenia); jaka jest tutaj różnica, której mi brakuje? Krótko mówiąc, Dlaczego miałbym używać jednego, a nie drugiego?

Author: Dave Schweisguth, 2014-06-29

2 answers

Posiadanie poleceń daje korzyści ze starego, dobrego wzorca poleceń:

  • możesz parametryzować obiekt, np. element interfejsu użytkownika, za pomocą polecenia do wykonania
  • Możesz zapisać polecenie i wykonać je później, np. w kolejce lub dzienniku transakcji
  • możesz śledzić, które polecenia wykonałeś, dając podstawy do implementacji undo

Jeśli Twoje usługi były duże, każda z wieloma złożonymi metodami (a jeśli metody nie były złożone, prawdopodobnie nie powinno się używać DDD lub CQRS), wtedy przeniesienie każdej metody do obsługi poleceń może poprawić Twoją aplikację, czyniąc ją bardziej złożoną, łatwiejszą do przetestowania, itp. Bez wątpienia jest to powszechne dla osób, które refakturują bezpośrednio z dużych usług do poleceń/programów obsługi poleceń, aby uznać to za korzyść z tego drugiego wzoru. Ale możesz uzyskać tę samą korzyść, rozkładając Duże usługi na mniejsze (jak sugeruje bardzo konkretna usługa w twoim przykładzie), więc ściśle mówiąc, nie jest to różnica między usługami a poleceniami/programami obsługi poleceń.

 17
Author: Dave Schweisguth,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-29 16:30:48

Myślę, że masz całkowitą rację kwestionując, że te dwa pojęcia wydają się być podobne w kontekście. Warto chyba wrócić i zastanowić się praktycznie do czego są one przeznaczone.

Usługi DDD

W Domain Driven Design istnieją różne rodzaje usług np. usługi aplikacyjne( potocznie usługi UI), usługi infrastrukturalne i usługi domenowe.

Jimmy Bogard doskonale wyjaśnia te

W "nutshell": {]}

Domain Services

Zadaniem usług domenowych jest wykonywanie funkcji, które zazwyczaj nie odpowiadają jednemu podmiotowi. Warto rozważyć korzystanie z usługi domeny, gdy masz część funkcjonalności, która wymaga różnych
encje (obiekty agregujące / wartości). Przykład może: aby obliczyć szacunkową kwotę, jaką może kosztować kredyt hipoteczny, potrzebujesz szczegółów na temat dochodu / zatrudnienia kupującego. Możesz wymagać historii kredytowej kupującego i wreszcie może potrzebować informacji na temat budynku, na który rozważana jest hipoteka.

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

Usługi Aplikacyjne

Przykład usług używanych jako część interfejsu użytkownika.

Usługi Infrastrukturalne

Usługi, które mają tendencję do komunikowania się z zewnętrznymi zasobami(nadawcy wiadomości e-mail, systemy plików, pliki xml, ftp itp...)

Command / CommandHandlers (CQRS)

Command Query Responsibility Segregation. Jak napisano na puszce; rozdzielenie of:

  1. uruchamianie zapytań przeciwko źródłu danych
  2. modyfikowanie (za pomocą poleceń) Twoich danych

Korzystanie z CQRS nie zawsze jest właściwą opcją, ale z mojego doświadczenia wynika, że ludzie mają tendencję do korzystania z niego, gdy ich dane są dystrybuowane w wielu źródłach danych.

Tak więc z poleceniami wyraźnie prosisz o wykonanie jednostki pracy (nie mylić z wzorcem UnitOfWork), np. AddFraudRecordCommand lub UpdateNoteCommand.


Z tym małe odświeżenie różnic między usługami DDD a poleceniami CQRS. Chciałbym zwrócić uwagę na następujące rzeczy:

  1. Czy w ogóle potrzebuję komend / Commandhandlerów? Co zyskuję, czy powinienem po prostu przejść bezpośrednio do usług?

  2. Zadaniem mojego Handlera poleceń jest obsługa logiki mojego polecenia (polecenie jest bardzo specyficznym żądaniem). Natomiast usługi DDD mają różne zadania (Usługi domenowe: koordynowanie funkcjonalności wielu podmiotów, Infrastruktura Usługi: współpraca z usługami zewnętrznymi, np. e-mail)

  3. Może pomyśl o tym w ten sposób: CommandHandler Job-wykonaj kod, aby uruchomić określone polecenie (może to obejmować korzystanie z wielu usług). Praca serwisowa – w zależności od rodzaju usługi.

nie jest to najlepszy przykład, ale mam nadzieję, że rzuci trochę światła na to, co próbuję powiedzieć:

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
Author: Mike,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-06 09:31:18