在C#整洁架构中如何发起HTTP请求?DDD实践困惑求解
基于DDD/整洁架构的方案选择
首先直接排除选项C:直接在Blazor UI或API控制器中调用HttpClient并触发事件的做法完全违反了整洁架构的依赖原则和关注点分离。UI/API属于架构最外层,不应直接处理业务逻辑或外部服务调用,这会导致代码重复(Blazor和控制器要写两遍相同逻辑)、业务逻辑分散,后续维护和扩展成本极高。
接下来分析选项A和B:
选项B的问题
如果InstanceService是领域服务,那么它的职责应该是处理跨聚合根的领域逻辑,或者无法归属到单个聚合根的核心业务规则。直接在领域服务中发起HTTP请求是错误的——HTTP调用属于基础设施层的外部依赖,领域层作为内层,绝不应该依赖外层的基础设施组件,这会打破整洁架构的依赖方向,导致领域逻辑与外部实现耦合。
如果InstanceService是应用服务,虽然可以用来协调流程,但直接在其中发起请求仍然不如事件驱动的方式解耦,并非最优解。
推荐选项A(调整细节后)
选项A的核心思路是正确的,但需要明确各层职责边界,避免领域模型越权处理外部依赖:
领域层(Instance聚合根):
- 在
Instance中实现OperationA()方法,仅聚焦核心业务规则:比如检查当前Instance是否处于允许发起OperationA的状态(如未在执行其他操作、状态正常),然后更新自身状态(如标记为OperationAInProgress),最后触发领域事件OperationARequestInitiatedEvent(事件中携带Instance的标识等必要信息)。 - 领域模型只负责自身的状态变更和领域规则,不涉及任何外部调用。
- 在
基础设施/应用层:
- 实现事件处理器监听
OperationARequestInitiatedEvent,在处理器中调用HttpClient发起/operationA请求(这部分属于基础设施层的外部服务实现)。 - 请求完成(成功或失败)后,触发
OperationAFinishedEvent(可以是应用事件或集成事件),由对应的处理器执行后续操作:- 通过仓储更新Instance的最终状态(如
OperationASucceeded或OperationAFailed); - 执行其他业务流程(如通知相关方、更新关联数据等)。
- 通过仓储更新Instance的最终状态(如
- 实现事件处理器监听
这种方式的优势:
- 符合整洁架构的依赖规则:领域层不依赖外层,外层依赖领域层;
- 业务逻辑高度内聚在领域模型中,确保核心规则不分散;
- 事件驱动的设计解耦了领域操作与外部调用,后续修改外部请求实现(如更换HttpClient、调整请求逻辑)不会影响领域层;
- 无论是Blazor UI还是API控制器,只需调用应用层的用例(或直接触发领域操作),无需重复编写业务逻辑。
补充:如果你的OperationA需要跨多个聚合根协作,才需要引入领域服务,但从当前描述看,操作仅针对单个Instance,因此聚合根自身的方法足够。
内容的提问来源于stack exchange,提问作者Mathieu
相关产品推荐
相关产品推荐

