DDD架构

Posted 造 山

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了DDD架构相关的知识,希望对你有一定的参考价值。

一、DDD架构相关概念

来自小张的博客

1.1什么是DDD

领域驱动设计,即Domain Driven Design(DDD)。

DDD是一套完整而系统的设计理论与方法,使得你的设计思路能够更加清晰,设计过程更加规范。
DDD 善于处理与领域相关的拥有高复杂度业务的产品开发

总之,DDD是专门为解决复杂性而诞生一套完整的理论方法

DDD落地实现离不开Clean架构、六边形架构、CQRS、Event Source等思想。

1.2 DDD相关概念

  • 领域:用来限定业务边界和范围
  • 子域:领域进一步划分就是子域
  • 核心域:核心域应该就是公司的主要业务,简单来说就是公司最盈利的业务。
  • 通用域:见明知意,就是不管什么业务,都会涉及到比较通用的范畴,例如登录、授权、网关等。随着业务的发展也可能发展成为核心域。
  • 支撑域:支撑业务系统正常运行的业务,但是不处于核心地位。优先级较低,当然随着业务的发展也可能发展成为核心域;例如:物流对于淘宝来说一开始就是支撑域,后来发展成为了核心域
  • 通用语言:在事件风暴过程中,通过团队交流达成共识的,能够简单、清晰、准确描述业务涵义和规则的语言
  • 限界上下文:通用语言和领域对象,提供的上下文环境,保证在领域之内的一些术语、业务相关对象等(通用语言)只有唯一一个确切的含义。领域边界就是通过限界上下文来定义的,是划分微服务的重要依据。
  • 聚合:由业务和逻辑紧密关联的实体和值对象组合而成的。聚合是数据修改和持久化的基本单元,每一个聚合对应一个仓储,实现数据的持久化特点:高内聚、低耦合,它是领域模型中最底层的边界,可以作为拆分微服务的最小单位
  • 聚合根:如果把聚合比作组织,聚合根则是组织的负责人,聚合根也叫做根实体,它不仅仅是实体,还是聚合的管理者
  • 实体:有 ID 标识,通过 ID 判断相等性,ID 在聚合内唯一即可。
  • 值对象 :无 ID,不可变,无生命周期,用完即扔
  • 领域事件:领域事件是领域模型中非常重要的一部分,用来表示领域中发生的事件。一个领域事件将导致进一步的业务操作,在实现业务解耦的同时,还有助于形成完整的业务闭环,可以通过event,mq等实现,达到最终一致性,和解耦目的

跨多个实体的业务逻辑通过领域服务来实现,跨多个聚合的业务逻辑通过应用服务来实现

二、DDD架构

DDD 分层架构就是优化后的四层架构。 从上到下依次是:用户接口层、应用层、领域层和基础层。

2.1 DDD分层架构:

2.1.1 DDD封层架构

  • 用户接口层:负责向用户显示信息和解释用户指令。这里的用户可能是:用户、程序、自动化测试和批处理脚本等等。
  • 应用层:很薄的一层,理论上不应该有业务规则或逻辑,主要面向用例和流程相关的操作。但应用层又位于领域层之上,因为领域层包含多个聚合,所以它可以协调多个聚合的服务和领域对象完成服务编排和组合,协作完成业务操作。此外,应用层也是微服务之间交互的通道,它可以调用其它微服务的应用服务,完成微服务之间的服务组合和编排。
  • 领域层:是实现企业核心业务逻辑,通过各种校验手段保证业务的正确性。领域层主要体现领域模型的业务能力,它用来表达业务概念、业务状态和业务规则。领域层包含聚合根、实体、值对象、领域服务等领域模型中的领域对象
  • 基础层:是贯穿所有层的,它的作用就是为其它各层提供通用的技术和基础服务,包括第三方工具、驱动、消息中间件、网关、文件、缓存以及数据库等。比较常见的功能还是提供数据库持久化。

DDD 分层架构有一个重要的原则:每层只能与位于其下方的层发生耦合。

2.1.2 DDD架构与MVC架构

DDD 分层架构中的要素其实和三层架构类似,只是在 DDD 分层架构中,这些要素被重新归类,重新划分了层,确定了层与层之间的交互规则和职责边界

2.2 整洁架构(洋葱架构)

  • 在整洁架构里,同心圆代表应用软件的不同部分,从里到外依次是领域模型、领域服务、应用服务和最外围的容易变化的内容,比如用户界面和基础设施。
  • 整洁架构最主要的原则是依赖原则,它定义了各层的依赖关系,越往里依赖越低,代码级别越高,越是核心能力。外圆代码依赖只能指向内圆,内圆不需要知道外圆的任何情况。

    在洋葱架构中,各层的职能划分:
  • 领域模型实现领域内核心业务逻辑,它封装了企业级的业务规则。领域模型的主体是实体,一个实体可以是一个带方法的对象,也可以是一个数据结构和方法集合。
  • 领域服务实现涉及多个实体的复杂业务逻辑。应用服务实现与用户操作相关的服务组合与编排,它包含了应用特有的业务流程规则,封装和实现了系统所有用例。
  • 最外层主要提供适配的能力,适配能力分为主动适配和被动适配。主动适配主要实现外部用户、网页、批处理和自动化测试等对内层业务逻辑访问适配。被动适配主要是实现核心业务逻辑对基础资源访问的适配,比如数据库、缓存、文件系统和消息中间件等。
  • 红圈内的领域模型、领域服务和应用服务一起组成软件核心业务能力。

