DDD工程结构说明
文档
本工程采用DDD的架构风格,经过组内DDD实践的沉淀形成的工程规范 DDD实践的参考文档详见:
工程结构:
--client/
|-- src
    |----|-- main
    |----|----|-- java
    |----|----|----|-- com.sankuai.crayfish.xxxx
    |----|----|----|----|-- service -- thrift服务
    |----|----|----|----|-- model -- thrift对象定义
--server/
    |-- deploy
    |-- src
    |----|-- main
    |----|----|-- java
    |----|----|----|-- com.sankuai.crayfish.xxxx
    |----|----|----|-- application -- 应用层
    |----|----|----|----|-- service -- 应用服务
    |----|----|----|----|-- factory -- 对象转换工程(非必须)
    |----|----|----|----|-- validator -- 应用层参数校验(非必须)
    |----|----|----|-- domain -- 领域层
    |----|----|----|----|-- aggragate -- 聚合层
    |----|----|----|----|-- convertor -- 对象转换(非必须)
    |----|----|----|----|-- entity -- 实体
    |----|----|----|----|-- event -- 领域事件(非必须)
    |----|----|----|----|-- repository -- 资源库行为
    |----|----|----|----|-- service -- 领域服务
    |----|----|----|----|-- valueobj -- 值对象
    |----|----|----|---| remote -- 远程调用接口申明(Interface)
    |----|----|----|-- infrustructure -- 基础设施层
    |----|----|----|----|-- annotation -- 注解
    |----|----|----|----|-- cache -- 缓存配置
    |----|----|----|----|-- common -- 公共目录
    |----|----|----|----|-- config -- 通用配置
    |----|----|----|----|-- mafka -- mq配置
    |----|----|----|----|-- http -- http接口
    |----|----|----|----|-- thrift -- thrift接口
    |----|----|----|----|-- repository -- 资源库
    |----|----|----|----|----|-- impl -- 资源库实现
    |----|----|----|----|----|----|-- convertor -- 对象转换(非必须)
    |----|----|----|----|----|-- persist -- 持久化
    |----|----|----|----|----|----|-- mapper -- 数据库mapper
    |----|----|----|----|----|----|-- model -- DO对象  
    |----|----|----|----|-- remote -- 远程调用(实现)
    |----|----|----|----|----| impl -- 远程调用(接口实现)
    |----|----|----|----|----| model -- 远程调用(thrift层对象申明)
    |----|----|----|----|-- util -- 对象转换
    |----|----|----|-- Application.java(启动类)
    |----|----|-- resources -- 资源
    |----|----|----|-- mabatis -- db配置
    |----|----|----|-- spring -- spring配置
    |----|----|----|-- application.properties -- 配置文件
    |----|----|-- profiles
下面针对每层进行说明:
应用层
应用服务是领域模型的直接客户,应用层要尽量简单,不包含业务规则或者知识,而只为下一层(指领域层)中的领域对象协调任务,分配工作,使它们互相协作。
领域层提供了细粒度的领域模型对象,不利于它的客户端调用。因此,“基于 KISS(Keep It Simple and Stupid)原则或最小知识原则,我们希望调用者了解的知识越少越好,调用变得越简单越好,这就需要引入一个间接的层来封装。这就是应用层存在的主要意义
目录说明
【service】放置应用层服务
【factory】放置应用层对象转换的工厂,非必须,有些情况下不需要对象转换的工厂
【validator】应用层参数校验逻辑的放置目录,`非必须,有些情况下不需要参数校验,参数校验应该遵循约定,具体参考实践文档
开发规约:
1.【强制】禁止在应用层写任何领域逻辑,仅负责协调领域模型对象,通过它们的领域能力来组合完成一个完整的应用目标
2.【强制】与横切关注点相关的内容应该放在应用层
3.【强制】thrift接口参数校验属于横切关注点,应该放在应用服务来做
领域层
DDD架构风格的核心层,领域逻辑的主要载体
aggregate 聚合
Eric Evans 阐释了何谓聚合模式:“将实体和值对象划分为聚合并围绕着聚合定义边界。选择一个实体作为每个聚合的根,并允许外部对象仅能持有聚合根的引用。作为一个整体来定义聚合的属性和不变量(Invariants),并将执行职责(Enforcement Responsibility)赋予聚合根或指定的框架机制。”
entity 实体
实体有自己的生命周期,他的生命周期从属于聚合根。能够以主体类型的形式表达领域逻辑中具有个性特征的概念,而这个主体的状态在相当长一段时间内会持续地变化,因此需要有一个身份标识(Identity) 来标记它。
一个典型的实体应该具备三个要素:
- 身份标识
- 属性
- 领域行为
规约
1.【强制】实体对象的命名以Entity结尾。比如UserEntity、CompanyEntity
valueobj 值对象
值类型用于度量和描述事物,是否拥有唯一的身份标识才是实体与值对象的根本区别
规约
1.【强制】值对象的命名规则为 name + Value
event 领域事件
发生在领域中的一些事件,将领域中所发生的活动建模成一系列的离散事件,每个事件都用领域对象来表示,领域事件是领域模型的组成部分,表示领域中过去发生的事情。
remote 远程调用
领域层remote只放置rpc接口的申明,具体实现放在基础设施层
service 领域服务
领域服务(Domain Service)代表了在名词世界(面向对象)中对动词的封装(接口),它封装了领域行为。表示一个无状态的操作
前提在于,这一领域行为在实体或值对象中找不到容身之处。换言之,当我们针对领域行为建模时,需要优先考虑使用值对象和实体来封装领域行为,只有确定无法寻觅到合适的对象来承担时,才将该行为建模为领域服务的方法。
repository 资源库
只定义Interface,代表了一种行为,实现放在基础设施层
convertor 转换器
非必须,如果需要这样的逻辑,放在转换器里
基础设施层
基础设施的职责是为应用程序的其他部分提供技术支持。
Http http接口
Thrift thrift接口
Config 通用配置
Repository 资源库
Remote Rpc调用实现
--|【impl】 Rpc调用实现
--|【model】Rpc调用需要的对象
--|【impl】领域层定义资源库行为的实现
--|---|--【convertor】领域层对象和持久层对象的转换服务 -- 非必须
--|【persist】持久层mapper、DO
Cache 缓存配置
Annotation 注解
Mafka mq配置