浅谈DDD(领域驱动设计)
背景
DDD是什么?
DDD是领域驱动设计(Domain Driven Design),是一个从系统分析到软件设计的方法论,是一种架构思想,是一种满足复杂需求的软件开发方法,模型有四级分层架构。
DDD由Eric Evans在2004年发表的书《领域驱动设计:软件核心负责性应对之道》提出,到微服务的使用而逐渐火起来。
DDD的目的是?
- 强调以业务优先,将问题域逐级细分,根据业务划分不同领域模块,解决系统架构不清晰的问题,解耦业务系统,使业务边界清晰
- 减少重构风险、可维护、可拓展
- 强调从设计到落地到开发,其思想都会贯穿
传统MVC三层架构
优点:分工很明确,清晰,很容易上手,适用于业务逻辑不复杂情况。
缺点然而,随着时间的增长,业务需求的迭代,系统的复杂性越来越高,维护成本也高。拓展性也差。
为了解决MVC的问题,DDD来了。
DDD四层架构
其框架如下图:
用户接口层 (interface)
1)用于接收外部输入的请求,负责向用户显示信息和解释用户指令。
2)负责接收请求参数,处理客户端发送的请求,并根据业务请求,将参数传递给应用层,并将应用层返回的结果再根据用户的需要进行组装,
业务应用层 (application)
主做业务逻辑处理,负责编排、转发、校验业务逻辑,协调领域对象执行任务,或者发送消息通知等
应用层下一层是领域层,也可以绕过领域层,直接访问基础层。
领域层 (domain)
系统的核心,封装核心业务逻辑,负责业务概念,业务状态信息及业务规则定义,即包含了该领域所有复杂的业务知识抽象和规则定义,如:实体,值对象,聚合(聚合根),领域服务,领域事件,仓储,工厂等规则定义
明确了需要解决的问题范围、及与其他业务域之间的关系和作业方式。
领域层模型大致如下:
基础层 (infrastructrue)
是业务与数据分离,为领域提供持久化机制、实现应用层、领域层与基础层的解耦,降低外部资源变化对应用的影响。
仓储层包含
- 数据访问层的全部代码,例如 mybatis的mapper接口,xml文件
- 工具类
- 实现领域层定义的仓储接口、网关接口
- Spring Configuration配置类
领域层相关术语
通用语言和限界上下文
通用语言是相关用户使用统一的语言,减少误解和偏差。降低沟通成本。
它有它的上下文环境,为了避免同样的概念或语义在不同的上下文环境中产生歧义
限界上下文就是领域的边界,而上下文则是语义环境。
不同的限界上下文之间可能有不同的模型,它们通过上下文映射来交互或集成。
划分技巧:一个界限上下文必须支持一个完整的业务流程。限界上下文是微服务拆分的依据,即每个限界上下文对应一个微服务。
实体(Entity)
实体的表现形式是实体类,这个类包含了实体的属性和方法,通过这些方法实现实体自身的业务逻辑。在 DDD 里,这些实体类通常采用充血模型,包含状态和行为。
然而,充血模型是什么呢?简单介绍下贫血模型和充血模型
- 贫血模型:只包含数据属性和对应的 getter 以及 setter及一些简单的业务逻辑,贫血模型将数据与操作分离。
- 充血模型:包含了数据属性以及引起属性发生状态变化的核心业务动作。
值对象(Value Object)
值对象:值对象可以属性集合,也定义为实体的单一属性,是一个没有标识符的对象。
优点:减少了实体表的数量,可以简单、清晰地表达业务概念
缺点:无法满足基于值对象的快速查询
实体和值对象代码举例
聚合和聚合根
聚合:是一些有关联性的实体、值对象的组合,用来支撑领域模型的行为。聚合内部实现事务一致性。
聚合根:是外部对象和聚合内部对象的唯一入口,以聚合根 ID 关联的方式接受外部任务和请求,外部对象不能直接访问聚合内实体。
领域服务
领域服务:当一些逻辑不属于某个实体活值对象时,则把这些逻辑单独拿出来放到领域服务中,表示领域中的一些操作或逻辑处理
领域事件
领域事件 = 事件发布 + 事件存储 + 事件分发 + 事件处理。用来表示领域中发生的事件。忽略不相关的领域活动,同时明确领域专家要跟踪或希望被通知的事情,或与其他模型对象中的状态更改相关联。比如,用户下单后,需要消息或者事件给积分系统领域增加用户积分、或者同步给仓库系统领域发货等。
资源库【Repository】
介于领域模型和数据模型之间,主要用于聚合的持久化和检索。
它隔离了领域模型和数据模型,以便我们关注于领域模型而不需要考虑如何进行持久化,同时提供了一些查询操作。
防腐层
防腐层(领域适配器):使领域模型与外部系统进行交互而不受污染,也被称适配层或者转换层
总结
DDD是面向对象编程的架构思想,不是高性能、高可用解决方案,是多种设计思想的汇总。
适用在解决业务的复杂性,如果对象模型非常复杂,建议采用 DDD
运用DDD,前期需要花大量时间设计好领域模型,保证后期的可拓展性和后期的可维护性,
笔者在了解完DDD领域模型后,与MVC对比再应用此框架,发现具体落地需要多种思量,得具体场景具体使用。同时希望大家了解完后,对后续的框架搭架有更近一层的思想。
总之:好的模型,可以沉淀资产,不好的模型,逐渐成为负载。
参考文档:
https://developer.aliyun.com/article/1583387
https://blog.csdn.net/tian830937/article/details/140847378
https://www.cnblogs.com/sTruth/p/17760144.html
作者:yana