2.3 CQRS架构(更改查询隔离架构)

  • CQRS — Command Query Responsibility Segregation,故名思义是将 command 与 query 分离的一种模式。
  • command :命令则是对会引起数据发生变化操作的总称,即我们常说的新增,更新,删除这些操作,都是命令。
  • Query:查询则和字面意思一样,即不会对数据产生变化的操作,只是按照某些条件查找数据。

    适用场景:
  • 查询数据复杂
    – 写入数据通常聚焦在一个领域或聚合内
    – 查询的数据结构复杂,跨域多个聚合的数据组合
  • 读写分离
    – 读数据比写数据频繁的多
    – 通过读写分离提高系统的性能,可以灵活的使用不同的数据库技术实
    缺点:
  • 数据一致性
    – 数据的写入与事件触发更新不在同一个事务
    – 两份数据可能异构存储如何保证最终一致性
  • 基础实施不成熟
    – CQRS大多是通过手工的读写分离实现
    – 缺少具有统治地位的成熟框架

2.4 六边形架构(端口适配器架构)

六边形架构的核心理念是:应用是通过端口与外部进行交互的

下图的红圈内的核心业务逻辑(应用程序和领域模型)与外部资源(包括 APP、Web 应用以及数据库资源等)完全隔离,仅通过适配器进行交互。它解决了业务逻辑与用户界面的代码交错问题,很好地实现了前后端分离。六边形架构各层的依赖关系与整洁架构一样,都是由外向内依赖。

六边形架构将系统分为内六边形和外六边形两层,这两层的职能划分如下:红圈内的六边形实现应用的核心业务逻辑;外六边形完成外部应用、驱动和基础资源等的交互和访问,对前端应用以 API 主动适配的方式提供服务,对基础资源以依赖倒置被动适配的方式实现资源访问。六边形架构的一个端口可能对应多个外部系统,不同的外部系统也可能会使用不同的适配器,由适配器负责协议转换。这就使得应用程序能够以一致的方式被用户、程序、自动化测试和批处理脚本使用。

这三种架构模型的设计思想微服务架构高内聚低耦合原则的完美体现,而它们身上闪耀的正是以领域模型为中心的设计思想,将核心业务逻辑与外部应用、基础资源进行隔离。

  • 红色框内部主要实现核心业务逻辑,但核心业务逻辑也是有差异的,有的业务逻辑属于领域模型的能力,有的则属于面向用户的用例和流程编排能力。按照这种功能的差异,我们在这三种架构中划分了应用层和领域层,来承担不同的业务逻辑。
  • 领域层实现面向领域模型,实现领域模型的核心业务逻辑,属于原子模型,它需要保持领域模型和业务逻辑的稳定,对外提供稳定的细粒度的领域服务,所以它处于架构的核心位置。
  • 应用层实现面向用户操作相关的用例和流程,对外提供粗粒度的 API 服务。它就像一个齿轮一样进行前台应用和领域层的适配,接收前台需求,随时做出响应和调整,尽量避免将前台需求传导到领域层。应用层作为配速齿轮则位于前台应用和领域层之间。

DDD专栏11微服务时代,单体架构淘汰了吗?

​ 上一讲我们重新回顾了DDD在代码设计层面的指导。通过讲解DDD的多种架构模型,解决了"DDD是什么?"的问题。DDD本质上并不是一个全新的技术或者框架,他也是和MVC架构一样,对业务逻辑进行编排和重组后形成的一种逻辑结构。最后,也提出了一种比较直接的DDD代码设计指导方式,就是菱形架构。但是还只介绍了菱形架构是什么,还没有介绍菱形架构到底如何指导程序设计。这一讲,我们将通过讲解菱形架构之间如何协作的问题,来集中解决"DDD到底干什么"的问题。

DDD视角下的微服务

​ 我们这一讲是对DDD进行重新审视,那我们首先从专栏最开始介绍的系统老化的问题说起。在专栏的第一篇,详细的分析了系统老化的各种问题,也提到了DDD使用限界上下文这样一个新的概念来对整个软件进行切分。但是,当时由于对DDD的讲解还不够深,所以对这个问题只能点到为止。现在,当我们经过对DDD一轮的讲解后,再回头来看系统老化的问题,就会发现,系统老化的根源在于没有守住限界上下文

​ 为什么这么说呢?我们回想一下,在DDD中,我们看到的表象是DDD定义了非常多的逻辑边界,限界上下文、聚合、防腐层等等,不断的规定业务代码能访问哪些功能,不能访问哪些功能。但是在传统的MVC架构中,这些边界在代码层面其实也是存在的,例如很多团队会要求只能通过接口形成直接依赖,Controller只能调用Service,不能直接调用DAO等。但是MVC架构在纵向的业务层面来看,每一层的代码与他的上下文都是绑定的,各种业务线是混杂在一起的。也就是说他们的知识语境是没有切割开的。整个架构看起来会像一座大山,内部虽然有很明显的岩层分隔,但是从外部看&#

以上是关于DDD架构的主要内容,如果未能解决你的问题,请参考以下文章

多研究些架构,少谈些框架-- 微服务和充血模型(转)

实践篇教你玩转微服务--基于DDD的微服务架构落地实践之路

DDD领域驱动设计在微服务架构的应用

DDD专栏7:DDD如何指导微服务设计实现

DDD兴起的原因以及与微服务的关系

DDD+SOA的事件驱动微服务读写分离架构,读后随笔