DDD中的对象

11 篇文章 0 订阅
1 篇文章 0 订阅
“对象”这个词,对我们来说并不陌生。以最常见的面向对象为例,软件系统中的任何事物都被认为是一种对象。针对如何设计和实现这些对象,业内也有一些对应的开发模式。例如,一种传统的做法是从数据的角度来规划对象的组织形式,即先设计数据库模型,然后基于数据库模型设计对象,这些对象内部通常只包含数据属性的定义,也就是说整个开发过程是数据驱动(Data Driven)的。
![在这里插入图片描述](https://img-blog.csdnimg.cn/19f8698645f34ec2b50edb3696629ff3.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAYW5keS5jYW8=,size_20,color_FFFFFF,t_70,g_se,x_16)
图1 数据驱动的开发模式示意图
随着 DDD 设计思想日渐深入人心,数据驱动不再是一种最理想的对象设计方法,取而代之的是采用领域驱动(Domain Driven)的方法来设计系统中的对象。为此,DDD 专门引入了一个全新的对象——聚合(Aggregate)对象。那么问题来了。
什么是聚合对象?
如何设计聚合对象?
今天我们就针对这两个问题展开讨论。我们先来看第一个问题。

什么是聚合对象?

在 DDD 中,对象的设计过程是领域驱动的,这和数据驱动完全不同。这些领域模型对象内部不仅仅定义了数据属性,还包含了业务逻辑的处理过程。图 2 就展示了数据对象与领域模型对象的这种差异。
![在这里插入图片描述](https://img-blog.csdnimg.cn/91ae8a8c05864f03b4cebfa2516c1a49.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAYW5keS5jYW8=,size_20,color_FFFFFF,t_70,g_se,x_16)
图2 数据对象与领域模型对象的差异
和限界上下文被用来划分子域之间的业务边界一样,在领域模型对象中,我们也需要从软件复杂度出发,明确对象之间的边界。现在,假设系统中存在 8 个对象,那么它们之间的交互方式就像图 3 展示的这样:
![在这里插入图片描述](https://img-blog.csdnimg.cn/b232ccbb4b9549b9a3e24b5a8181b37f.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAYW5keS5jYW8=,size_16,color_FFFFFF,t_70,g_se,x_16)
图3 8个对象的一种交互示意图
从图 3 中,我们可以看出,原则上这 8 个对象之间的交互方式最多可以达到 255(2 的 8 次方 -1)种。而一个系统里的对象显然远远不止这个数量, 系统的复杂度会随着对象数量的增多而急剧上升,这也是架构腐化的一个根源 。为了降低这种对象交互带来的复杂度,DDD 引入了聚合对象的概念。那么,聚合对象是如何解决这一点的呢?
聚合的设计思想实际上很简单,就是 尽量减少系统中对象之间的关联关系,简化外部组件对领域模型对象的访问入口,从而降低系统的复杂度。
现在,我们已经明确了 DDD 中聚合的设计思想,下面我们来讨论一下它的组成结构。聚合由两部分组成,分别是聚合根和聚合边界。
聚合根:聚合对外暴露的访问对象,外部组件只能通过这个聚合根对象实现对聚合的 CRUD 操作。
聚合边界:聚合的业务边界和范围,规定了一个聚合内部应该具备的业务逻辑和操作。
图4 聚合对象的结构示意图
换句话说,对一个聚合来说,外部组件只能看到一个聚合根对象,而位于聚合边界内部的其他对象只能通过聚合根进行关联。通过这种固定的规则,我们也确保聚合内部的数据操作具有严格的事务性。我们回到前面讨论的那 8 个对象,运用聚合思想,就可以得到类似图 5 的效果。
![在这里插入图片描述](https://img-blog.csdnimg.cn/4c6ae890cdf34d868077a93f7b19a96c.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAYW5keS5jYW8=,size_18,color_FFFFFF,t_70,g_se,x_16)
图5 聚合对象的交互示意图
可以看到,我们把原来的 8 个对象拆分成了 3 个聚合对象,每个聚合对象有一个明确的边界,内部包含了一定数量的领域模型对象。而这 3 个聚合对象之间的交互只能通过各自的聚合根。这样,对象之间的最多有 7 种交互方式(2 的 3 次方 -1),而不是原来的 255 种。

如何设计聚合对象?

现在,我们已经了解了“什么是聚合对象?”。接下来讨论今天的第二个问题——如何设计聚合对象?
事实上,在 DDD 中,领域模型对象包括三大类。除了聚合对象之外,还包括实体(Entity)和值对象(Value Object)。
图6 领域模型对象的三大类型
在这三种领域模型对象中,聚合是核心。实体和值对象是聚合的组成部分,而值对象同时也是实体的组成部分,这三种对象之间的关系是这样的:
图7 领域模型对象之间的组成关系示意图
接下来,我们先从实体对象开始讲起。实体对象是构成聚合对象的基础。事实上,聚合中的聚合根就是一种实体对象。
实体
实体对象和数据对象的区别在于,实体中除了定义了数据属性之外,还包含了业务的状态以及围绕这些状态所产生的生命周期,也就是说它具有可变性。同时,我们也需要使用唯一标识来区分不同的实体对象,所以它还具有唯一性。
图8 实体对象的唯一性和可变性
唯一标识(Identity)是实体对象必须具备的一种属性,也是实体与值对象之间的核心区别之一。实体对象的唯一标识概念比较好理解,实现起来方法也有很多。而所谓的可变性,指的是实体对象一般都会具备自己的基础业务方法,对自身对象的各种状态进行统一的管理和维护。图 9 展示了一个典型的实体对象的表现形式,这个对象来自客户系统中的工单管理场景。
![在这里插入图片描述](https://img-blog.csdnimg.cn/1296becb3dea41d68b931eca28a27a23.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAYW5keS5jYW8=,size_20,color_FFFFFF,t_70,g_se,x_16)
图9 实体对象的可变性示意图
值对象
值对象的特征决定了分离值对象的方法。和实体对象相比,值对象自身没有状态,所以是一种不可变对象。在设计过程中,通常我们会先识别系统中的实体对象,然后从实体对象中分离出潜在的值对象。图 10 给出了实现这一过程的示例。
![在这里插入图片描述](https://img-blog.csdnimg.cn/f4fc79a9ead74a6886fa5515f381dc00.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAYW5keS5jYW8=,size_18,color_FFFFFF,t_70,g_se,x_16)
图10 从实体中分离值对象
在图 10 中,我们首先设计了一个订单对象 Order,显然这个对象具有唯一标识符 orderNumber,所以是一个实体对象。然后我们发现 Order 对象中包含了收货地址相关的 street、city 和 state 属性,而这三个属性就可以被抽取成一个值对象 DeliveryAddress。因为一个收货地址,可以被多个订单共用,不需要具备唯一标识,而且也没有可变性。如果我们需要改变收货地址,通常会新生成一个 DeliveryAddress 对象。
聚合
介绍完实体和值对象之后,我们通过一个简单的案例来解释聚合建模的实现过程。在日常开发过程中,我们通常都需要对业务功能(Feature)进行评审,然后通过拆分任务(Task)的方式完成工作量评估和排期(Schedule)。在这个业务场景中,一个业务功能可以创建很多任务,同时需要评估出一个排期。通过分析,我们可以识别 Feature、Task、Schedule 这三个领域模型对象。图 11 展示了上述场景的聚合建模方案。
![在这里插入图片描述](https://img-blog.csdnimg.cn/d6d6048067594e56b738f546c5154d89.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAYW5keS5jYW8=,size_19,color_FFFFFF,t_70,g_se,x_16)
图11 聚合建模方案
可以看到,这里我们把 Feature 和 Task 设计成了聚合对象,并通过两个值对象分别指定它们的唯一标识,而把 Plan 设计成了一个实体对象。

总结

如果你正在开发一个 DDD 应用程序,那么识别系统中的聚合对象并完成建模是一项必不可少的工作。针对系统中的每一个子域以及上下文边界,我们首先需要对其中存在的各种对象进行区分。在实体、值对象的基础上构建聚合对象,确保边界的完整性和对象访问的有效性。
聚合建模方法需要考虑业务场景和限界上下文,有时候并没有标准的设计方案,而是取决于你对业务模型的理解和分析。今天我们针对聚合的设计思想和表现形式进行了详细的分析,帮助你更好地把它应用到日常开发过程中。
![在这里插入图片描述](https://img-blog.csdnimg.cn/c3338a3c8d554366985ed0cc53ba1988.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAYW5keS5jYW8=,size_20,color_FFFFFF,t_70,g_se,x_16)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值