11

嗨,我正在使用Simple Injector DI 库,并且一直在关注一些关于围绕命令模式设计的架构模型的非常有趣的材料:

容器将管理 . 的生命周期UnitOfWork,我正在使用命令对数据库执行特定功能。

我的问题是,如果我有一个命令,例如 an AddNewCustomerCommand,它又对另一个服务执行另一个调用(即发送一条短信),从设计的角度来看这是可以接受的还是应该在更高级别完成,如果是这样,如何最好这样做?

示例代码如下:

public class AddNewBusinessUnitHandler
    : ICommandHandler<AddBusinessUnitCommand>
{
    private IUnitOfWork uow;
    private ICommandHandler<OtherServiceCommand> otherHandler;

    AddNewBusinessUnitHandler(IUnitOfWork uow, 
        ICommandHandler<OtherServiceCommand> otherHandler)
    {
        this.uow = uow;
        this.otherHandler = otherHandler;
    }

     public void Handle(AddBusinessUnitCommand command)
     {
        var businessUnit = new BusinessUnit()
        {
            Name = command.BusinessUnitName,
            Address = command.BusinessUnitAddress
        };

        var otherCommand = new OtherServiceCommand()
        {
            welcomePostTo = command.BusinessUnitName
        };

        uow.BusinessUnitRepository.Add(businessUnit);

        this.otherHandler.Handle(otherCommand);
     }
}
4

1 回答 1

21

这取决于您对(业务)命令的架构视图,但是在用例和命令之间具有一对一的映射是很自然的。在这种情况下,表示层应该(在单个用户操作期间,例如单击按钮)只创建命令并执行它。此外,它应该只执行单个命令,不再执行。执行该用例所需的一切都应由该命令完成。

也就是说,发送文本消息、写入数据库、进行复杂的计算、与 Web 服务通信以及操作业务所需的所有其他操作都应该在该命令的上下文中完成(或者可能排队稍后发生)。不是在此之前,也不是在之后,因为它是以与表示无关的方式表示需求的命令。

这并不意味着命令处理程序本身应该完成所有这些。将很多逻辑转移到处理程序所依赖的其他服务是很自然的。所以我可以想象你的处理程序依赖于一个ITextMessageSender接口,例如。

另一个讨论是命令处理程序是否应该依赖于其他依赖命令处理程序。当您查看用例时,大用例由多个较小的子用例组成的可能性不大,因此从这个意义上说,这并不奇怪。同样,命令和用例之间将存在一对一的映射。

但是,请注意,嵌套命令处理程序相互依赖的深度依赖图可能会使代码导航变得复杂,因此请仔细研究一下。ITextSessageSender例如,注入一个而不是使用一个可能会更好ICommandHandler<SendTextMessageCommand>

允许处理程序嵌套的另一个缺点是它使基础设施工作变得更加复杂。例如,当使用添加事务行为的装饰器包装命令处理程序时,您需要确保嵌套处理程序与最外层处理程序在同一事务中运行。我今天碰巧帮助了我的一个客户。这并不难,但需要一点时间才能弄清楚。像死锁检测这样的事情也是如此,因为它也在事务的边界上运行。

此外,死锁检测是展示这种命令/处理程序模式强大功能的一个很好的例子,因为几乎所有其他架构风格都无法插入这种行为。看看这篇文章DeadlockRetryCommandHandlerDecorator中的类)看一个例子。

于 2012-06-08T14:58:50.623 回答