我认为你完全正确地质疑这两个概念在上下文中似乎相似。因此,回顾一下它们的实际用途是值得的。
DDD服务
在领域驱动设计中,有不同类型的服务,例如应用程序服务(通常是用户界面服务)、基础设施服务和域服务。
Jimmy Bogard很好地解释了这些
简而言之:
域服务
域服务的工作是执行通常不适合一个实体的功能。当您需要进行一项功能并需要访问多种实体(聚合/值对象)时,请考虑使用域服务。例如:计算抵押贷款可能花费多少,您需要详细了解购房者的收入/就业情况,还需要购房者的信用历史记录,最后还需要有关正在考虑抵押贷款的房屋的信息。
pricingService.CalculateMortageEstimate(BuyerIncomingDetails bid, BuyerCreditHistory bch, BuildingOverview bo)
应用服务
例如作为UI的一部分使用的服务。
基础设施服务
通常与外部资源(如电子邮件发送器、文件系统、xml文件、ftp等)通信的服务。
命令/命令处理程序(CQRS)
命令查询责任分离。正如其名称所示,将以下内容分开:
- 对数据源运行查询
- 通过命令修改您的数据
使用CQRS并不总是正确的选择,但在我的经验中,当数据分布在多个数据源时,人们倾向于使用它。
因此,对于命令,您明确要求执行工作单元(不要与UnitOfWork模式混淆),例如AddFraudRecordCommand或UpdateNoteCommand。
通过这些关于DDD服务和CQRS命令之间的差异的小刷新,我想指出以下几点:
我是否需要命令/命令处理程序?我能得到什么好处,我直接转到服务是不是更好?
我的命令处理程序的工作是处理命令的逻辑(命令是非常具体的请求)。而DDD服务有不同的工作(领域服务:协调多个实体的功能,基础设施服务:与外部服务(例如电子邮件)协作)
也许可以这样考虑:
CommandHandler工作-执行代码以运行特定命令(这可能包括使用多个服务)。
服务工作-根据服务类型而定。
不是最好的例子,但我希望它能为我试图说的内容带来一些启示:
public class CalculateFraudProbabilityCommandHandler : CommandHandler<CalculateFraudProbabilityCommand>
{
IFraudService _fraudService;
IEmailNotifier _notifier;
ICustomerRepository _customerRepo;
public CalculateFraudProbabilityCommandHandler(ICustomerRepository customerRepo, IFraudService fraudService, IEmailNotifier notifier)
{
_fraudService = fraudService;
_notifier = notifier;
_customerRepo = customerRepo;
}
public void Execute(CalculateFraudProbabilityCommand command) {
Customer customer = _customerRepository.GetById(command.CustomerId);
FraudHistory fraudHistory = _fraudService.RetrieveFraudHistory(customer);
if(fraudHistory.FraudSince(DateTime.Now.AddYear(-1)) {
_notifier.SendEmail(_fraudService.BuildFraudWarningEmail(customer, fraudHistory));
}
}
}