DDD(领域驱动设计) 核心概念浅析

news2024/11/19 11:22:59

文章目录

  • DDD(领域驱动设计) 核心概念浅析
    • 前言
    • 贫血模型
      • 什么是贫血模型
      • 贫血模型的优点
      • 贫血模型的缺点
    • 充血模型
      • 充血模型的优点
      • 充血模型的缺点
    • DP 概念
    • 抽象接口
    • 简单概念
      • 简单概念
      • 流程:
      • 实现
    • 统一语言和模型价值
      • DP 和 Entity 的区别
    • Aggregate(聚合)
    • 限界上下文
    • 防腐层(Anti-corruption layer)
      • 应用场景
      • 解决方案
      • 问题
    • 总结

DDD(领域驱动设计) 核心概念浅析

前言

大家好,这里是 Rocky 编程日记,喜欢后端架构中间件源码,该篇是对 DDD(领域驱动设计) 做了一个简短的概念梳理。文章分享出来,供大家学习交流,如若笔记中有不对的地方,那一定是当时我的理解还不够,希望你能及时提出。
在这里插入图片描述

贫血模型

什么是贫血模型

在日常项目中,我们也会把大部分的业务逻辑实现都写到 service 层里,而不是写在我们的实体类中。即实体类里面只包含了对象的属性以及属性的 get 、set 方法,不包括该对象的具体行为,业务逻辑都处于 service 层。

贫血模型的优点

将业务逻辑分离了出去,使得系统耦合度降低,对象只用作承载和传输暑假。

贫血模型的缺点

不符合面向对象编程 (OOP) 的思想,对象只有属性没有行为,没有生命,不是真正的对象。

业务逻辑分离到了 service 层,service 层会显得十分厚重。

充血模型

不仅包含了对象的属性,还包含了属性的职责,对象的行为,包括业务逻辑、数据持久化等操作。

充血模型的优点

面向对象,Business Logic符合单一职责,不像在贫血模型里面那样包含所有的业务逻辑太过沉重。

充血模型的缺点

对于如何划分业务逻辑,什么样的逻辑应该放在Domain Object中,什么样的业务逻辑应该放在Business Logic中比较含糊。

DP 概念

在 DDD 里,DP (Domain Primitive) 可以说是一切模型、方法、架构的基础。它是在特定领域、拥有精准定义、可以自我验证、拥有行为的对象。可以认为是领域的最小组成部分。

DP 三条原则

  1. 让隐性的概念显性化
  2. 让隐性的上下文显性化
  3. 封装多对象行为

思考: 在实际的项目中,如果你使用了充血模型,那么如何把握它的强弱程度?

依赖都是可以替换的,属于业务域核心逻辑之外的东西,你对他们是没有控制权的,即使这些外部依赖产生了变动,也能将自身系统产生的变化,控制在最小范围内。
由外部系统的依赖变动,导致的内部系统的改造程度,我们可以理解为一个系统的可维护性。

抽象接口

抽象接口本质是一种中间协议,依赖方和被依赖方都只要对该协议负责,接口将软件分层隔离,在这种隔离下任何一方的变动都将被控制在当前范围内。

M个业务 * N个业务 -> M个业务 + N个业务
由内部逻辑的变化所导致的内部系统的改造程序,我们可以狭义地理解为系统的 可扩展性。

思考:发奖的逻辑如果改动,难道还要修改注册逻辑么?

简单概念

简单概念

● DP:抽象并封装自检和一些隐性属性的计算逻辑,且这些属性是无状态的
● Entity:抽象并封装单对象有状态的逻辑
● Domain Service:抽象并封装多对象的有状态逻辑
● Repository:抽象并封装外部数据访问逻辑。

流程:

  1. 首先对需要处理的业务问题进行总览。
  2. 然后领域对象 (Entity) 进行划分,明确每个领域对象的包含的信息和职责边界。并进行跨对象,多对象的逻辑组织(Domain Service)。
  3. 接着在上层应用中根据业务描述去编排 Entity 和 Domain Service。
  4. 最后再做一些下水道工作,去对下层的数据访问、RPC调用去做一些具体

实现

DDD语境传统语境
含义ValueObjectViewObject / ValueObject
作用领域基础类型用于展示的数据

统一语言和模型价值

财务人眼中技术人眼中
含义资产=负债+所有者权益借钱? 存钱?贷款?

为了建设有价值的模型,我们需要在形成UL的基础上,消化知识,并向模型中提炼知识。

DP 和 Entity 的区别

DP(VO)Entity
是否充血
有无状态

举例:有无状态的判定即 “程序是否需要追踪该对象的变化事件”,具体来说就是 假如体育场的很多座位,观众通过预定程序买了票,每张票上都对应一个座位号,这种场景下,座位就是有状态的,它是 Entity , 程序需要关注该对象的变化事件,比如通过唯一 ID 来追踪该对象,关注它的预定状态,价格,位置等属性。另一种场景下,假如观众通过预定程序买了票,进场只要有空座位就可以随便坐,这时候,座位就是无状态的, 它是 DP ,程序不需要对每个座位对象加以追踪,只需要关注总数即可。这也是 DP 和 Entity 的异同之处。

