03.领域驱动设计:了解实体和值对象以及它们的区别

目录

1、概述

2、实体

1.实体的业务形态

2.实体的代码形态

3.实体的运行形态

4.实体的数据库形态

3、值对象

1.值对象的业务形态

2.值对象的代码形态

3.值对象的运行形态

4.值对象的数据库形态

5.值对象的优势和局限

4、实体和值对象的区别

5、总结


1、概述

DDD战术设计中的两个重要概念:实体和值对象。这两个概念都是领域模型中的领域对象。

它们在领域模型中起什么作用,战术设计时如何将它们映射到代码和数据模型中去?

另外,在战略设计向战术设计过渡的这个过程中,理解和区分实体和值对象在不同阶段的形态是很

重要的,毕竟阶段不同,它们的形态也会发生变化,这与我们的设计和代码实现密切相关。

2、实体

在DDD中有这样一类对象,它们拥有唯一标识符,且标识符在历经各种状态变更后仍能保持一

致,这是实体。

1.实体的业务形态

在DDD不同的设计过程中,实体的形态是不同的。在战略设计时,实体是领域模型的一个重要对

象。

领域模型中的实体是多个属性、操作或行为的载体。在事件风暴中,我们可以根据命令、操作或者

事件,找出产生这些行为的业务实体对象,进而按照一定的业务规则将依存度高和业务关联紧密的

多个实体对象和值对象进行聚类,形成聚合。可以理解是实体和值对象是组成领域模型的基础单

元。

2.实体的代码形态

在DDD 里,这些实体类通常采用充血模型,与这个实体相关的所有业务逻辑都在实体类的方法中

实现,跨多个实体的领域逻辑则在领域服务中实现。

3.实体的运行形态

实体以 DO(领域对象)的形式存在,每个实体对象都有唯一的ID

我们可以对一个实体对象进行多次修改,修改后的数据和原来的数据可能会大不相同。但是,由于

它们拥有相同的ID,它们依然是同一个实体。

4.实体的数据库形态

与传统数据模型设计优先不同,DDD是先构建领域模型,针对实际业务场景构建实体对象和行

,再将实体对象映射到数据持久化对象

在领域模型映射到数据模型时,一个实体可能对应0个、1个或者多个数据库持久化对象。大多数

情况下实体与持久化对象是一对一。

3、值对象

值对象相对实体来说,会更加抽象一些。

值对象的定义:通过对象属性值来识别的对象,它将多个相关属性组合为一个概念整体。在 DDD

中用来描述领域的特定方面,并且是一个没有标识符的对象,叫作值对象。

也就说,值对象描述了领域中的一件东西,这个东西是不可变的,它将不同的相关属性组合成了一

个概念整体

简单来说,值对象本质上就是一个集

人员实体原本包括:姓名、年龄、性别以及人员所在的省、市、县和街道等属性。

这样显示地址相关的属性就很零碎了对不对?现在,我们可以将“省、市、县和街道等属性”拿出来

构成一个“地址属性集合”,这个集合就是值对象

1.值对象的业务形态

值对象是DDD领域模型中的一个基础对象,它跟实体一样都来源于事件风暴所构建的领域模型

都包含了若干个属性,它与实体一起构成聚合。

本质上,实体是看得到、摸得着的实实在在的业务对象,实体具有业务属性、业务行为和业务逻

。而值对象只是若干个属性的集合,只有数据初始化操作和有限的不涉及修改数据的行为,基本

不包含业务逻辑

值对象的属性集虽然在物理上独立出来了,但在逻辑上它仍然是实体属性的一部分,用于描述实体

的特征。

在值对象中也有部分共享的标准类型的值对象,它们有自己的限界上下文,有自己的持久化对象,

可以建立共享的数据类微服务,比如数据字典

2.值对象的代码形态

值对象在代码中有这样两种形态。如果值对象是单一属性,则直接定义为实体类的属性;如果值对

象是属性集合,则把它设计为Class类,Class将具有整体概念的多个属性归集到属性集合,这样

的值对象没有ID,会被实体整体引用。

我们看一下下面这段代码,person这个实体有若干个单一属性的值对象,比如Id、name等属性;

同时它也包含多个属性的值对象,比如地址address。

3.值对象的运行形态

值对象嵌入到实体的话,有这样两种不同的数据格式,也可以说是两种方式,分别是属性嵌入的方

