Document类入库前外部授权的最优实现方案咨询
方案对比与优化建议
这是个非常务实的领域模型设计问题,咱们来逐一拆解两个方案的优劣,再聊聊有没有更贴合领域驱动设计思想的优化方向:
方案一分析
- 优势:封装性做得很直接,
Document自己包揽了“触发授权”和“更新状态”的逻辑,UseCase层只需要调用doc.authorize(authorizator)就能完成授权操作,不用关心内部细节,符合迪米特法则。 - 劣势:最大的问题是职责越界——
Document作为核心领域对象,本该只负责维护自身的业务状态和行为,现在却直接依赖了外部的IExternalAuthorizator服务。这会导致:- 单元测试变复杂:测试
Document时必须mockIExternalAuthorizator,增加了测试成本; - 扩展性差:如果后续授权逻辑需要调整(比如新增多场景授权、加重试机制),
Document不得不跟着修改,违反了单一职责原则; - 领域模型不纯粹:外部服务的侵入会让
Document的业务边界变得模糊。
- 单元测试变复杂:测试
方案二分析
- 优势:这是个明显的进步,完美实现了职责分离!
Document回归了领域对象的本质:只负责接收AuthorizationResult并更新自身状态,完全不依赖任何外部服务,测试起来只需要传入不同的结果就能验证状态逻辑,非常清爽;- UseCase层承担了“协调者”的角色:负责调用外部授权服务、拿到结果后再通知
Document更新,逻辑清晰,后续如果要在授权前后加日志、参数校验,都可以在UseCase里轻松扩展,不会影响领域模型。
- 劣势:相比方案一,UseCase层多了一行调用代码,看起来稍微繁琐一点,但这是职责清晰带来的微小代价,完全可以接受。
第三种更优方案:引入领域服务(Domain Service)
如果你的项目有一定规模,或者后续授权逻辑可能会变得复杂,推荐引入领域服务来进一步解耦,让各角色的职责更纯粹:
- 定义
DocumentAuthorizationService领域服务,它依赖IExternalAuthorizator,提供一个authorize(Document doc)方法; - 在这个服务内部,先调用
authorizator.authorize(doc)获取授权结果,再调用doc.applyAuthorizationResult(result)(对应方案二中的authorize方法)完成状态更新; - UseCase层的代码会非常简洁:实例化
Document后,调用documentAuthorizationService.authorize(doc),最后执行repo.save(doc)即可。
这个方案的核心好处:
Document彻底成为纯粹的领域对象,只关心自身业务状态,完全不涉及外部服务调用;- 授权的核心逻辑被封装在领域服务中,UseCase层只需要调用服务方法,不用关心内部流程,代码可读性和可维护性大幅提升;
- 扩展性极强:后续如果要新增授权前置校验、重试机制、多渠道授权,只需要修改
DocumentAuthorizationService,不会影响Document和UseCase,完美符合开闭原则; - 测试更友好:各模块的测试边界清晰,分别mock对应的依赖即可。
总结建议
- 如果项目规模小、授权逻辑简单,方案二是性价比最高的选择,它在代码复杂度和职责分离之间做了很好的平衡;
- 如果项目有长期扩展需求、追求更纯粹的领域模型,第三种领域服务方案会是更长远的最优解;
- 方案一因为让领域对象依赖外部服务,会增加后续维护成本,不推荐长期使用。
内容的提问来源于stack exchange,提问作者user1094627
相关产品推荐
相关产品推荐

