怎么样划分聚合

一下内容学习汤学华的博文,包括但不限于这个网址:http://www.cnblogs.com/netfocus/archive/2012/02/12/2347938.html

实体有ID、生命周期、有状态(用值对象来描述状态)、实体通过ID进行区分不同实体对象(只要在聚合内唯一即可)

聚合根是实体,ID是全局唯一的,

值对象的核心意思是值,不考虑类型,值对象用于描述实体的状态

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

从标识的角度:

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

从是否只读的角度:

聚合根除了唯一标识外,其他所有状态信息都理论上可变;实体是可变的;值对象是只读的;

从生命周期的角度:

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

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

聚合根到聚合根:通过ID关联;

聚合根到其内部的实体,直接对象引用;

聚合根到值对象,直接对象引用;

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

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

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),回复一定会有一个对应的帖子;但是回复有其自己的生命周期,不应该随着帖子的删除而级联删除。这种情况下,如果你删除了 帖子,就导致回复也成为了一条无效的数据;所以,我们绝对不允许删除任何聚合根,因为一旦你删除了聚合根,那就意味着与该聚合根相关的其他任何聚合根都会 有外键引用缺失的问题,会导致整个领域模型数据的不一致;所以,永远都不要删除聚合根;

以User,Blog(你应该是指博客随笔或文章吧?),CommentOfBlog为例:
User一定可以独立,这点你也没异议;
Blog呢?首先User和Blog是一对多的关系,User可以发表多篇blog,但这不表明user离开blog就不能活了,或者说是否user离开blog就没意义了?显然不是。因此可以推理出user不需要聚合blog;从blog的角度分析,虽然每个blog都有一个作者(author,user类的一个实例),但是blog存在的意义是否总是为了user而存在,我们创建blog的目的是为了被内聚到user吗?显然不是,blog创建的目的与user无关,我们是为了写随笔而创建blog,我们创建一个blog不是为了在user里增加一个blog。所以,应该理解为blog.Author,即author只是一个blog的关联属性,表示谁创建了该blog。

CommentOfBlog:一个blog可以有多个comment,从blog角度分析,blog是否必须聚合comment?不见得,因为blog可以没有评论;但是从comment的角度来看,comment是否总为为了blog二存在?实际上是的,1)comment可以属于其他的Blog吗?不可以;2)comment被创建的目的是为了评论blog,可以说离开blog谈comment总是完全没有任何意义。所以我们会让blog聚合comment。

之前我们分析聚合,可能更多的仅仅总是从一方面去分析,就是会分析当前聚合根应该聚合哪些对象,而不会从哪些被聚合的实体上去分析它是否真的应该被聚合还是应该独立。所以有时的出来的聚合会不准确。

另外一篇博文

http://www.cnblogs.com/daxnet/archive/2011/12/24/2300169.html

时间: 2024-10-13 01:52:30

怎么样划分聚合的相关文章

领域驱动设计之聚合与聚合根实例一

通过一个实例来说明如何划分聚合与聚合根 场景:一个下订单的业务,一个订单必须有相应的客户信息,订单下有订单项,每个订单项必须有相应的产品信息,产品有分类的信息. 1.根据这个基本的需求,我们初步确定的实体.值对象与关联关系为(这里采用EF的Model First): 2.经过业务深入分析,以及聚合与聚合根确定原则,最终我们确定的聚合与聚合根是(红色代表聚合根,蓝色代表聚合内的实体,灰色代表值对象): 划分与确定理由1.订单.客户与产品都可以在不同的领域被独立访问到,所以应该是属于不同聚合的聚合根

NOSQL(二)聚合数据模型

<NoSQL精粹>读书笔记,转载请注明出处<jiq?钦's technical Blog> 一.NoSQL的数据模型 关系型数据库的数据模型是"关系"和"元组",一个关系对应一张表,而一个元组对应一行,其中元组由一系列的值组成,不能嵌套. NoSQL数据库最大的转变就是抛弃了关系模型.但是每种NoSQL解决方案模型都不同,大体上可以将NoSQL数据模型分为四类:"键值"."文档"."列族&qu

关于聚合设计与cqrs