序列化大对象的方式。

引用单一属性的值对象或只有一条记录的多属性值对象的实体,可以采用属性嵌入的方式嵌入

引用一条或多条记录的多属性值对象的实体,可以采用序列化大对象的方式嵌入

比如,人员实体可以有多个通讯地址,多个地址序列化后可以嵌入人员的地址属性。值对象创建后

就不允许修改了,只能用另外一个值对象来整体替换。

案例 1:以属性嵌入的方式形成的人员实体对象,地址值对象直接以属性值嵌入人员实体中。

案例 2:以序列化大对象的方式形成的人员实体对象,地址值对象被序列化成大对象Json串后,

嵌入人员实体中。

4.值对象的数据库形态

DDD 引入值对象是希望实现从“数据建模为中心”向“领域建模为中心”转变,减少数据库表的数量

和表与表之间复杂的依赖关系,尽可能地简化数据库设计,提升数据库性能。

如何理解用值对象来简化数据库设计呢?

传统的数据建模大多是根据数据库范式设计的,每一个数据库表对应一个实体,每一个实体的属性

值用单独的一列来存储,一个实体主表会对应 N 个实体从表。而值对象在数据库持久化方面简化

了设计,它的数据库设计大多采用非数据库范式,值对象的属性值和实体对象的属性值保存在同一

个数据库实体表中

举个例子,还是基于上述人员和地址那个场景,实体和数据模型设计通常有两种解决方案:

第一是把地址值对象的所有属性都放到人员实体表中,创建人员实体,创建人员数据表;

第二是创建人员和地址两个实体,同时创建人员和地址两张表。

第一个方案会破坏地址的业务涵义和概念完整性;

第二个方案增加了不必要的实体和表,需要处理多个实体和表的关系,从而增加了数据库设计的复

杂性。

我们可以综合这两个方案的优势,扬长避短

在领域建模时,我们可以把地址作为值对象,人员作为实体,这样就可以保留地址的业务涵义和概

念完整性。而在数据建模时,我们可以将地址的属性值嵌入人员实体数据库表中只创建人员数据

库表。这样既可以兼顾业务含义和表达,又不增加数据库的复杂度。

总结一下:

领域建模时,我们可以将部分对象设计为值对象,保留对象的业务涵义,同时又减少了实体的数

量;在数据建模时,我们可以将值对象嵌入实体,减少实体表的数量,简化数据库设计。

5.值对象的优势和局限

值对象是一把双刃剑,它的优势是可以简化数据库设计,提升数据库性能

值对象采用序列化大对象的方法简化了数据库设计,减少了实体表的数量,可以简单、清晰地表达

业务概念。

这种设计方式虽然降低了数据库设计的复杂度,但却无法满足基于值对象的快速查询,会导致搜索

值对象属性值变得异常困难。

值对象采用属性嵌入的方法提升了数据库的性能,但如果实体引用的值对象过多,则会导致实体

堆积一堆缺乏概念完整性的属性,这样值对象就会失去业务涵义,操作起来也不方便。

所以,你可以对照着以上这些优劣势,结合你的业务场景,好好想一想了。

那如果在你的业务场景中,值对象的这些劣势都可以避免掉,那就请放心大胆地使用值对象

4、实体和值对象的区别

实体和值对象是微服务底层的最基础的对象,一起实现实体最基本的核心领域逻辑

值对象和实体在某些场景下可以互换,很多DDD专家在这些场景下,其实也很难判断到底将领域

对象设计成实体还是值对象?值对象在某些场景下有很好的价值,但是并不是所有的场景都适合值

对象。你需要根据团队的设计和开发习惯,以及上面的优势和局限分析,选择最适合的方法。

DDD引入值对象还有一个重要的原因,就是到底领域建模优先还是数据建模优先?

DDD提倡从领域模型设计出发,而不是先设计数据模型

传统的数据模型设计通常是一个表对应一个实体,一个主表关联多个从表,当实体表太多的时候就

很容易陷入无穷无尽的复杂的数据库设计,领域模型就很容易被数据模型绑架。

可以说,值对象的诞生,在一定程度上,和实体是互补的。

我们可以看出,同样的对象在不同的场景下,可能会设计出不同的结果。

有些场景中,地址会被某一实体引用,它只承担描述实体的作用,并且它的值只能整体替换,这时

