1、内容摘要

最近在看DDD领域驱动设计,看到实体(Entity),值对象 (Value Object),以及聚合根(Aggregate Root) 时。对他们的关系有些模糊,不清楚。于是去找了找资料,看到有篇文章写的挺好的,于是分享出来给大家。

2、文章来源

http://www.cnblogs.com/netfocus/archive/2012/02/12/2347938.html 博客园用户名 :netfocus [ http://www.cnblogs.com/netfocus/ ]

3、文章详情

3.1 聚合根、实体、值对象的区别?

  • 从标识的角度:

    聚合根具有全局的唯一标识,而实体只有在聚合内部有唯一的本地标识,值对象没有唯一标识,不存在这个值对象或那个值对象的说法;
  • 从是否只读的角度:

    聚合根除了唯一标识外,其他所有状态信息都理论上可变;实体是可变的;值对象是只读的;
  • 从生命周期的角度:

    聚合根有独立的生命周期,实体的生命周期从属于其所属的聚合,实体完全由其所属的聚合根负责管理维护;值对象无生命周期可言,因为只是一个值;

3.2 聚合根、实体、值对象对象之间如何建立关联?

  • 聚合根到聚合根:通过ID关联;
  • 聚合根到其内部的实体,直接对象引用;
  • 聚合根到值对象,直接对象引用;

    实体对其他对象的引用规则:

    • 能引用其所属聚合内的聚合根、实体、值对象;
    • 能引用外部聚合根,但推荐以ID的方式关联,另外也可以关联某个外部聚合内的实体,但必须是ID关联,否则就出现同一个实体的引用被两个聚合根持有,这是不允许的,一个实体的引用只能被其所属的聚合根持有;

值对象对其他对象的引用规则:只需确保值对象是只读的即可,推荐值对象的所有属性都尽量是值对象;

3.3 如何识别聚合与聚合根?

明确含义: 一个Bounded Context(界定的上下文)可能包含多个聚合,每个聚合都有一个根实体,叫做聚合根;

识别顺序: 先找出哪些实体可能是聚合根,再逐个分析每个聚合根的边界,即该聚合根应该聚合哪些实体或值对象;最后再划分Bounded Context;

聚合边界确定法则: 根据不变性约束规则(Invariant)。不变性规则有两类:1)聚合边界内必须具有哪些信息,如果没有这些信息就不能称为一个有效的聚合;2)聚合内的某些对象的状态必须满足某个业务规则;

例子分析1:订单模型

Order(一 个订单)必须有对应的客户信息,否则就不能称为一个有效的Order;同理,Order对OrderLineItem有不变性约束,Order也必须至少有一个OrderLineItem(一条订单明细),否 则就不能称为一个有效的Order;另外,Order中的任何OrderLineItem的数量都不能为0,否则认为该OrderLineItem是无效 的,同时可以推理出Order也可能是无效的。因为如果允许一个OrderLineItem的数量为0的话,就意味着可能会出现所有 OrderLineItem的数量都为0,这就导致整个Order的总价为0,这是没有任何意义的,是不允许的,从而导致Order无效;所以,必须要求 Order中所有的OrderLineItem的数量都不能为0;那么现在可以确定的是Order必须包含一些OrderLineItem,那么应该是通 过引用的方式还是ID关联的方式来表达这种包含关系呢?这就需要引出另外一个问题,那就是先要分析出是OrderLineItem是否是一个独立的聚合 根。回答了这个问题,那么根据上面的规则就知道应该用对象引用还是用ID关联了。那么OrderLineItem是否是一个独立的聚合根呢?因为聚合根意 味着是某个聚合的根,而聚合有代表着某个上下文边界,而一个上下文边界又代表着某个独立的业务场景,这个业务场景操作的唯一对象总是该上下文边界内的聚合 根。想到这里,我们就可以想想,有没有什么场景是会绕开订单直接对某个订单明细进行操作的。也就是在这种情况下,我们 是以OrderLineItem为主体,完全是在面向OrderLineItem在做业务操作。有这种业务场景吗?没有,我们对 OrderLineItem的所有的操作都是以Order为出发点,我们总是会面向整个Order在做业务操作,比如向Order中增加明细,修改 Order的某个明细对应的商品的购买数量,从Order中移除某个明细,等等类似操作,我们从来不会从OrderlineItem为出发点去执行一些业 务操作;另外,从生命周期的角度去理解,那么OrderLineItem离开Order没有任何存在的意义,也就是说OrderLineItem的生命周 期是从属于Order的。所以,我们可以很确信的回答,OrderLineItem是一个实体。

