了解DDD上下文中的命令模式

时间:2017-12-27 11:02:52

标签: c# domain-driven-design

我最近在这里阅读这篇文章:https://cuttingedge.it/blogs/steven/pivot/entry.php?id=100。它似乎谈论使用命令(http://www.dofactory.com/net/command-design-pattern)而不是应用程序服务。

请参阅以下代码:

public sealed class ShipmentController
{
    private readonly ICommandDispatcher dispatcher;

    public void ShipOrder(ShipOrder cmd) => dispatcher.Dispatch(cmd);
}

sealed class CommandDispatcher : ICommandDispatcher
{
    private readonly Container container;

    public void Dispatch(dynamic cmd) => GetHandler(cmd.GetType()).Handle(cmd);

    private dynamic GetHandler(Type type) =>
        container.GetInstance(typeof(ICommandHandler<>).MakeGenericType(type));
}

取代了这样的代码:http://www.zankavtaskin.com/2013/11/applied-domain-driven-design-ddd-part-6.html

我有三个问题:

1)这是说在应用服务层中每个命令请求应该有一个命令吗?这不会导致类爆炸,例如如果你有100个命令?

2)您如何处理CQRS查询?您是否为这些创建常规应用程序服务?

3)您如何处理从数据库中提取的场景(比如订单);在订单上执行命令,例如CalculateTax然后坚持到数据库?我假设流程是(这是正确的):

MVC 
Application Service (to extract order from database)
Command (Application Service calls CalculateTaxCommand)

1 个答案:

答案 0 :(得分:3)

  

似乎谈论使用命令而不是应用程序服务。

不,它没有谈论命令设计模式。在我的博客和其他地方描述的命令设计模式和类似CQRS的模式之间存在非常清晰且至关重要的区别。

命令设计模式中的“命令”将数据行为组合在同一个类中。使用CQRS,该命令只是一条没有行为的消息。行为被移动到“处理程序”类。这种分离是实现此设计的可维护性和灵活性的驱动因素。

  

1)这是说在应用服务层中每个命令请求应该有一个命令吗?这不会导致类爆炸,例如如果你有100个命令?

这是与开发人员非常常见的误解。他们认为系统中的类型数量与该系统的可维护性之间存在直接关系,其中类别的增加意味着可维护性的降低。

然而,SOLID设计模式有利于小型和集中式类而不是大类,因为使类更小,实际上可以极大地提高系统的可维护性。

这正是这里发生的事情。应从SOLID的角度来看待这种设计。我的经验是,在我重构到该模型的系统中,我们看到可维护性大幅增加了一个数量级,即使类的数量也会增加一个数量级。

不要担心系统中的类数。只是担心可维护性。

这并不意味着项目结构无关紧要。事实并非如此。因此,为您的命令,处理程序和装饰器找到一个好的项目结构。

  

2)您如何处理CQRS查询?您是否为这些创建常规应用程序服务?

您对查询执行与命令完全相同的操作。每个查询都应该有自己的查询消息和处理程序,以及可选的结果消息类。 This blog post描述了如何设计查询。

  

3)您如何处理从数据库中提取的场景(比如订单);在订单上执行命令,例如CalculateTax然后坚持到数据库?我假设流程是(这是正确的):

这是一个原子操作,应该都是命令的一部分。执行该命令时,将根据在命令中捕获的ID从数据库加载订单。计算税额,并将订单作为该(业务)交易的一部分保留。