为了建立有价值的模型, 在确认了 UL 之后消化领域知识,并向无状态的 DP 和有状态的 Entity 中提炼知识。

在复杂的系统中,对一个对象进行修改,可能会涉及到大量其他关联对象的状态,如何使这些关联的对象始终保持一致,是一个比较复杂的话题。

Aggregate(聚合)

聚合是对存在引用关系的一组对象的封装,它的目的就是屏蔽掉内部对象之间复杂的关联关系,只对外暴露统一接口,关于聚合,我们需要关注它的两个属性,根对象 (root) 边界 (Boundary)

根对象:是整个聚合中唯一能够被外部引用的对象,也就是说 聚合所暴露的接口只允许操作根对象,根对象是一个 Entity, 因为每个聚合都需要 ID 和状态来区分其他聚合,所以这里也是通过根对象的 ID 来作为整个聚合的 ID。

边界: 简单来说,聚合的边界就是你判断哪些对象可以被放入当前聚合的条件。

限界上下文

本质是为了解决复杂系统的领域分治问题,这并不仅仅是 DDD 这种架构方式需要面临和处理的问题,其他任何架构方式都需要处理类似问题,领域分治最清晰的方式就是通过拆分成微服务,但拆分成微服务本身也存在边界问题,而且将会增加通信的复杂度,

其次,有些领域能力本身就适合作为一个集合,由一个系统来提供,不适合按照每种能力拆分成微服务,所以在一个系统内,如何进行领域分治,也是一个有价值的话题。

防腐层(Anti-corruption layer)

防腐层(Anti-Corruption Layer)模式,是一种在不同语义的子系统间构建的一层功能,对子系统间的请求进行翻译适配,从而确保应用设计不受外部依赖的系统的限制。

应用场景

许多应用依赖于外部系统提供的数据或者功能。当直接使用外部系统的API、数据结构时,自身就存在因使用外部系统,而被外部系统的质量问题影响,从而“腐化”本身设计的问题。比如,当一个遗留应用需要移植到新系统时,可能仍需使用现存的遗留资源,新的特性需要调用遗留系统。这种场景在系统迁移过程中尤其普遍。

解决方案

在应用自身与外部之间,构筑专门的一层组件或者服务,对两个系统进行通讯转换和语义隔离。这层组件或者服务,称为 防腐层

问题

  • 防腐层可能增加两个系统间的通讯延迟;
  • 防腐层增加了额外的服务,需要管理和维护;
  • 如果防腐层是系统迁移战略的一部分,则需要考虑防腐层是否是永久的,是否在遗留系统功能完全迁移完成后将其移除。

总结

大家好,这里是 Rocky 编程日记,喜欢后端架构中间件源码,该篇是对 DDD(领域驱动设计) 做了一个简短的概念梳理。后面也会陆续分享更多有关于 DDD(领域驱动设计) 的知识,喜欢的小伙伴们可以三连支持一下噢~,同时也可以评论区留下你宝贵的意见噢 ~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/681335.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

HackTheBox - 学院【CPTS】复习1 - PASSWORD ATTACKS

前言 有一个月时间没发文章了,我在6月11号进入htb学院学习CPTS,在扎实的THM基础的加持下,我学的非常顺利,其实大部分内容都相当于复习,而学到的内容只是一些可能不太常见、又或者非常细节的小技巧,这也是非…

vscode 出现 No such file or directory 的解决办法(python tkinter)

问题 Traceback (most recent call last): File “e:\Github\Python-GUI\PyQt-Fluent-Widgets\examples\navigation\demo.py”, line 202, in w Window() File “e:\Github\Python-GUI\PyQt-Fluent-Widgets\examples\navigation\demo.py”, line 95, in init self.initWindo…

ThreadPoolExecutor源码剖析

ThreadPoolExecutor源码涉及到的内容比较多,需要一点点的去啃和查看… ThreadPoolExecutor的核心属性 ThreadPoolExecutor的核心属性主要就是CTL。基于CTL获取到线程池的状态以及工作线程个数。 ctl是一个int类型的整数,內部基于AtomicInteger&#xff0…

再谈StringBuilder为什么线程不安全以及带来的问题

1 缘起 比较有意思的是,学习锁消除的过程中,有人讲到StringBuffer在方法内构建,不会被其他方法引用时,StringBuffer的锁会被消除, 于是,顺便看了一下同源的StringBuidler为什么线程不安全,以及…

【无标题】TP-LINK XDR5470 WiFi6路由器 简单开箱评测

TL-XDR5470易展版AX5400双频WiFi6路由器 简单开箱测评,上次买的XDR6078覆盖不够,还是得每层再买一个,所以又买了个TL-XDR5470,支持易展mesh。 上次买的XDR6078没有外置FEM功放芯片,所以信号差了一点,得加2…

PE系统盘制作

目录 前言 制作PE盘的步骤如下 前言 PE盘是一个轻量级的系统,类似于Windows系统。当您的计算机无法进入Windows系统时,您可以通过启动PE盘来访问一个独立的操作系统,从而执行各种任务,例如拷贝重要文件或进行系统安装。PE盘通常…

