Mat*_*oli 37 design-patterns domain-driven-design command-pattern cqrs
我一直在阅读使用Command对象来表示我们的域公开的用例,以及Command Handler对象来处理这些命令.
例如:
RegisterUserCommandRegisterUserCommandHandler但它看起来与a具有完全相同RegisterUserService,其中命令对象将表示registerUser()方法的参数.
当然,如果方法有太多的参数,我最终会创建一个对象来包装它们,并且该对象与它相同RegisterUserCommand.
那么为什么有不同的模式来表示同样的事情呢?服务很普遍,而不是命令(根据我的经验); 我错过了什么区别?简而言之,为什么我会使用一个而不是另一个?
Dav*_*uth 24
拥有命令可以获得良好的旧命令模式的好处:
如果您的服务很大,每个都有很多复杂的方法(如果方法不复杂,您可能不应该使用DDD或CQRS),那么将每个方法移动到命令处理程序中可能会使应用程序更易于组合,从而改善您的应用程序,更容易测试,等等.毫无疑问,直接从大服务重构到命令/命令处理程序的人认为这是后一种模式的好处.但是,通过将大型服务分解为较小的服务(如示例中的特定服务所示),您可以获得相同的好处,因此严格来说,这不是服务和命令/命令处理程序之间的区别.
Mik*_*ike 20
我认为你完全有理由质疑这两个概念在背景下似乎是相似的.它可能值得回去并且实际上考虑它们的用途.
在域驱动设计中,有不同类型的服务,例如应用程序服务(通常是UI服务),基础结构服务和域服务.
简而言之:
域名服务
域服务的工作是执行通常不适合一个实体的功能.当您拥有需要各种
实体(聚合/值对象)的功能时,请考虑使用域服务.一个例子可能是:要计算抵押贷款可能花费多少的估计,您需要有关买方收入/就业的详细信息.您可能需要买方的信用记录,最后您可能需要有关抵押贷款正在考虑的建筑物的信息.
pricingService.CalculateMortageEstimate(BuyerIncomingDetails bid, BuyerCreditHistory bch, BuildingOverview bo)
Run Code Online (Sandbox Code Playgroud)
应用服务
一个示例可能是用作UI的一部分的服务.
基建服务
倾向于与外部资源通信的服务(电子邮件发件人,文件系统,xml文件,ftp等...)
命令查询责任隔离.正如它在锡上所说; 分离:
使用CQRS并不总是正确的选择,但根据我的经验,人们倾向于在数据分布在多个数据源时使用它.
因此,使用这些命令,您明确要求执行一个工作单元(不要与UnitOfWork模式混淆),例如AddFraudRecordCommand或UpdateNoteCommand.
通过DDD服务和CQRS命令之间的差异进行小小的更新.我会注意到以下几点:
我甚至需要Command/CommandHandlers吗?我有什么收获,我应该直接去服务吗?
我的命令处理程序的工作是处理我的命令的逻辑(命令是一个非常具体的请求).DDD服务有不同的工作(域服务:协调多个实体的功能,基础设施服务:与外部服务协作,例如电子邮件)
也许可以这样想:CommandHandler 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));
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
9175 次 |
| 最近记录: |