DDD分层架构规范
分层架构图
简述
Controller层:接口层,负责对前端展示的路由和适配;如果需要的话,消费事件和发送消息通知等也可以放在这里;
Application层:主要负责获取输入,组装上下文,参数校验,调用领域层做业务处理
Domain层:领域是应用的核心,主要是封装了核心业务逻辑,通过领域服务(Domain Service)、领域对象(Entity)的方法对App层提供业务实体和业务逻辑计算;
Infrastructure层:主要负责技术细节问题的处理,比如数据库的CRUD、搜索引擎、文件系统、分布式服务的RPC等;
分层说明
- APP层采用CQE模型,查询和命令分离
- AppService调用实体和IRepo进行编排实现简单业务,通过调用DomainService实现复杂业务场景
- AppService和DomainService均为无状态服务
- App只允许调用仓储以及实体自带方法,不允许写任何方法,避免出现AppService过大的情况
- DomainService封装所有跨实体的业务逻辑
- 为避免出现AppService之间或者Domainservice之间相互调用,抽取出两者公共部分为一个Helper
聚合根和实体
- 按聚合根分包,和包名一样的实体为聚合根
- 可以识别的聚合根就写成聚合根,否则做成实体
- 聚合根的一致性由自己保障
- 跨实体的操作放到领域服务中
领域对象实体为充血模型,为一般业务对象,具备业务属性和业务行为
- 实体都有自己的唯一标识通常
- 实体可以不和表一一对应,通常操作单个表,可以操作多表
领域服务
某个操作过程或转换过程不是实体的职责时,我们便应该将该操作放在一个单独的接口中,即领域服务。
- 用于实现某个领域的任务,不适合放在实体对象上时,就放在领域服务上
- 放在实体的静态方法上有悖DDD
- 避免在实体中调用资源库,数据通过AppService调用Repo传入
- 如果有复杂逻辑,其中间的状态依赖前面步骤结果查询数据库作为后续逻辑的输入,通过把Repo传入到Domainservice的方式达到无状态效果
传输对象
- DTO:接受Controller层发来的请求,返回结果
- Entity :将DTO转换为要操作的领域层对象
无状态
- 一次请求所需的全部信息,要么都包含在这个请求里,要么可以从外部获取到(比如说数据库),服务本身不存储任何信息
- 有状态服务(stateful service)则相反,它会在自身保存一些数据,先后的请求是有关联的
- 无状态服务的优势在于可以很方便地水平伸缩