首页/开发/系统分析与架构设计速查/领域服务与应用服务
需求分析与建模61 条

领域服务与应用服务

领域服务承载跨聚合的领域规则且无状态;应用服务负责编排用例:加载聚合、调用领域逻辑、提交事务、发布事件与权限校验,二者职责不应混同。

领域服务与应用服务

领域服务承载跨多个聚合或多个实体才能完成的领域规则,自身无状态,属于领域层;应用服务负责编排用例:加载聚合、调用领域逻辑、提交事务、发布事件并做权限校验,属于应用层。二者都是无状态的,区别在于关注点是业务规则还是流程编排。业务规则写进应用服务会导致多处重复,应用流程写进领域层会让模型依赖框架与事务设施。

对比

维度领域服务应用服务
关注点业务规则与不变量用例编排与事务边界
状态无状态无状态
依赖领域模型与领域接口仓储、领域服务、消息、鉴权
示例跨账户转账手续费计算提交订单用例的流程编排
测试纯业务输入输出,易做单元测试需要替身模拟仓储与消息

划分判断

  • 规则需要跨多个聚合或实体才能计算完整,考虑放入领域服务
  • 逻辑主要是“取数据、调用、保存、发事件”的顺序编排,属于应用服务
  • 规则只涉及单个聚合内部,直接写进聚合,不需要额外服务
  • 逻辑与技术设施强相关(事务、消息、鉴权),不要放进领域层
  • 同一规则在多个用例中重复出现,抽到领域服务或聚合中
  • 只有一次调用且无复用价值的流程,保持扁平,不要为对称而分层

基本信息

命名习惯领域服务用业务动作命名,应用服务以用例名称命名
事务边界通常由应用服务控制,聚合内部负责不变量
常见误区把领域服务当工具类,塞入与业务无关的通用方法
与事务脚本区别事务脚本把规则与流程混在一起,难以复用与测试
落地收益规则集中后修改点唯一,重复实现的风险显著下降
如果领域服务只有一层转发、方法体只是调用仓储,通常说明它没有存在的必要,直接在应用服务里完成即可。
应用服务里堆积大量业务判断,是贫血模型的典型信号:规则散落、无法复用,同一规则在不同用例中实现不一致。

易错点

  • 业务规则写进应用服务,多个用例各自实现一遍,修改时漏改导致行为不一致
  • 把事务与框架逻辑放进领域层,领域模型无法脱离基础设施测试
  • 领域服务被当成通用工具类,混入日期处理、字符串拼接等无关方法
  • 为对称而分层,产生只做转发的空壳服务,调用链变长而信息没有增加
  • 用应用服务直接操作数据库表,绕过聚合与不变量约束

数据来源与参考

  • Eric Evans《Domain-Driven Design》
  • Vaughn Vernon《Implementing Domain-Driven Design》
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