I think you're completely right to question that these two concepts seem to be similar in context.
It’s probably worth going back and considering, practically, what they are intended for.
DDD Services
In Domain Driven Design, there are different types of services
e.g. Application Services (commonly UI services), Infrastructure Services and Domain Services.
Jimmy Bogard does an excellent job of explaining these
In a nutshell:
Domain Services
The job of the domain services is to execute functionality that typically doesn't suit for one entity. Consider using a domain service when you have a piece of functionality that requires a variety of
entities (aggregate / value objects). An example maybe: to calculate an estimate on how much a mortgage may cost, you require the detail on the buyer’s income / employment. You may require the buyer’s credit history and finally you may need information on the building that the mortgage is being consider for.
pricingService.CalculateMortageEstimate(BuyerIncomingDetails bid, BuyerCreditHistory bch, BuildingOverview bo)
Application Services
An example maybe services used as part of the UI.
Infrastructure Services
Services that tend to communicate with external resources (email senders, file systems, xml files, ftp etc...)
Command / CommandHandlers (CQRS)
Command Query Responsibility Segregation. As it says on the tin; a separation of:
- running queries against your data source
- Modifying (via commands) your data
using CQRS isn't always the right option but in my experience, people tend to use it when their data is distributed across multiple data sources.
So with the commands, you are explicitly asking for a unit of work (not to be confused with the UnitOfWork pattern) to be executed e.g. AddFraudRecordCommand or UpdateNoteCommand.
With that little refreshment on the differences between DDD services and CQRS commands.
I would note the following things:
Do I even need Command / CommandHandlers? What am I gaining, should I just go directly to the services?
The job of my Command Handler is to handle the logic of my command (a Command being a very specific Request). Whereas the DDD services have different jobs (Domain Services: coordinate functionality of multiple entities, Infrastructure Services: collaborate with external services e.g. email)
Maybe think of it like this:
CommandHandler Job – execute the code to run the specific command (this may include using multiple services).
Service Job – Depending on what type of service it is.
Not the best example, but I’m hoping it shines some light on what I’m trying to say:
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));
}
}
}