例子分析2:帖子与回复的模型,做个对比,以便更好地理解。

>不变性分析:帖子和回复之间有不变性规则吗?似乎我们只知道一点是肯定的,那就是帖子和回复之间的关系,1:N的关系;除了这个之外,我们看不到任何其他的 不变性规则。那么这个1:N的对象关系是一种不变性规则吗?不是!首先,一个帖子可以没有任何回复,帖子也不对它的回复有任何规则约束,它甚至都不知道自 己有多少个回复;再次,发表了一个回复和帖子也没有任何关系;其次,发表回复对帖子没有任何改变;从业务场景的角度去分析,我们有发表帖子的场景,有发表 回复的场景。当在发表回复的时候,是以回复为主体的,帖子只是这个回复里所包含的必要信息,用于说明这个回复是对哪个帖子的回复。这些都说明帖子和回复之 间找不出任何不变性约束的规则;因为帖子和回复都有各自独立的业务场景的需要,所以可以很容易理解它们都是独立的聚合根;那也很容易知道该如何建立他们之 间的关联了,但是我们要尽量减少关联,所以只保留回复对帖子的关联即可;帖子没有任何必要去保存一个回复的ID的列表;那么你可能会说,当我删除一个帖子 后,回复应该是没有存在的意义的呀?不对,不是没有存在的意义,而是删除了帖子后导致了回复对帖子的关联信息的缺失,导致数据不一致。这是因为帖子和回复 之间有一种必然的联系(1:N),回复一定会有一个对应的帖子;但是回复有其自己的生命周期,不应该随着帖子的删除而级联删除。这种情况下,如果你删除了 帖子,就导致回复也成为了一条无效的数据;所以,我们绝对不允许删除任何聚合根,因为一旦你删除了聚合根,那就意味着与该聚合根相关的其他任何聚合根都会 有外键引用缺失的问题,会导致整个领域模型数据的不一致;所以,永远都不要删除聚合根;

4、精彩评论

感觉看着要

