什么是领域驱动设计模型?
DDD全称为(Domain-Driven Design,简称DDD),领域驱动设计
基础概念
领域: 领域是DDD中最大的概念,主要确定边界范围,领域又分为核心域(核心业务逻辑)、通用域(公共业务逻辑)、支撑域(基础第三方业务逻辑);
界限上下文:在界限上下文中要建立通用语言,望文生义,就是大家都看得到,认可的叫法就是通用语言;界限上下文主要是来确定领域边界;
聚合根:聚合根式一个根实体,里面包含了许多聚合,而且该聚合根有唯一标识,可以协调里面的每个聚合,外部访问只能根据聚合根的唯一标识进行访问里面的私有内容;
聚合:聚合是一个整体,把所有的实体和值对象组织起来,做到一个聚合的作用,确保领域在执行逻辑的时候,确定数据一致性,从设计上避免数据不一致性;
实体:整体概念的多个属性归集到的属性集合,有唯一标识id,实体是实实在在的业务对象,具有业务属性、行为和业务逻辑;
值对象:若干个属性的集合,只有数据初始化操作和有限的不涉及修改数据的行为,不包含业务逻辑
应用层{application}
应用服务位于应用层。用来表述应用和用户行为,负责服务的组合、编排和转发,负责处理业务用例的执行顺序以及结果的拼装。
应用层的服务包括应用服务和领域事件相关服务。
应用服务可对微服务内的领域服务以及微服务外的应用服务进行组合和编排,或者对基础层如文件、缓存等数据直接操作形成应用服务,对外提供粗粒度的服务。
领域事件服务包括两类:领域事件的发布和订阅。通过事件总线和消息队列实现异步数据传输,实现微服务之间的解耦。
领域层{domain}
领域服务位于领域层,为完成领域中跨实体或值对象的操作转换而封装的服务,领域服务以与实体和值对象相同的方式参与实施过程。
领域服务对同一个实体的一个或多个方法进行组合和封装,或对多个不同实体的操作进行组合或编排,对外暴露成领域服务。领域服务封装了核心的业务逻辑。实体自身的行为在实体类内部实现,向上封装成领域服务暴露。
为隐藏领域层的业务逻辑实现,所有领域方法和服务等均须通过领域服务对外暴露。
为实现微服务内聚合之间的解耦,原则上禁止跨聚合的领域服务调用和跨聚合的数据相互关联。
基础层{infrastructrue}
基础服务位于基础层。为各层提供资源服务(如数据库、缓存等),实现各层的解耦,降低外部资源变化对业务逻辑的影响。
基础服务主要为仓储服务,通过依赖反转的方式为各层提供基础资源服务,领域服务和应用服务调用仓储服务接口,利用仓储实现持久化数据对象或直接访问基础资源。
接口层{interfaces}
接口服务位于用户接口层,用于处理用户发送的Restful请求和解析用户输入的配置文件等,并将信息传递给应用层。
取之于官网架构描述:
共有三个垂直层:接口、应用程序和域,每个层都由不同类型的基础设施支持。
DDD官网模型
{接口}
该层包含与其他系统交互的所有内容,例如 Web 服务、RMI 接口
或 Web 应用程序和批处理前端。它处理口译、验证和翻译
传入的数据。它还处理传出数据的序列化,例如跨 HTTP 的 HTML 或 XML
Web 浏览器或 Web 服务客户端,或用于远程 Java 客户端的 DTO 类和分布式外观接口。
{应用}
应用层负责驱动应用的工作流程,匹配手头的用例。
这些操作与接口无关,可以是同步的,也可以是消息驱动的。
这一层非常适合跨越事务、高级日志记录和安全性。
应用层在域逻辑方面很薄——它只是协调域
层对象来执行实际工作。
{领域}
领域层是软件的核心,这就是有趣的事情发生的地方。
每个聚合有一个包,每个聚合都属于实体、值对象、领域事件、
存储库接口,有时还有工厂。
业务逻辑的核心,比如判断一个处理事件是否应该注册,货物如何交付
受到处理的影响,属于这里。聚合、类和方法的结构和命名
领域层应该遵循无处不在的语言,并且你应该能够向领域专家解释
通过绘制一些简单的图表并使用实际的类和方法名称,这部分软件是如何工作的
的源代码。
{基础设施}
除了三个垂直层外,还有基础设施。
所有三层都以不同的方式,促进层之间的通信。简单来说,
基础设施由独立于我们的应用程序存在的所有内容组成:外部库,
数据库引擎、应用程序服务器、消息传递后端等。
此外,我们考虑将其他层粘合到基础设施的代码和配置文件作为基础设施层的一部分。
例如,查看持久性方面、数据库模式定义、Hibernate 配置和映射文件
存储库接口的实现是基础设施层的一部分。
虽然在任何给定情况下对哪种代码属于基础设施层给出一个可靠的定义可能很棘手,
应该可以在纯 Java 单元/场景测试中完全排除基础设施,并且仍然能够
使用领域层和可能的应用层来解决核心业务问题。
有什么作用?优势?缺点?
作用:
它像是更小粒度的迭代设计,它的最小单元是领域模型(Domain Model),所谓领域模型就是能够精确反映领域中某一知识元素的载体,这种知识的获取需要通过与领域专家(Domain Expert)进行频繁的沟通才能将专业知识转化为领域模型。
优势:
接触到需求第一步就是考虑领域模型,而不是将其切割成数据和行为,然后数据用数据库实现,行为使用服务实现,最后造成需求的首肢分离。DDD让你首先考虑的是业务语言,而不是数据。重点不同导致编程世界观不同。
DDD可以更加领域模型界限上下文边界快速拆分微服务,实现系统架构适应业务的快速变化,例如:系统的用户量并发量增长得很快,单体应用很快就支持不了,如果我们一开始就采用DDD领域驱动设计,那我们就能很快的把服务拆分成多个微服务,以适应快速增长的用户量。
DDD 是一套完整而系统的设计方法,它能带给你从战略设计到战术设计的标准设计过程,使得你的设计思路能够更加清晰,设计过程更加规范。
使用DDD可以降低服务的耦合性,让系统设计更加规范,即使是刚加入团队的新人也可以根据业务快速找到对应的代码模块,降低维护成本。
DDD 善于处理与领域相关的拥有高复杂度业务的产品开发,通过它可以建立一个核心而稳定的领域模型,有利于领域知识的传递与传承。
DDD 强调团队与领域专家的合作,能够帮助你的团队建立一个沟通良好的氛围,构建一致的架构体系。
DDD 的设计思想、原则与模式有助于提高你的架构设计能力。
无论是在新项目中设计微服务,还是将系统从单体架构演进到微服务,都可以遵循 DDD 的架构原则。
缺点:
学习成本较高:掌握DDD需要一定的领域知识和编程经验,对于初学者来说,学习成本较高。
过度设计:在实际项目中,过度关注领域划分可能导致系统设计过于复杂,反而降低开发效率。
领域建模挑战:对于某些复杂业务场景,领域建模可能存在一定的困难,需要开发者具备较高的业务理解和建模能力。
模型图:
各层之间的关系?
api:
存放要对外暴露的rpc||http的service层
web:
跟传统的controller层作用一样,用于校验和转发等简单业务。
biz(business):
业务逻辑层,等于传统设计的service层。其中api需要实现的业务逻辑都在biz,不对外提供。
dal(Data Access Layer):
与传统的dao层一致,主要用于数据的交互。mysql、hbase、es
tomain:
存放通用的,可以对外暴露的Object、枚举、常量类、方法等工具。制定标准,提供给下游使用。
config:
存放通用的配置,如缓存,中间件,日志、消息消费。但具体的业务实现还是在biz重实现。
client:
存放调用第三方平台,外部服务等rpc或http借口等。但具体的业务实现还是在biz重实现。