从壹开始微服务 [ DDD ] 之五 ║聚合:实体与值对象 (上)

 系列教程一目录:.netcore+vue 前后端分离

系列教程二目录:DDD领域驱动设计

 

 

正文

前言

哈喽,老张是周四放松又开始了,这些天的工作真的是繁重,三个项目同时启动,没办法,只能在深夜写文章了,现在时间的周四凌晨,白天上班已经没有时间开始写文章了,希望看到文章的小伙伴,能给个辛苦赞👍哈哈,当然看心情很随意。废话不多说,话说上次咱们对DDD简单说明了下存在的意义,还有就是基于教学上下文的第一次定义,今天咱们就继续说说DDD领域驱动设计中的聚合相关知识,聚合这一块比较多,我暂时决定用两到三篇文章来说说,今天就主要说一下“实体和值对象”的相关概念,其实之前我在定计划的时候,感觉这一块应该很好说,但是晚上吃完饭搜索资料的时候,发现真的好多人对实体理解的还好,但是对值对象真是各种不理解,甚至嗤之以鼻,这一点我感觉是不好的,希望我的读者不要只会说这个不好,那个不对,而是想,这个东西既然产生了,并且一直被大家说着,也有在使用的,肯定有存在的意义,举个栗子,可能今天大家看完对值对象还是蒙胧胧,多想想,多跟着DDD的思想走,也许就好多了,思想真的很难改变,不过只要努力了就是成功了。

好!咱们还是开篇一个小问题,给大家正好一个思考的时间:

咱们从壹大学的后台系统中,每个学生都有自己的家庭住址,肯定会有这样或那样的原因,会变化,那我们是如何设计 Student模型 和 Address 模型的呢,这里只是说代码实现上,数据库其实是对应的。

1、在Students实体中,添加家庭地址属性:省、市、县、街道;

2、新建家庭地址Address实体,在Student中引入地址外键;

3、新建 Students 、Address、StuAdd三个表,在Students中引入List<Address>,一对多;

这个就是我们平时的思路,无论是第一种的一对一(一个学生一个家庭地址),还是第三种的一对多(一个学生多个家庭地址),如果你对这个思路很熟悉,那就需要好好看看今天的文章了,因为上边的这种还是面向数据库数据开发的,希望下边的说明,能让你对DDD的思想有一定的体验。

 

零、今天要实现蓝色的部分

 

 一、实体 —— 唯一标识

实体对应的英语单词为Entity。提到实体,你可能立马就想到了代码中定义的实体类。在使用一些ORM框架时,比如Entity Framework,实体作为直接反映数据库表结构的对象,就更尤为重要。特别是当我们使用EF Code First时,我们首先要做的就是实体类的设计。在DDD中,实体作为领域建模的工具之一,也是十分重要的概念。

但DDD中的实体和我们以往开发中定义的实体是同一个概念吗?
不完全是。在以往未实施DDD的项目中,我们习惯于将关注点放在数据上,而非领域上。这也就说明了为什么我们在软件开发过程中会首先做数据库的设计,进而根据数据库表结构设计相应的实体对象,这样的实体对象是数据模型转换的结果。
在DDD中,实体作为一个领域概念,在设计实体时,我们将从领域出发。

1、DDD中的实体是什么

许多对象不是由它们的属性来定义,而是通过一系列的连续性(continuity)和标识(identity)来从根本上定义的。只要一个对象在生命周期中能够保持连续性,并且独立于它的属性(即使这些属性对系统用户非常重要),那它就是一个实体。

对于实体Entity,实体核心是用唯一的标识符来定义,而不是通过属性来定义。即即使属性完全相同也可能是两个不同的对象。同时实体本身有状态的,实体又演进的生命周期,实体本身会体现出相关的业务行为,业务行为会实体属性或状态造成影响和改变。

如果从值对象本身无状态,不可变,并且不分配具体的标识层面来看。那么值对象可以仅仅理解为实际的Entity对象的一个属性结合而已。该值对象附属在一个实际的实体对象上面。值对象本身不存在一个独立的生命周期,也一般不会产生独立的行为。

2、为什么要使用实体

当我们需要考虑一个对象的个性特征,或者要区分不同对象的时候,我们就需要一个实体这个领域概念,一个实体是一个唯一的东西,并且可以长时间相当长的一段时间内持续的变化,但是无论我们做了多少变化,这个的实体对象可能也已经变化的很多了,但是因为他们都一个相同的身份标识,所有还是同一个实体。很简单,就好像一个学生,无论手机号,姓名,年龄,邮箱,是否毕业等等,全部变化了,因为唯一标识的原因,我们就可以认为,变化前后的所有对象,都是同一个实体。随着对象的改变,我们可能会一直跟踪变化过程,什么时候,什么人,发生了什么变化:就比如学生因为学习太好,学校研究通过,提前毕业,更新状态为已毕业等。
这个时候我们发现了,实体的两大特性:
1、有唯一的标识,不受状态属性的影响。
2、可变性特征,状态信息一直可以变化。
 

二、定义一个实体

 在我们之前的代码中,我们定义了 Student 模型,我们是在当前模型中,添加了唯一标识 
复制代码
    public class Student    {        protected Student() { }        public Student(Guid id, string name, string email, DateTime birthDate)        {            Id = id;            Name = name;            Email = email;            BirthDate = birthDate;        }        public Guid Id { get; private set; }//模型的唯一标识        public string Name { get; private set; }        public string Email { get; private set; }        public string Phone { get; private set; }        public DateTime BirthDate { get; private set; }    }
50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信