记得在去年的时候,也就是14年下半年的时候,那个时候第一次系统得学习领域驱动设计.在此之前,从<企业应用架构模式>中对领域驱动的设计,有所耳闻,并自己瞎摸索实践了,有大概一年. 后来,啃<领域驱动设计>一书,对其中的构件有了一些系统的了解,但是,仍然缺乏经验.当时,用面向对象设计的原则来划分聚合,用四分法来划分聚合,查cqrs,其实都感觉有些无力.经过两三个小项目的磨合,对其中的一些坑和原则,已有一些体会.直到后来,啃了<实现领域驱动设计>.书中对各种设计进行了相当详细

企业级业务系统开发实战

通过一个系列讲述一个真实企业的ERP系统开发全过程.其中包括需求分析.设计建模.开发.测试全生命周期过程,其中会详细讲方法论与技术实践.涉及到的方法包括敏捷软件开发.四色原型.领域驱动设计.业务架构.技术架构与具体的EF.WF.EasyUI等技术在项目中的使用. 领域驱动设计案例之领域层框架搭建 摘要: 根据前面对领域驱动设计概念以及一些最佳实践的理解,领域模型是系统最核心的部分,我们还是采用前面销售订单的例子,这个案例系统的核心构建就从领域层开始.领域层框架搭建主要完成两个任务:1.领域模型的

以DDD为开发模式的设计开发步骤可以是

以DDD为开发模式的设计开发步骤可以是:1)分析需求:2)画出用例图,系统中各个角色如何使用系统,也包括外部系统如何使用系统,也包括系统中到某个时间点自动启动的某些功能(此时角色就是时间):3)针对各个用例图,就知道了系统使用的各种业务场景,同时也明确了系统的边界,从而就明确了领域模型的边界:4)在领域模型的边界内划分聚合,找出每个聚合的边界,找出边界内的聚合根,实体,值对象:这步是难点.这里一定不能混淆的一个概念是,领域建模不是以用户为中心的建模,而是以用户的需求为中心的建模.所以要努力寻找各

聚合的划分(二)---再次总结

聚合划分原则: 有很多个实体.值对象表现了一个完整的概念,他们之间是有很强关联的. 找最小的业务场景 找出聚合根(先确定可能是聚合根的实体,可能包含的实体),确定的原则是:具有独立的生命周期 确定聚合根的边界,如包括 Entity1,E2,E3....这些实体要依赖于聚合根的存在而存在.聚合边界确定法则:根据不变性约束规则(Invariant),有两类:1)聚合边界内必须具有哪些信息,如果没有这些信息就不能称为一个有效的聚合:2)聚合内的某些对象的状态必须满足某个业务规则: 对象间是有规则的(如

Linux Redhat6.5中 vlan划分和trunk聚合

虚拟局域网(VLAN)是一组逻辑上的设备和用户,这些设备和用户并不受物理位置的限制,可以根据功能.部门及应用等因素将它们组织起来,相互之间的通信就好像它们在同一个网段中一样,由此得名虚拟局域网.VLAN是一种比较新的技术,工作在OSI参考模型的第2层和第3层,一个VLAN就是一个广播域,VLAN之间的通信是通过第3层的路由器来完成的.与传统的局域网技术相比较,VLAN技术更加灵活,它具有以下优点: 网络设备的移动.添加和修改的管理开销减少:可以控制广播活动:可提高网络的安全性.在计算机网络中,一

聚合(根)、实体、值对象精炼思考总结

1.      聚合根.实体.值对象的区别? 从标识的角度: 聚合根具有全局的唯一标识,而实体只有在聚合内部有唯一的本地标识,值对象没有唯一标识,不存在这个值对象或那个值对象的说法: 从是否只读的角度: 聚合根除了唯一标识外,其他所有状态信息都理论上可变:实体是可变的:值对象是只读的: 从生命周期的角度: 聚合根有独立的生命周期,实体的生命周期从属于其所属的聚合,实体完全由其所属的聚合根负责管理维护:值对象无生命周期可言,因为只是一个值: 2.      聚合根.实体.值对象对象之间如何建立关联

ENode框架Conference案例分析系列之 - 上下文划分和领域建模

前面一片文章,我介绍了Conference案例的核心业务,为了方便后面的分析,我这里再列一下: 业务描述 Conference是这样一个系统,它提供了一个在线创建会议以及预订会议座位的平台.这个系统的用户有两类:1)客户,可以创建和管理会议:2)会议座位预定者,可以预订会议座位.具体的关键业务描述如下: 客户创建一个会议,并录入会议的基本信息,比如名称.时间段.地点,等:会议创建后,系统会为客户自动生成一个AccessCode,客户可以通过AccessCode访问自己创建的会议: 客户定义某个会