手把手教你落地 DDD
钟敬
Thoughtworks 首席咨询师、数字化转型与运营团队 DDD 负责人
19697 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 45 讲
AIGC特别策划 (2讲)
结束语&结课测试 (2讲)
手把手教你落地 DDD
15
15
1.0x
00:00/00:00
登录|注册

19|值对象(中):值对象有什么好处?

你好,我是钟敬。
上节课我们讲了值对象的基本概念和编程方法。实体和值对象的差别大体可以总结成这句话:实体是一个“东西”,而值对象是一个“值”,往往用来描述一个实体的属性。
学完前面的内容,不知道你会不会有这样的疑问:我们花了这么大的功夫来区分实体值对象,那么识别值对象有什么好处呢?今天我们就来聊这个问题。
值对象的优点,主要体现在内存和数据库布局的灵活性上。有了这种灵活性,就可以根据性能、编程方便性等因素,决定值对象的不同实现方式。其次,值对象的不变性也会带来更高的程序质量。这些优点,都是实体所不具备的。
那么,这里说的“布局”指什么呢?我们慢慢讲。先提示一下,后面有不少图片和代码,你可以边看文稿,边听我说。

对象的内存布局

先说内存里的布局,也就是程序运行的时候,对象在内存里是怎么存储的。为了说明这个问题,我们可以利用 UML 的对象图(Object Diagram)来分析。
假如有一个员工,名字叫“张三”,出生日期是“1990 年 1 月 1 日”,员工号是“1001”。他有两个技能:一个是 Go 语言,做过 3 年,达到中等水平;另一个是 Java 语言,做过 10 年,达到高级水平。他还有两段工作经历:从“2017 年 1 月 1 日”到“2022 年 1 月 1 日”在“ABC Inc”公司工作;从“2014 年 1 月 1 日”到“2016 年 12 月 31 日”在“123 Inc”工作。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

值对象在内存和数据库布局上具有灵活性和优势,是本文的主要讨论内容。在内存布局方面,值对象可以共享或不共享,而实体对象在内存空间里只能出现一次,这种灵活性是实体所不具备的。在数据库布局方面,值对象在数据库的存储方式上也有更多的灵活性。值对象的不变性也会带来更高的程序质量。此外,值对象还具有减少编程错误、利于并发以及利于函数式编程等好处。文章还提到了值对象在数据库里常常用“内嵌”的方式存储在实体表里,以及维护值对象的共享需要更复杂的编程。总的来说,值对象的灵活性和不变性为程序设计带来了许多优势,而实体则需要更复杂的程序逻辑来保证共享。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《手把手教你落地 DDD》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(13)

  • 最新
  • 精选
  • 南山
    个人理解嵌入的前提是实体与实体之间一对一关联的时候,要不要嵌入还要再做考虑,比如是否归属同一聚合内,是否经常一起变更等。

    作者回复: 没错

    2023-01-18归属地:江苏
    4
    11
  • py
    享元模式是Flyweight,不是lightweight

    作者回复: 十分感谢指出这个笔误,我尽快改。

    2023-02-22归属地:上海
    4
    2
  • 6点无痛早起学习的和尚
    这里有个问题请教一下: 1. 国内还是用 mybatis及mybatis plus 多一些,会根据数据库自动生成单表的 xxMapper 和 xxEntity,所以一般都在仓库的实现层做 xxEntity 和领域对象的转换是吧?不管是 save 、update、select 还是 delete

    作者回复: 是

    2023-02-15归属地:北京
    1
  • H·H
    值对象也可以以json形式内嵌 我理解实体不能内嵌,如果内嵌就成了另一个实体的值对象了

    作者回复: JSON也是一种可行的方式 内嵌实体的情况比较少,但理论上不能排除这种可能性。

    2023-02-01归属地:上海
    1
  • tt
    实体不可以采用内嵌的方式吧,因为实体有自己的标识,那么被内嵌到的实体数据如何保存唯一的标识呢?

    作者回复: 假如是一对一的话,是可以考虑嵌入的(但不是一定要嵌入)。这时可以理解为共用同一个标识。

    2023-01-17归属地:北京
    1
  • Geek1560
    技能和工作经验也可以定位成不可变的,当需要变化时,重建一个即可吧

    作者回复: 仅从技术角度似乎是可以的,关键在于是否正确反映了业务含义。比如说,对于技能,开发人员可以和领域专家聊聊:如果张三有Java技能,3年经验。明年变成了4年经验,这时候,是认为张三掌握了一项新技能,还是只是原有的技能(Java)的经验时长变了,但仍然还是原来那个技能。根据领域专家的回答,就可以做出判断了。

    2023-10-25归属地:上海
  • Faddei
    请问老师 工作经验和技能 这两个是实体吗?如果是实体的话,这两个又没有唯一的标识符;如果是值对象的话,工作经验和技能又都是可变的。有点搞不懂这两个

    作者回复: 只要可变,那么肯定是实体而不是值对象。对于技能来说“员工ID + 技能类别”就是唯一标识(注意,我没有用“符”字)。实体要求的唯一标识,只需要有一种方法(有可能是联合主键)能够唯一确定这个实体就可以了,不需要一定是单一的ID。

    2023-09-10归属地:浙江
  • Geek_79f5fb
    个人理解,数据库存储共享“地址”,这时候已经把“地址”作为实体看待了,而又在内存层面看成是值对象,中间做的转换感觉是一个伪工作。所以我理解值对象只有非共享模式。

    作者回复: 为什么数据库共享“地址”,就是看作实体了呢?

    2023-05-30归属地:浙江
  • Sam.张朝
    用mongoDB json 存储的话,属于自身的,都可以内嵌,如果没有外部关联查询

    作者回复: mongodb 是一种情况。就算用关系数据库,如果是一对一的关系,也可以内嵌

    2023-04-19归属地:上海
  • Michael
    不共享对象特别是地址这种数据,也是我们正在用的方式,这种方式还有一个不好的地方,就是duplicate太多数据在数据库,导致查询性能降低。所以又渐渐开始共享数据,确实会增加编程复杂性,那么请问老师对于不共享数据造成的查询性能下降有什么解决办法么?

    作者回复: 这要看一下具体的查询场景才能回答。比如利用索引,搜索引擎,还有后面讲的CQRS的一些思路。

    2023-03-07归属地:陕西
收起评论
显示
设置
留言
13
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部