快速理解DDD领域驱动设计架构思想-基础篇 | 京东物流技术团队
1 前言
本文与大家一起学习并介绍领域驱动设计(Domain Drive Design) 简称DDD,以及为什么我们需要领域驱动设计,它有哪些优缺点,尽量用一些通俗易懂文字来描述讲解领域驱动设计,本篇并不会从深层大论述讲解落地实现,这些大家可以在了解入门后再去深层次学习探讨或在后续进阶和高级篇了解,希望通过本文介绍,可以让大家快速了解DDD并有一个基础的认知,DDD本身就是理论的集合,很难在不积累理论情况下来有效的实施DDD,仅仅看一些代码案例后就开搞,最终出来东西也是东施效颦,莫要好高骛远。 最后期望大家在工作中能多思考,如你所负责项目如果用DDD如何设计、以及会面临哪些挑战。
学习了解DDD之前,期望大家可在温顾下以往我们所了解掌握一些知识,努力让自己所学所掌握的内容沉淀下来,推荐阅读系列。
- Head First 设计模式:基础面向对象概念和重要的设计模式;
- UML面向对象建模基础:从需求到分析,从分析到设计,从设计到编码,UML都有用武之地
- 实现领域驱动设计:很厚,更加务实,推荐阅读
- 领域驱动设计:张逸-DDD开山之作,挺玄幻的,多读几遍受益匪浅;
2 定义与概念
领域驱动设计(DDD)提出是从系统的分析到软件建模的一套方法论。将业务概念和业务规则转换成软件系统中的概念和规则,从而降低或隐藏业务复杂性,使系统具有更好的扩展性,以应对复杂多变的现实业务问题。总结它是一套完整而系统的设计方法、是一种设计思维、一种方法论,并不是"系统架构",一种架构设计原则、思维。
2.1、为什么要使用"领域驱动设计",或者说其用途,应用场景式什么?
-
善于处理高复杂业务的产品研发、可帮助我们提炼稳定的产品内核(领域模型中称为核心域);
-
通过建模可提高建模高内聚、降低模型间的耦合度,提高系统的可扩展性与稳定性;
-
强调团队与领域专家的合作沟通,有助于建立一个沟通良好的团队组织;
-
统一设计思想与设计规范,有助于提高团队成员的架构设计能力和面向对象设计能力;
-
现有的微服务建构都是遵循领域驱动设计的架构原则;
-
如果你负责的软件系统并不复杂,那么,你确实不需要学习领域驱动设计!
2.2、领域驱动设计跟时下流行的架构思维最大的区别是什么?
领域驱动设计的思维是:对象+行为+服务,所有的设计围围绕着对象、行为、服务展开;
时下流行架构设计思维是:基于MVC分层架构进行纵向扩展,分业务模块进行产品横向扩展;

2.2.1. 传统的方案
三层应用架构:数据-应用(业务逻辑层)-展现,通常是以数据位为起点进行数据库分析设计。
-
服务层过重,数据模型失血,没东西;
-
面条式编程或者面向数据库编程,服务层围绕数据库作业完成业务逻辑,经常一条线撸到底;
3) 代码一整块一整块的过重,很难扩展复用;
- 数据库模型只是数据库映射,没有相关的行为支撑,行为都被上一层Service给完成等了,因此是失血 的领域模型;
2.2.2. 领域驱动方案
架构四层在DDD分层结构中将三层中业务逻辑拆解为应用层和领域层,核心业务逻辑表现下沉到领域层去实现,以业务领域模型为核心建模(面向对象建模),更能体现对现实世界的抽象,其优点如下
1) 轻服务层+充血的领域模型;
-
领域模型封装和实现各自应有的行为,可以认为是一个高内聚、低耦合的组件;
-
由于模型集数据与行为于一身,是一种自解释的对象,代码复用性高,业务逻辑清晰明确;
- 用户界面层:主要职责是通过用户界面向用户显示数据信息,同时解释用户的命令,并把用户的请求发送到应用层。
- 应用层:通过调用基础设置和领域层完成数据资源操作及业务流程编排,相当于BS层;
- 领域层:将业务逻辑高度内聚到领域层,所以领域层是整个系统的核心,它只与实际业务相关,不关心任何技术细节,尽可能做到与持久化无关;
- 基础设施层:包含了任何类型的框架、数据库访问代码或者公共的方法等,纯技术的一层;