【转载自netfocus博客】聚合(根)、实体、值对象精炼思考总结的更多相关文章

  1. CSDN如何转载别人的博客

    前言   对于喜欢逛CSDN的人来说,看别人的博客确实能够对自己有不小的提高,有时候看到特别好的博客想转载下载,但是不能一个字一个字的敲了,这时候我们就想快速转载别人的博客,把别人的博客移到自己的空间 ...

  2. .net c#将数据库数据对象转换为实体值对象

    using System; using System.Data; namespace Sunlib { public static class DataHelper { //将数据库数据对象转换为实体 ...

  3. 五、Abp vNext 基础篇丨博客聚合功能

    介绍 业务篇章先从客户端开始写,另外补充一下我给项目起名的时候没多想起的太随意了,结果后面有些地方命名冲突了需要通过手动using不过问题不大. 开工 应用层 根据第三章分层架构里面讲到的现在我们模型 ...

  4. 解决ASP.NET上传文件大小限制------(转载人家的博客很好用,略作修改)

    解决ASP.NET上传文件大小限制 (2012-06-26 15:18:01) 转载▼ 标签: it   第一种方法,主要适用于IIS6.0版本 一.修改配置Web.Config文件中的httpRun ...

  5. CSDN怎么转载别人的博客

    在参考"如何快速转载CSDN中的博客"后,由于自己不懂html以及markdown相关知识,所以花了一些时间来弄明白怎么转载博客,以下为转载CSDN博客步骤和一些知识小笔记. 参考 ...

  6. CSDN怎么一键转载别人的博客

    在参考"如何快速转载CSDN中的博客"后,由于自己不懂html以及markdown相关知识,所以花了一些时间来弄明白怎么转载博客,以下为转载CSDN博客步骤和一些知识小笔记. 参考 ...

  7. HACMP 学习笔记--转载自wangjialiang-csdn博客

    An41 教程: Ha: 初始阶段的规划最重要 第一部分:概念和模型 Ha 目标:掩盖和消除计划和非计划的宕机 Eliminate SPOF :消除单节点故障, single point of fai ...

  8. CSS3 基础知识[转载minsong的博客]

    CSS3 基础知识1.边框    1.1 圆角  border-radius:5px 0 0 5px;    1.2 阴影  box-shadow:2px 3px 4px 5px rgba(0,0,0 ...

  9. B/S和C/S【转载Jane的博客 http://blog.sina.com.cn/liaojane】

    什么是C/S和B/S结构?         C/S又称Client/Server或客户/服务器模式.服务器通常采用高性能的PC.工作站或小型机,并采用大型数据库系统,如Oracle.Sybase.In ...

随机推荐

  1. Node.js + gulp 合并静态页模版,文件更新自动热重载。浏览器可预览

    github地址:https://github.com/Liaozhenting/template 使用的是ejs的语法.其实你用什么文件后缀都可以,都是按ejs来解析. 模板文件放在componen ...

  2. 学号:201621123032 《Java程序设计》第5周学习总结

    1:本周学习总结 1.1: 写出你认为本周学习中比较重要的知识点关键词 接口interface,comparator接口和comparable接口. 1.2:尝试使用思维导图将这些关键词组织起来. 2 ...

  3. python 进程复习

    import os import time ret = os.fork() # 创建子线程 if ret ==0: # 子进程中返回值为0,父进程>0 while True: print('.. ...

  4. 关于GPUImage的导入

    对于GPUImage的使用方面,GitHub上已经非常详细了,就不一一赘述了,但是对于项目的导入来说,最好的方式是 1.下载GPUImage并解压 2.打开压缩包后如图 3.打开终端,cd到此目录 4 ...

  5. Angular组件——组件生命周期(一)

    组件声明周期以及angular的变化发现机制 红色方法只执行一次. 变更检测执行的绿色方法和和组件初始化阶段执行的绿色方法是一个方法. 总共9个方法. 每个钩子都是@angular/core库里定义的 ...

  6. 一句话了解JAVA与大数据之间的关系

    大数据无疑是目前IT领域的最受关注的热词之一.几乎凡事都要挂上点大数据,否则就显得你OUT了.如果再找一个可以跟大数据并驾齐驱的IT热词,JAVA无疑是跟大数据并驾齐驱的一个词语.很多人在提到大数据的 ...

  7. OpenCASCADE Trihedron Law

    OpenCASCADE Trihedron Law eryar@163.com Abstract. In differential geometry the Frenet-Serret formula ...

  8. JAVA_SE基础——36.static的实际应用

    什么时候定义静态函数 如果功能内部没有访问到非静态数据(对象的特有数据.那么该功能就可以定义为静态) P.S. 静态方法作为类和接口的重要组成部分,可以通过类名或接口直接访问,通常将那些使用频率较高的 ...

  9. JAVA_SE基础——17.方法的重载

    方法重载: 方法重载就是方法名称重复,加载参数不同. 具体规范: 一.方法名一定要相同. 二.方法的参数表必须不同,包括参数的类型或个数,以此区分不同的方法体. 1.如果参数个数不同,就不管它的参数类 ...

  10. Extensions in UWP Community Toolkit - Overview

    概述 UWP Community Toolkit  中有一个 Extensions 的集合,它们可以帮助开发者实现很多基础功能,省去自己造轮子的过程,本篇我们先来看一下 Extensions 的功能都 ...