win10查看端口是否被占用,被哪一个程序占用(图文)

window系统中有时候我们会出现需要的端口号被占用,但不知道具体是哪个程序占用的。这时我们需要找到使用此端口的程序。 方法如下: 1)以管理员身份打开命令提示符窗口(开始-运行)。 2)使用命令查看端口使…

R730直通Tesla P40显卡

本次讲述如何在R730的ESXi上,将Tesla P40直通到centos7.7和WinServer2016。使用直通模式,安装普通的驱动即可,不需要vGPU的驱动。 按计划本来后面要自己装一下系统、做RAID的,不过最近需要用到显卡,所以先把显卡安装上…

初探Flink的Java实现流处理和批处理

端午假期,夏日炎炎,温度连续40度以上,在家学习Flink相关知识,记录下来,方便备查。 开发工具:IntelliJ Idea Flink版本:1.13.0 本次主要用Flink实现批处理(DataSet API) 和…

SAM与Prompt的结合

1. SAM介绍 由Meta AI Research开发的Segment anything model(简称SAM)最近引起了广泛的关注。SAM在超过10亿个mask的大型分割数据集上进行了训练,能够在特定的图像上分割任何对象。在最初的SAM工作中,作者们使用了零样本迁移任务…

08- c语言字符串 (C语言)

一 字符串的定义及基本使用 1、什么是字符串 被双引号引用的字符集合!例如:”hello” 、”world”,或者是以 \0 结尾的字符数组!!! 比如:char ch[] {h, e, \0} 注意:”hello” 中…

GB50149-2010电气装置安装工程母线装置施工及验收规范

为了确保强硬钢丝绳金属封闭体绝缘金属封闭母线、绝缘子、硬件、穿墙套管等设备母线的安装质量,加快安装技术的进步,和确保设备的安全运行,使该规范。 本规范适用于总线设备安装了750 kv及以下的T范围施工和验收。 母线的安装应按照批准的设计文件施工。 设备和设备运输、储…

python:并发编程(二十五)

前言 本文将和大家一起探讨python并发编程的实际项目:win图形界面应用(篇七,共八篇),系列文章将会从零开始构建项目,并逐渐完善项目,最终将项目打造成适用于高并发场景的应用。 本文为python并…

postman 文档、导出json脚本 导出响应数据 response ,showdoc导入postman json脚本 导出为文档word或markdown

生成文档 Collections中 选中文件夹 - ... (文件夹 功能小按钮) - view documentation : 保存响应数据 Response:(如果导出接口数据,会同步导出响应数据) 请求接口后,点击下方 Save as Example 可以保存响应数…

机器学习day20(前向传播的向量化代码,矩阵乘法)

前向传播的循环代码与向量化代码的对比 把X、B写作二维数组,即矩阵左边的for循环就可以用右边的np.matmul来实现matmul是numpy执行矩阵乘法的一种方式注意:此时所有的变量(X、W、B、Z、A_out)都是二维数组,即矩阵 向…

基础排序算法【归并排序+非递归版本+边界修正】

基础排序算法【归并排序非递归版本边界修正】 Ⅰ.归并排序(递归版本)①.分割②.归并③.拷贝 Ⅱ.非递归版本Ⅲ.边界修正 Ⅰ.归并排序(递归版本) 递归排序,采用的是分治法。分成子问题来处理。先让序列不断分割成子序列,当子序列有序后再合并。 对于一段…

Yolov5-Face 原理解析及算法解析

YOLOv5-Face 文章目录 YOLOv5-Face1. 为什么人脸检测 一般检测?1.1 YOLOv5Face人脸检测1.2 YOLOv5Face Landmark 2.YOLOv5Face的设计目标和主要贡献2.1 设计目标2.2 主要贡献 3. YOLOv5Face架构3.1 模型架构3.1.1 模型示意图3.1.2 CBS模块3.1.3 Head输出3.1.4 stem…

202320读书笔记|《宋词》——竹杖芒鞋轻胜马,谁怕?一蓑烟雨任平生

202320读书笔记|《宋词》——竹杖芒鞋轻胜马,谁怕?一蓑烟雨任平生 《宋词》韩震主编,偶然从书友那加入书架的书。宋词挺喜欢李清照的词以及知否的《菩萨蛮》。诗集,词,俳句,短歌我都很喜欢&…

工欲善其事,必先利其器-基于ubuntu18.04 VScode开发100ASK-ESP32

点击上方“嵌入式应用研究院”,选择“置顶/星标公众号” 干货福利,第一时间送达! 来源 | 嵌入式应用研究院 整理&排版 | 嵌入式应用研究院 前面我们基于ubuntu环境搭建了esp-idf的开发环境,它也是为了接下来基于VSCode来开发1…

【openGauss基本概念】---快速入门

【openGauss简单使用】---快速入门 🔻 一、基本概念🔰 1.1 openGauss🔰 1.2 数据库(Database)🔰 1.3 数据块(Block)🔰 1.4 行(Row)🔰 …