基于Clean Architecture的MediatR与CQRS调用场景合理性咨询
基于Clean Architecture与MediatR的CQRS场景规范分析
下面针对你提到的三个调用场景逐一分析是否符合规范,并给出实践建议:
1. 从NotificationHandler中调用Command
不符合规范。
Notification的本质是事件发布-订阅,用于告知系统中多个订阅者某个事件已发生,本身不应该触发新的业务操作(Command是主动发起的写操作)。这么做会让NotificationHandler承担了命令发起的职责,违反单一职责原则,同时会让业务流程变得隐蔽,难以追踪和调试。
替代方案:若需在事件发生后触发后续业务操作,应该在领域层的领域事件处理器中定义逻辑(领域层不依赖MediatR,可通过领域事件机制传递),再由应用层的适配器触发对应Command;或者在触发Notification的原CommandHandler中,直接编排后续Command的执行逻辑。
2. 在CommandHandler中调用CommandHandler
不推荐,不符合CQRS与Clean Architecture的职责分离原则。
每个Command对应单一的业务操作,其Handler应只聚焦处理当前Command的逻辑。跨CommandHandler调用会导致职责耦合,降低代码的可测试性和可维护性,同时破坏了Command的单一职责边界。
替代方案:
- 若业务需要多个操作原子执行,定义一个聚合Command(如
CreateOrderWithStockReservationCommand),在其Handler中调用领域服务完成多步业务逻辑,而非调用其他CommandHandler。 - 若需协调多个独立Command的执行,可在应用层新增流程编排服务,统一管理Command的调用顺序与事务一致性。
- 跨微服务场景下,通过消息队列异步触发目标Command,避免同步调用的耦合。
3. 在CommandHandler中调用QueryHandler
允许,但需遵守边界限制。
Command负责写操作,Query负责读操作,在CommandHandler中读取数据是合理的,但需注意:
- 仅读取当前Command执行必需的数据,不能依赖Query结果来决定核心业务逻辑(这类判断应放在领域层实现)。
- 确保数据一致性:若使用读写分离架构,需读取主库数据以获取最新状态。
- 优先通过领域仓储或领域服务读取数据,而非直接调用QueryHandler,这更符合Clean Architecture的依赖倒置原则(应用层依赖领域层,而非同层的Query)。
核心原则参考
- Clean Architecture:核心为依赖倒置,所有依赖指向领域层;应用层(Command/Query)作为领域层与外层的适配器,不应包含核心业务逻辑。
- CQRS:Command与Query分离,Command专注修改状态,Query专注读取状态,避免读写逻辑混合;两者可共享领域模型,但应保持操作边界清晰。
- MediatR实践:Notification用于事件通知,无返回值;Command为单一操作,Handler应保持简洁,仅处理当前Command的业务流程。
内容的提问来源于stack exchange,提问作者Ahmad
相关产品推荐
相关产品推荐