候你就可以将地址设计为值对象,比如收货地址。

而在某些业务场景中,地址会被经常修改,地址是作为一个独立对象存在的,这时候它应该设计为

实体,比如行政区划中的地址信息维护。

5、总结

今天主要学习了实体和值对象在DDD不同设计阶段的形态,以及它们从战略设计向战术设计演进

过程中的设计方法。

这个过程是从业务模型向系统模型落地的过程,比较复杂,很考验你的设计能力,很多时候我们都

结合自己的业务场景,选择合适的方法来进行微服务设计。强调一点,我们不避讳传统的设计方

法,毕竟适合自己的才是最好的。

希望你能充分理解实体和值对象的概念和应用,将学到的知识运用,最终将适合自己业务的DDD

设计方法纳入到架构体系,实现落地。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

企业虚拟机服务器中了lockbit3.0勒索病毒怎么办,lockbit3.0勒索病毒解密处理流程

对于企业来说,企业的数据是企业的核心命脉,关乎着企业的生产与运营的所有工作。随着网络技术的不断发展,网络安全威胁也在不断增加。近期,云天数据恢复中心接到了很多企业的求助,企业的虚拟机服务器遭到了lockbit3.0勒…

vue的pinia环境搭建

一、 pinia是什么? Pinia是Vue的新一代轻量级状态管理库,它允许您跨组件/页面共享状态。Pinia由Vue.js官方成员重新设计,旨在提供更直观、更易于学习的状态管理解决方案。 Pinia的主要特点包括: 对Vue2和Vue3提供良好的支持&#…

机器学习之pandas库学习

这里写目录标题 pandas介绍pandas核心数据结构SeriesDataFrameDataFrame的创建列访问列添加列删除行访问行添加行删除数据修改 pandas介绍 pandas是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。Pandas 纳入 了大量库和一些标准的数据模型&#xff…

C#学习(十一)——Array和Collection

一、集合 集合重要且常用 孤立的数据是没有意义的,集合可以作为大量数据的处理,可进行数据的搜索、迭代、添加、删除。 C#中,所有集合都必须实现ICollection接口(数组Array除外) 集合说明Array数组,固定长…

【Linux】进程间通信概念 | 匿名管道

文章目录 一、什么是进程间通信进程间通信的概念进程间通信的目的进程间通信的分类进程间通信的本质 二、什么是管道三、匿名管道匿名管道的原理✨站在内核角度理解管道✨站在文件描述符角度理解管道 pipe系统调用fork后在父子进程间使用管道通信代码实现 匿名管道的读写规则管…

初识人工智能,一文读懂机器学习之逻辑回归知识文集(7)

🏆作者简介,普修罗双战士,一直追求不断学习和成长,在技术的道路上持续探索和实践。 🏆多年互联网行业从业经验,历任核心研发工程师,项目技术负责人。 🎉欢迎 👍点赞✍评论…

CSS 双色拼接按钮效果

