用户工具


模块划分

包划分

代码样例

设计原则

  1. biz层,domain层是实现业务核心逻辑的地方。有且只有业务代码,对外部的基础设施的依赖应放到基础设施层
  2. biz层 (一个接口对应一个业务功能)
    1. 特点:调用1个或多个领域服务或实体,流程编排,共同实现一个业务功能。还包括鉴权,事务,事件,通知,日志等任务
  3. domain层(一个接口对应一个领域内功能)
    1. domain service 没有外部依赖,只有纯业务逻辑。可直接写单测无需mock
    2. 只定义repository,不实现
  4. 基础设施层屏蔽底层实现细节。biz层,domain层如果有依赖基础设施层的地方,只需要定义接口即可。全部统一由本层来实现

fangqiang 2023/12/06 09:47

值对象,实体,领域服务

  • 值对象: 只有数据和get、set方法
  • 实体:含有数据、和基本逻辑
    • 哪写方法可以放入领域服务?
      • 实体内的数据所能提供的功能方法,且方法不依赖其他外部资源
  • 领域服务:调用实体完成业务功能
    • 哪写方法可以放入领域服务?
      • 领域行为需要多个领域实体参与协作
      • 领域行为与状态无关
      • 领域行为需要与外部资源(尤其是DB)协作

函数放哪的原则

  • 遵守“信息专家模式”,谁有这个数据,谁处理
  • 值对象。完全没有业务功能
  • 实体。尽量将函数下沉到实体类(有利于复用、封装。 ddd的核心思想)
  • 领域服务。实在不能放入实体类的方法,放入领域服务类。(作为承担业务逻辑的最后的救命稻草)

看图

  • 左边:判断方法下沉到实体类
  • 右边:判断方法放在服务类


应用服务

  1. 获取用户参数
  2. 转成转成领域服务的参数
  3. 调用领域服务完成业务功能
  4. 接收领域服务返回的值
  5. 调用基础服务,完成其他操作(如:调用邮件服务发送邮件)
  6. 转换成用户的返回值,并返回

领域服务

  1. 接收该领域中的对象为参数
  2. 组合调用领域对象完成业务功能(领域服务没有具体逻辑,只负责组合调用,具体逻辑由领域对象完成)
  3. 返回该领域中的对象给应用服务层

聚合

  1. 将一些子对象封装成一个更上层的对象
  2. 聚合封装了对象之间复杂的关系网
  3. 聚合有自己的生命周期,一般随着一次请求而创建,请求结束而销毁

工厂

  • 如果对象(聚合,entity,VO)创建非常复杂可以,将创建过程封装到工厂方法汇中。

我们创建一个对象是为了使用这个对象提供的功能,而不是关心这个对象是怎么生成的。所以如果把复杂的创建逻辑给对象本身自己完成,则会让对象变得很重。

版本二