目前团队大多数项目都是基于DDD分层架构开发的,而不是传统的MVC模式,这就让很多之前没有接触过DDD思想的同学在刚开始接触项目的时候有点懵。那么什么DDD?这种DDD项目结构和之前的有哪些不同,我该如何开发我的代码,开发不同职责的代码该放在哪里?下面就我的理解,说一说DDD的分层架构。
传统开发分层
传统的数据驱动开发模式,View、Service、dao这种三层分层模式,我们会很自然的写出过程式代码,这种开发方式中的对象只是数据载体,而没有行为,是一种贫血对象模型。以数据为中心,以数据库ER图为设计驱动,分层架构在这种开发模式下可以认为是数据处理和实现的过程。
什么是DDD?
DDD 全称是 Domain-Driven Design,中文叫领域驱动设计,是一套应对复杂软件系统分析和设计的面向对象建模方法论。
以前的系统分析和设计是分开的,导致需求和成品非常容易出现偏差,两者相对独立,还会导致沟通困难,DDD 则打破了这种隔阂,提出了领域模型概念,统一了分析和设计编程,使得软件能够更灵活快速跟随需求变化。
DDD的术语与基本概念
- 领域:
领域就是范围。范围的重点是边界。领域的核心思想是将问题逐级细分来减低业务和系统的复杂度,这也是 DDD 的核心。
2.子域:
领域可以进一步划分成子领域,即子域。这是处理高度复杂领域的设计思想,它试图分离技术实现的复杂性。
3.核心域:
在领域划分过程中,会不断划分子域,子域按重要程度会被划分成三类:核心域、通用域、支撑域。
4.通用域:
中间件服务或第三方服务。
5.支撑域:
企业公共服务。
6.统一语言:
映射概念:统一概念。
定义上下文的含义。它的价值是可以解决交流障碍,不管是 RD、PM、QA 等什么角色,让每个团队使用统一的语言(概念)来交流,甚至可读性更好的代码。
7.限界上下文:
定义上下文的边界。领域模型存在边界之内。对于同一个概念
8.聚合:
聚合概念类似于包的概念,每个包里包含一类实体或者行为,它有助于分散系统复杂性,也是一种高层次的抽象,可以简化对领域模型的理解。
在定义聚合的时候,应该遵守不变形约束法则:
聚合边界内必须具有哪些信息,如果没有这些信息就不能称为一个有效的聚合;
聚合内的某些对象的状态必须满足某个业务规则:
一个聚合只有一个聚合根,聚合根是可以独立存在的,聚合中其他实体或值对象依赖与聚合根。
只有聚合根才能被外部访问到,聚合根维护聚合的内部一致性。
9. 聚合根:
一个上下文内可能包含多个聚合,每个聚合都有一个根实体,叫做聚合根,一个聚合只有一个聚合根。
10. 实体:
Domain 或 entity。(有唯一ID)
11. 值对象:
Domain 或 entity。(没有唯一ID)
常见的两种领域模型
- 贫血型
简单来说,就是 Domain Object 包含了不依赖于持久化的领域逻辑,而那些依赖持久化的领域逻辑被分离到 Service 层。
这种模式不在 Domain 层里依赖 DAO。持久化的工作还需要在 DAO 或者 Service 中进行。
缺点:
- Domain Object 的部分比较紧密依赖的持久化 Domain Logic 被分离到 Service 层。
- Service 过于厚重。
2. 充血模型
充血模型和第二种模型差不多,区别在于业务逻辑划分,将绝大多数业务逻辑放到 Domain 中,Service 是很薄的一层,封装少量业务逻辑,并且不和 DAO 打交道。即:Service (事务封装) —> Domain Object <—> DAO
DDD分层架构
目前我们团队项目分层主要是按照入下图DDD分层进行。
交互层:Web项目、Task项目、其它项目,为最顶层。
应用层:Service API项目和Service Provider项目,API项目不能对其它项目进行依赖,是整个领域的边界,向第三方提供接口。API项目包含了DTO对象和服务接口。
领域层:Domain项目,纯粹的领域模型,不包含任何数据访问,纯OO实现。
基础设施层:拆分为Component项目和Repository项目,Component项目提供公共组件,Repository项目提供领域存储,但是Domain项目不依赖于Repository项目,相反是Repository项目依赖于Domain项目,Repository项目以依赖注入的方式,注入到领域层和应用层。该设计与DDD的架构设计是存在差异的。
整个应用系统与Spring高度集成。Factory基于Spring创建prototype的聚合根、实体、VO。聚合根使用依赖注入动态注入Repository实现。因此,整个系统的依赖关系与高层架构设计吻合。
DDD好处
最大好处就是所有参与者围绕一个统一一致的领域模型工作,传统的分析模型和设计模型不再割裂,不管是做设计、做分析还是写代码、写文档,脑海中所构建的画面都是一致的。
DDD 是一个软件开发过程,它显式地把领域和设计放到了软件开发的核心,软件人员和业务人员被受到同样的重视,他们合作来构建领域模型,使得软件的交付质量更高且维护成本更低。
DDD 提出的分层架构,有效分离了业务复杂度和技术复杂度,凸显了领域模型,使得领域层的代码和领域模型保持高度一致。
统一语言非常重要,每个概念在各自的上下文中是清晰的无歧义的,同时要控制领域模型的复杂度,于是 DDD 在战略上提出了分离子域(问题域空间)和拆分 BC(解决方案空间)的模式,BC 间通过 Context Mapping 来集成。
DDD 在战术层面提出了很多模式(聚合,实体,值对象,服务,工厂,仓储),对领域模型中的元素进行了分类,并给出了每类元素在领域模型中的职责和特征,降低了领域模型的构建成本