2.3、如何学习领域驱动设计
没有谁能够做到领域驱动设计的一蹴而就,所谓"理论联系实际",在刚开始接触或学习设计领域驱动时,总会有一种诉求希望能给出公式般的设计准则或规范,似乎软件设计就像拼积木一般,只要遵循图示给出的拼搭过程,不经思考就能拼出期待的模型,这似乎不切实际的幻想,要掌握领域驱动设计,首先要了解掌握一些概念以知识理论,在此基础之上思考这些概念背后蕴含的原理,设计原则,思考限界上下文(Bounded Context)边界的划分,实际还是围绕"高内聚、低耦合"原则的体现,只是我们考虑什么内容才是高内聚,如何抽象才能做到低耦合,在分层架构中,各层之间该如何协作?出现了依赖如何解耦,仍然需要从重用与变化的角度去思考设计决策。
3 领域驱动设计
领域驱动设计强调以"领域"为核心驱动力,通过模型驱动设计来保障领域模型与程序设计的一致,领域模型不应该包含任何技术实现因素,模型中的对象真实的表达了领域概念,却不受技术实现的约束,领域模型本身和技术无关,领域驱动从设计上划分为战略设计和战术设计。
- 一个领域是由一个或多个模型组成;
- 从定义上讲模型是领域的抽象;
- 从理解上将模型可以认为是一个高内聚、低耦合的组件、模块,也可以称为一个子领域;
- 模型重在建模过程,建模过程会抽象出一系列领域对象和领域服务;
- 在DDD中,定义一系列的标准"领域元素"用于领域建模;如战术设计元模型

3.1. 战略设计
强调业务战略上的重点,如何按重要性分配工作,以及如何进行最佳,遵循量大原则:
-
必须指导设计决策,以便减少各个部分之间的相互依赖,在使用设计意图更为清晰的同时而又不失去关键的互操作性和系统性;
-
必须把模型的重点放在捕获系统概念核心,也就是系统的"远景"上。
3.1.1 子域划分
整个业务领域的一部分,关注与宏观业务,通过对大领域进行划小在业务间划分出概念上分界线,便于在系统筹划阶段决策如何分配资源(人、钱)。
1) 核心子域:领域中最有价值和最核心的部分,产品成败的关键,核心竞争力,在DDD开发中,主要关注核 心域,给予最高优先级;
-
支撑子域:项目中对核心子域起着支撑作用的相关功能,专注于业务的某个反面;
-
通用子域:与项目意图无关的内聚子领域,解决一些通用问题,任何专有的业务都不应该放在通用子域;
3.1.2. 战略建模
关注点在于系统物理划分,根据你对领域的分割结果及公司或部门的组织结构决策如何划分子系统,比如分出几个,系统间如何交互,该层面往往暂不会涉及够多技术细节。
1) 限界上下文(Bounded Context):通俗讲指系统中模块,微服务架构中的子服务、单体中"包(Java)"或名称空间(C#),对系统的一个物理划分,限定了领域模型的边界,在更深层次介绍深挖,这东西得分成两个词:限界、上下文,可以理解成系统设计之初,你需要画一个圈设置一个范围,保证领域模型限制在这个圈内不可串场,这个‘圈’即为限界上下文。
-
通用语言:用于统一领域专家、产品、研发、测试大家在使用的语言,避免出现需求理解不一致,设计与需求不一致,沟通不顺畅等问题,简单来说大家在一起聊某个东西的时候都能明白彼此所致的是什么,场景不同,同一个词就会有着不同含义。
-
上下文映射图:用图的方式,表达出限界上下文之间关联,后续会单独在详细介绍上下文映射图,如 合作关系、防腐层、大泥球等;
3.2. 战术设计
依赖于领域模型和通用预言,通过技术模式将领域模型和通用预言中的概念映射到代码实现中。随着模型的进化,代码实现也会进行重构,以更好的体现模型概念。
- 主要包括:
-
代表领域中的概念,如实体、值对象、领域服务、模块等;
-
用于管理对象的生命周期。如聚合、工厂、仓库等;
-
用于集成或跟踪,如领域事件等;

3.3. 名词解释
-
领域/子域:什么领域?从广义上将,领域即是一个组织所做的事情以及所包含的一切,领域可大可小有界限,不是无限大,如电商领域,交易领域,购物领域等,比如我们常听客户说“我们有这样几块业务”一般来说这里所谓"几块儿"就是指子域 。
-
实体(entity):这个词被我们广泛使用,甚至过分使用,实体是一个重要的概念,一个典型实体应具备3个要素(身份标识、属性、领域行为),必须有唯一的身份标识,没有身份标识的领域对象就不是实体。如:User对象就是一个实体。
-
属性:实体的属性用来说明主体的静态特征,并持有数据与状态。
@Data
public class Product{private String sku;private String name;private Price price;
}
- 领域行为:实体拥有领域行为,可以更好地说明其作为主体的动态特征。一个不具备动态特征的对象不属于领域行为。
@Data
public class Product{private String sku;private String name;private Price price;//变更状态的领域行为public void changePriceTo(Price newPrice){//设计产品新加个.......}
}
- 值对象(value object):比较抽象,通常作为实体的属性,区分值对象与实体的区别在于,值对象是不可变的,并且没有唯一标识,仅由其属性的值定义,参与则对它的判断是依据值还是依据身份标识,前者是值对象,后者是实体;
举个小例子:订单项和订单的关系:多对一,一个订单里有多条订单项,一个订单项,只会出现在一个订单里,组合关系,部分不能脱离主体单独存在
public class Order {int id;User user;
}public class OrderItem {private int id;private Product product;private int num;private Order order;
}

6) 聚合根:聚合中需要指定一个实体作为聚合根来作为整个聚合的对外触电,也就是说外部只能通过聚合根实现对内部对象的访问,这样的限制可以对内部对象实现最大化的保护。
4 价值是什么
几乎所有项目的发展都有这样一个规律:初期需求简单,中后期业务激增系统复杂度升级,导致最初的设计理念需要大刀阔斧的改革,所以,系统越复杂、代码规模越大,DDD 的优势就越明显。
- 合作沟通:强调团队与领域专家的合作沟通,有助于建立一个沟通良好的团队组织;
- 统一思想:统一设计思想与设计规范,有助于提高团队成员的架构设计能力和面向对象设计能力;
- 系统灵活:通过建模可提高模型的高内聚,降低模型建的耦合度,提高系统的可扩展性与稳定性;
- 产品内核:善于处理高复杂度业务产品研发,可帮助我们提炼稳定的产品内核;
- 业务沉淀:领域模型是系统的核心,是领域内业务的直接沉淀,具有非常大的业务价值。