<template><view class="sss"><button> <!-- 按钮 --><view class="span"> 按钮 </view> <!-- 按钮文本 --></button></view></template><script></script><style>body {b…

uniapp微信小程序-input默认字的样式

需要的是这样的 问题 正常是在input框上面写样式就行&#xff0c;但是uniapp不起作用 解决 直接在input上写placeholder-style"color就解决了 <input class"findInput" type"text" placeholder"关键词查询"placeholder-style"co…

Gin 框架之jwt 介绍与基本使用

文章目录 一.JWT 介绍二.JWT认证与session认证的区别2.1 基于session认证流程图2.2 基于jwt认证流程图 三. JWT 的构成3.1 header : 头部3.2 payload : 负载3.2.1 标准中注册的声明 (建议但不强制使用)3.2.2 公共的声明3.2.3 私有的声明3.2.4 定义一个payload 3.3 signatrue : …

一文掌握SpringBoot注解之@Component 知识文集(5)

&#x1f3c6;作者简介&#xff0c;普修罗双战士&#xff0c;一直追求不断学习和成长&#xff0c;在技术的道路上持续探索和实践。 &#x1f3c6;多年互联网行业从业经验&#xff0c;历任核心研发工程师&#xff0c;项目技术负责人。 &#x1f389;欢迎 &#x1f44d;点赞✍评论…

操作系统(5)-----操作系统进程相关

目录 一.进程的组成 1.PCB&#xff08;进程控制块&#xff09; 2.程序段与数据段 二.进程的特征 三.进程的状态以及状态的转换 四.进程的组织 1.链接方式 2.索引方式 五.进程控制 六.进程控制相关原语 1.创建原语 2.撤销原语 3.阻塞原语 4.唤醒原语 5.切换原语 …

Spring MVC 请求流程

SpringMVC 请求流程 一、DispatcherServlet 是一个 Servlet二、Spring MVC 的完整请求流程 Spring MVC 框架是基于 Servlet 技术的。以请求为驱动&#xff0c;围绕 Servlet 设计的。Spring MVC 处理用户请求与访问一个 Servlet 是类似的&#xff0c;请求发送给 Servlet&#xf…

5G赋能智慧文旅:科技与文化的完美结合,打造无缝旅游体验,重塑旅游业的未来

一、5G技术&#xff1a;智慧文旅的强大引擎 5G技术的起源可以追溯到2010年&#xff0c;当时世界各国开始意识到4G技术已经达到了瓶颈&#xff0c;无法满足日益增长的移动通信需求。2013年&#xff0c;国际电信联盟&#xff08;ITU&#xff09;成立了5G技术研究组&#xff0c;开…

力扣516. 最长回文子序列

动态规划 思路&#xff1a; 字符串最长回文子序列问题可以转换为原字符串 s 和逆串 s 的最长公共子序列长度问题&#xff0c;具体推断过程可以参考 力扣1312. 让字符串成为回文串的最少插入次数问题变成了求两个字符串最长公共子序列长度问题&#xff0c;具体思路可以参考 力扣…

物联网协议Coap之C#基于Mozi的CoapClient调用解析

目录 前言 一、CoapClient相关类介绍 1、CoapClient类图 2、CoapClient的设计与实现 3、SendMessage解析 二、Client调用分析 1、创建CoapClient对象 2、实际发送请求 3、Server端请求响应 4、控制器寻址 总结 前言 在之前的博客内容中&#xff0c;关于在ASP.Net Co…

《向量数据库指南》——Milvus Cloud 2023 年关键数据

10 倍 - 内存节省 在 2023 年,RAG 模型被广泛认为是向量数据库的最主要应用之一。我们发现,在文档被分割成块之后,一个含有 500 个 Token 的 Chunk(通常 1000 字节)会转换成一个 1536 维的 float32 向量(通常 6000 字节),这意味着向量数据的体积可能会超过原始文档的…

Linux服务器配置与管理(第三次实验)

实验目的及具体要求 目的 1.熟悉Shell 脚本语法 2.掌握创建脚本的方法 3.掌握运行脚本的方法 4.掌握变量及表达式 5.掌握Shell 控制结构 6.掌握Shell 函数 任务 1.显示当前日期时间、执行路径、用户账户及所在的目录位置 2.判断一个文件是不是字符设备文件&#xff0…

Github 2024-01-28 开源项目日报Top10

根据Github Trendings的统计&#xff0c;今日(2024-01-28统计)共有10个项目上榜。根据开发语言中项目的数量&#xff0c;汇总情况如下&#xff1a; 开发语言项目数量Python项目3TypeScript项目2Rust项目1HTML项目1JavaScript项目1Cuda项目1C#项目1非开发语言项目1 Nuxt&#…

有手就行!阿里云上3分钟搞定幻兽帕鲁联机服务器搭建

幻兽帕鲁最近在社区呈现了爆火的趋势&#xff0c;在线人数已突破百万级别&#xff0c;官方服务器也开始出现不稳定&#xff0c;卡人闪退的情况。对于有一定财力的小伙伴&#xff0c;搭建一个私人服务器是一个最稳定而舒服的解决方案。 本文萝卜哥将讲解一下如何快速搭建 palwo…

Nginx解析漏洞(nginx_parsing_vulnerability)

目录 Nginx解析漏洞 环境搭建 复现 漏洞利用 Nginx解析漏洞 NGINX解析漏洞主要是由于NGINX配置文件以及PHP配置文件的错误配置导致的。这个漏洞与NGINX、PHP版本无关&#xff0c;属于用户配置不当造成的解析漏洞。具体来说&#xff0c;由于nginx.conf的配置导致nginx把…