大佬教程收集整理的这篇文章主要介绍了DDD(Domain Driver Design)领域驱动模型,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
DP概念
DP 是 DDD 中的一个基础概念,是 DDD 中可以执行的一个最小单元,最直接的体现是,将业务相关的参数定义在一个特定的领域中(比如一个 class 文件),封装成一个具有精准定义,自我验证,拥有行为的 ValueObject。
行为指相关业务代码
Value Object
区别于 Entity,拥有 id,是一个表的实例,而 VO 没有 id,更多的强调数据,不需要对应任何表,只是一个数据的集合,一个值对象,它的一个最大特点是 Immutable(不可变性),这个值对象自从被创建出来后不会被改变,所以说这个对象中的属性最好都是被 private final 修饰。
DP原则
什么情况可以考虑使用 DP 进行业务优化?
1 接口清晰度,通过接口参数是否能够显示业务
2 数据校验和错误处理是否统一维护,数据校验的依赖性,比如地区号的获取依赖于电话号,那地区号校验就要放在“电话号”类中做校验
3 业务逻辑代码的清晰度,胶水代码是否存在于核心业务代码中,区分核心业务代码和非核心业务代码(胶水代码:从一些入参里抽取一部分数据,然后调用一个外部依赖获取更多的数据,然后通常从新的数据中再抽取部分数据用作其他的作用。)
View Object(VO)-- 视图对象,代表展示层需要显示的数据,通常由 DTO 转换后展示。
Data Transfer Object(DTO)-- 数据传输对象,主要作为 Application 层的入参和出参。
Entity - 基于领域逻辑的实体类,拥有 ID,它的字段和数据库储存不需要有必然的联系,不仅包含数据,还有行为,字段也不仅仅是 String 等基础类型,而应该尽可能用 Domain Primitive 代替,可以避免大量的校验代码。
Data Object(DO)- DO 是单纯的和数据库表的映射关系,每个字段对应数据库表的一个 column,DO 只有数据,没有行为。
Repository - 只负责定义 Entity 对象的存储和读取方法,返回对象一般为 Entity。
RepositoryImpl - 实现数据库存储读取的细节,通过加入 Repository 接口,底层的数据库连接可以根据实际情况用不同的实现类来替换。
Mapper(DAO) - DAO 对应的是一个特定的数据库类型的操作,CRUD。
Builder/Factory - 实现 DO 与 Entity 之间的转化。
Anti-Corruption Layer(ACL)- 防腐层,很多时候我们的系统会去依赖其他的系统,而被依赖的系统可能包含不合理的数据结构、API、协议或技术实现,如果对外部系统强依赖,会导致我们的系统被”腐蚀“。这个时候,通过在系统间加入一个防腐层,能够有效的隔离外部依赖和内部逻辑,无论外部如何变更,内部代码可以尽可能的保持不变。
ACL作用
ACL 原理
Domain Layer(领域层):Entity、Domain Primitive 和 Domain service 都属于领域层,领域层没有任何外部依赖关系。Domain Primitive 是无状态的。当某个行为影响到多个 Entity 时,属于跨实体的业务逻辑,在这种情况下就需要通过一个第三方的领域服务(Domain service)来完成。
Application Layer(应用层):Application service、Repository、ACL 类属于应用层,应用层依赖领域层,但不依赖具体实现。
Infrastructure Layer(基础设施层):ACL,Repository 等的具体实现类,通常依赖外部具体的技术实现和框架。
Domain-Driven Design(DDD):领域驱动设计,架构思路是先写 Domain 层的业务逻辑,然后再写 Application 层的组件编排,最后才写每个外部依赖的具体实现。
@H_616_76@
Repository:当成一个中性的类,使用语法如 find、save、remove,使用中性的 save 接口,然后在具体实现上根据情况调用 DAO 的 insert 或 update 接口,根据 Aggregate 的 ID 是否存在且大于 0 来判断一个 Aggregate 是需要更新还是插入。这样做是为了概念上和数据库解绑,不去直接使用 insert、SELEct、update、delete。
Repository 复杂实现:一次操作中,并不是所有 Aggregate 里的 Entity 都需要变更,但是如果用简单的写法,会导致大量的无用 DB 操作。具体实现参照:Repository复杂实现
Entity
通过聚合根保证主子实体的一致性
在稍微复杂一点的领域里,通常主实体会包含子实体,这时候主实体就需要起到聚合根的作用,即:
不可以强依赖其他聚合根实体或领域服务
一个实体类不能直接在内部直接依赖一个外部的实体或服务。正确的对外部依赖的方法有两种:
任何实体的行为只能直接影响到本实体(和其子实体),不能直接修改其他的实体类。
Interface层
1 网络协议的转化:通常这个已经由各种框架给封装掉了,我们需要构建的类要么是被注解的 bean,要么是继承了某个接口的 bean。
2 统一鉴权:比如在一些需要 AppKey+Secret 的场景,需要针对某个租户做鉴权的,包括一些加密串的校验
3 Session 管理:一般在面向用户的接口或者有登陆态的,通过 Session 或者 RPC 上下文可以拿到当前调用的用户,以便传递给下游服务。
4 限流配置:对接口做限流避免大流量打到下游服务
5 前置缓存:针对变更不是很频繁的只读场景,可以前置结果缓存到接口层
6 异常处理:通常在接口层要避免将异常直接暴露给调用端,所以需要在接口层做统一的异常捕获,转化为调用端可以理解的数据格式
7 日志:在接口层打调用日志,用来做统计和 debug 等。一般微服务框架可能都直接包含了这些功能。
规范:
Application层
1 Applicationservice 应用服务:最核心的类,负责业务流程的编排,但本身不负责任何业务逻辑。
2 DTO Assembler:负责将内部领域模型转化为可对外的 DTO。
3 Command、Query、Event 对象:作为 Applicationservice 的入参。
4 返回的DTO:作为 Applicationservice 的出参。
Command、Query、Event对象
CQE vs DTO
CQE:CQE 对象是 Applicationservice 的输入,是有明确的“意图”的,所以这个对象必须保证其“正确性”。
DTO:DTO 对象只是数据容器,只是为了和外部交互,所以本身不包含任何逻辑,只是贫血对象。
规范
Application service 是业务流程的封装,不处理业务逻辑
判断是否业务流程的几个点:
1 不要有 if/else 分支逻辑:通常有分支逻辑的,都代表一些业务判断,应该将逻辑封装到 Domain service 或者 Entity 里,但这不代表完全不能有 if 逻辑,比如:
ItemDO item = itemservice.getItem(cmd.getItemId());
if (item == null) {
throw new IllegalArgumentexception("Item not found");
}
但这里仅仅代表了中断条件,具体的业务逻辑处理并没有受影响。
2 不要有任何计算逻辑。
3 数据的转化交给其他对象来做,数据的转化可以交给其他对象来做。
各个包结构的简要功能描述
以上是大佬教程为你收集整理的DDD(Domain Driver Design)领域驱动模型全部内容,希望文章能够帮你解决DDD(Domain Driver Design)领域驱动模型所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。