> Meanwhile… on the command side of my architecture
> Meanwhile… on the query side of my architecture
容器将管理UnitOfWork的生命周期,我使用命令来执行数据库的特定功能.
我的问题是,如果我有一个命令,例如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); } }
解决方法
也就是说,发送文本消息,写入数据库,进行复杂计算,与Web服务通信以及操作业务需求所需的其他所有内容都应该在该命令的上下文中完成(或者可能在以后排队等待).不是之前,而是之后,因为它是以表示不可知的方式表示需求的命令.
这并不意味着命令处理程序本身应该完成所有这些.将很多逻辑移动到处理程序所依赖的其他服务是很自然的.所以我可以想象你的处理程序取决于ITextMessageSender接口.
另一个讨论是命令处理程序是否应该依赖于其他依赖命令处理程序.当您查看用例时,大用例不一定包含多个较小的子用例,因此从这个意义上来说并不奇怪.同样,命令和用例之间将存在一对一的映射.
但是,请注意,依赖于彼此的嵌套命令处理程序的深度依赖关系图可能会使代码导航变得复杂,因此请仔细查看.例如,注入ITextSessageSender而不是使用ICommandHandler< SendTextMessageCommand>可能更好.
允许处理程序嵌套的另一个缺点是它使基础结构的东西变得复杂一些.例如,在使用添加事务行为的装饰器包装命令处理程序时,需要确保嵌套处理程序在与最外层处理程序相同的事务中运行.今天我碰巧帮助了我的客户.这并不难,但需要一点时间才能搞清楚.死锁检测之类的东西也是如此,因为它也在事务的边界运行.
此外,死锁检测是一个很好的例子,展示了这个命令/处理程序模式的强大功能,因为几乎所有其他架构风格都无法插入这种行为.看一下this article中的DeadlockRetryCommandHandlerDecorator类来查看示例.