5 基础篇结束语
微服务划分的一个重要理论基础就是领域驱动设计,但由于DDD门槛高、概念多,体系庞大又抽象,再加上实践经验和案例缺少,很多开发人员对DDD存在不少疑惑,或只停留在平时依靠检索或身边同事谈及耳闻了解DDD,通过本篇初步认识了领域驱动设计、前期我们先暂短介绍这里,后续会将从代码层面入手分享DDD实现落地。
作者:京东物流 边雷
来源:京东云开发者社区 自猿其说Tech 转载请注明来源
相关文章:
快速理解DDD领域驱动设计架构思想-基础篇 | 京东物流技术团队
1 前言 本文与大家一起学习并介绍领域驱动设计(Domain Drive Design) 简称DDD,以及为什么我们需要领域驱动设计,它有哪些优缺点,尽量用一些通俗易懂文字来描述讲解领域驱动设计,本篇并不会从深层大论述讲解落地实现,这…...
C++学习笔记(堆栈、指针、命名空间、编译步骤)
C 1、堆和栈2、指针2.1、指针的本质2.2、指针的意义2.3、清空指针2.4、C类中的this 3、malloc and new4、命名空间4.1、创建命名空间4.2、使用命名空间 5、编译程序的四个步骤5.1、预处理5.2、编译5.3、汇编5.4、链接 1、堆和栈 堆(heap)和栈࿰…...
Rust Yew应用开发的事件初探
在Rust的世界中有一个叫Yew的框架,它借鉴了React的思想。我的React代码也写了不少,今天就聊一下我个人对Yew应用开发中事件相关部分的体验。 我的也是才开始学习Rust和Yew,说得不对的地方还请大家多多指教。 下面的例子涉及到3个组件 Paren…...
高并发下单例线程安全
1.使用静态内置类实现单例模式 自定义线程池 2.使用static代码块实现单例 3.使用静态内置类实现单例模式 4.使用static代码块实现单例 public class MySingleton {//使用volatile关键字保其可见性volatile private static MySingleton instance null;private MySingleton…...
【EKF】EKF原理
原理简述 卡尔曼滤波可以在线性模型,误差为高斯模型的情况下,对目标状态得出很好的估计效果,但如果系统存在非线性的因素,其效果就没有那么好了。比较典型的非线性函数关系包括平方关系,对数关系,指数关系…...
蓝桥杯官网填空题(古堡算式)
题目描述 本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。 福尔摩斯到某古堡探险,看到门上写着一个奇怪的算式:ABCDE ∗ ?EDCBA 他对华生说:“ABCDE 应该代表不同的数字,问号…...
Python---集合set
集合特点 1. 可以容纳多个数据 2. 可以容纳不同类型的数据 3.数据是无序存储的(不支持下标索引) 4. 不允许重复数据存在 5. 可以修改 6. 支持for循环,不支持while循环 集合定义 # 定义集合 变量 {元素1, 元素2, 元素3, 元素4...}# 定…...
LORA项目源码解读
大模型fineturn技术中类似于核武器的LORA,简单而又高效。其理论基础为:在将通用大模型迁移到具体专业领域时,仅需要对其高维参数的低秩子空间进行更新。基于该朴素的逻辑,LORA降低大模型的fineturn门槛,模型训练时不需…...
Azure + React + ASP.NET Core 项目笔记一:项目环境搭建(一)
不重要的目录标题 前提条件第一步:新建文件夹第二步:使用VS/ VS code/cmd 打开该文件夹第三步:安装依赖第四步:试运行react第五步:整理项目结构 前提条件 安装dotnet core sdk 安装Node.js npm 第一步:新…...
html 学习 之 文本标签
下面是一些常见的HTML文本标签(,,,,和)以及它们的作用: 标签 (Emphasis - 强调): 作用:用于在文本中表示强调或重要性。 示例: <p>这是一段文本,&l…...
联发科3纳米芯片预计2024年量产,此前称仍未获批给华为供货
9月7日,联发科与台积电共同宣布,联发科首款采用台积电3纳米制程生产的天玑旗舰芯片开发进度顺利,已成功流片,预计将在2024年量产,并将于下半年正式上市。这款旗舰芯片并非今年上市的天玑9300。 据联发科总经理陈冠州介…...
搭建vue3项目并git管理
搭建vue3项目 采用vue3的create-vue脚手架搭建项目,底层是vite,要求环境 node 16.0及以上(node -v检查node版本) 在文件夹右键->终端-> npm init vuelatest,输入项目名称,根据需要选择是否装包 src…...
【Azure OpenAI】OpenAI Function Calling 101
概述 本文是结合 github:OpenAI Function Calling 101在 Azure OpenAI 上的实现: Github Function Calling 101 如何将函数调用与 Azure OpenAI 服务配合使用 - Azure OpenAI Service 使用像ChatGPT这样的llm的困难之一是它们不产生结构化的数据输出…...
立晶半导体Cubic Lattice Inc 专攻音频ADC,音频DAC,音频CODEC,音频CLASS D等CL7016
概述: CL7016是一款高保真USB Type-C兼容音频编解码芯片。可以录制和回放有24比特音乐和声音。内置回放通路信号动态压缩, 最大42db录音通路增益,PDM数字麦克风,和立体声无需电容耳机驱动放大器。 5V单电源供电。兼容USB 2.0全速工…...
【Flutter】支持多平台 多端保存图片到本地相册 (兼容 Web端 移动端 android 保存到本地)
免责声明: 我只测试了Web端 和 Android端 可行哈 import dart:io; import package:flutter/services.dart; import package:http/http.dart as http; import package:universal_html/html.dart as html; import package:oktoast/oktoast.dart; import package:image_gallery_sa…...
postgresql 安装教程
postgresql 安装教程 本文以window 15版本为教程 文章目录 postgresql 安装教程1.下载地址2.以管理员身份运行3.选择安装路径,点击Next4.选择组件(默认都勾选),点击Next5.选择数据存储路径,点击Next6.设置超级用户的…...
手写数据库连接池
数据库连接是个耗时操作.对数据库连接的高效管理影响应用程序的性能指标. 数据库连接池正是针对这个问题提出来的. 数据库连接池负责分配,管理和释放数据库连接.它允许应用程序重复使用一个现有的数据路连接,而不需要每次重新建立一个新的连接,利用数据库连接池将明显提升对数…...
在CentOS7上增加swap空间
在CentOS7上增加swap空间 在CentOS7上增加swap空间,可以按照以下步骤进行操作: 使用以下命令检查当前swap使用情况: swapon --show创建一个新的swap文件。你可以根据需要指定大小。例如,要创建一个2GB的swap文件,使用…...
@Autowired和@Resource
文章目录 简介Autowired注解什么是Autowired注解Autowired注解的使用方式Autowired注解的优势和不足 Qualifier总结: Resource注解什么是Resource注解Resource注解的使用方式Resource注解的优势和不足 Autowired vs ResourceAutowired和Resource的区别为什么推荐使用…...
QTableView通过setColumnWidth设置了列宽无效的问题
在用到QT的QTableView时,为了显示效果,向手动的设置每一列的宽度,但是如下的代码是无效的。 ui->tableView->setColumnWidth(0,150);ui->tableView->setColumnWidth(1,150);ui->tableView->setColumnWidth(2,150);ui->t…...
51c自动驾驶~合集58
我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留,CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制(CCA-Attention),…...
3.3.1_1 检错编码(奇偶校验码)
从这节课开始,我们会探讨数据链路层的差错控制功能,差错控制功能的主要目标是要发现并且解决一个帧内部的位错误,我们需要使用特殊的编码技术去发现帧内部的位错误,当我们发现位错误之后,通常来说有两种解决方案。第一…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序
一、开发环境准备 工具安装: 下载安装DevEco Studio 4.0(支持HarmonyOS 5)配置HarmonyOS SDK 5.0确保Node.js版本≥14 项目初始化: ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...
现代密码学 | 椭圆曲线密码学—附py代码
Elliptic Curve Cryptography 椭圆曲线密码学(ECC)是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础,例如椭圆曲线数字签…...
Java入门学习详细版(一)
大家好,Java 学习是一个系统学习的过程,核心原则就是“理论 实践 坚持”,并且需循序渐进,不可过于着急,本篇文章推出的这份详细入门学习资料将带大家从零基础开始,逐步掌握 Java 的核心概念和编程技能。 …...
逻辑回归暴力训练预测金融欺诈
简述 「使用逻辑回归暴力预测金融欺诈,并不断增加特征维度持续测试」的做法,体现了一种逐步建模与迭代验证的实验思路,在金融欺诈检测中非常有价值,本文作为一篇回顾性记录了早年间公司给某行做反欺诈预测用到的技术和思路。百度…...
群晖NAS如何在虚拟机创建飞牛NAS
套件中心下载安装Virtual Machine Manager 创建虚拟机 配置虚拟机 飞牛官网下载 https://iso.liveupdate.fnnas.com/x86_64/trim/fnos-0.9.2-863.iso 群晖NAS如何在虚拟机创建飞牛NAS - 个人信息分享...
毫米波雷达基础理论(3D+4D)
3D、4D毫米波雷达基础知识及厂商选型 PreView : https://mp.weixin.qq.com/s/bQkju4r6med7I3TBGJI_bQ 1. FMCW毫米波雷达基础知识 主要参考博文: 一文入门汽车毫米波雷达基本原理 :https://mp.weixin.qq.com/s/_EN7A5lKcz2Eh8dLnjE19w 毫米波雷达基础…...
MySQL的pymysql操作
本章是MySQL的最后一章,MySQL到此完结,下一站Hadoop!!! 这章很简单,完整代码在最后,详细讲解之前python课程里面也有,感兴趣的可以往前找一下 一、查询操作 我们需要打开pycharm …...
EEG-fNIRS联合成像在跨频率耦合研究中的创新应用
摘要 神经影像技术对医学科学产生了深远的影响,推动了许多神经系统疾病研究的进展并改善了其诊断方法。在此背景下,基于神经血管耦合现象的多模态神经影像方法,通过融合各自优势来提供有关大脑皮层神经活动的互补信息。在这里,本研…...
