聚合Aggregate

什么是聚合:

聚合是一个更大的封装单位,而不仅仅是一个类。每个事物的范围限定在单个聚合内。聚合组件的使用期被界限在整个聚合的生命周期中。
具体的,一个聚合将会处理命令,请求事件,并在其中封装一个状态模型,使其能够实现所需的命令验证,从而维护聚合的不变量(即业务规则)

聚合和聚合根之间有什么区别:

聚合形成对象关系的树或者图。而聚合根是树的“顶”,它总体上说明了聚合并且代表了剩余部分,它很重要因为他是所有通信的地方。

我知道聚合是事务边界,但我真的需要在同一个事务中事务更新两个聚合。我该怎么办?

我们应该重新思考如下:
   ①你的聚合边界
   ②每个聚合的自责
   ③你怎么样才可以侥幸逃脱掉在读的一端或者在一个saga中
   ④你的领域的真实的非功能性的需求
   如果你写了一个解决方案,但是有两个或者多个的聚合以事务的方式耦合了,那么就说明你没有理解聚合

为什么使用GUID作为ID是一个很好的做法?

因为它们(合理)全局唯一,并且可以由服务器或客户端生成。

如何获取新创建的聚合的ID?

这是一个重要的见解,客户端可以生成自己的ID。
如果客户端生成了GUID并且将其放在创建聚合的命令中,这不是一个问题。否则,你需要从适当的读取端进行轮询,其中ID将以最终一致的时间框架出现。显然,这种是比在一开始就生成的方式要
脆弱的多的

我们应该允许聚合间的引用吗?

从真实的“内存引用”的意义而言,当然是不可以的
在写方面,一个真实的从一个聚合到另外一个聚合的内存引用是不对和禁止的。因为聚合的定义不允许到达他自己的外部(如果允许的话,那么意味着聚合不再是事务边界,意味着我可以不再去
思考维护其不变量的能力,他亦阻止了聚合的分隔)
使用字符串标识符引用另一个聚合是可以的。在写方面是没有用的(因为标识符必须被视为不透明的值,因此聚合不能到达自身之外)。读的一端可能自由的使用这些信息来进行有趣的相关性

如何在一组聚合中验证命令?

这是一种再也无法通过聚合进行查询了的常见的副作用,有几个答案:
①客户端验证
②使用读的一端
③使用saga
④如果那些完全不切实际,那么这就该考虑是否是聚合的边界不对

如何保证整体的引用完整性?

你现在仍在思考外来的关系引用,而不是聚合。看最后的那个问题。当然,记住仅仅因为是两个表的关系设计不易任何方式表明他们是两个聚合。聚合设计是不同的

如何确保新创建的用户具有唯一的用户名?

这是一个常见的问题,因为我们明确地不会在写方面执行交叉聚合操作。但是,我们有很多选择:
①创建一个已经分配了用户名字的读取端。让客户端可以交互式的以键入用户名的方式查询读取端。
②创建一个响应式的saga来标记和停用那些不过是以用户名的读本创建的账户(无论是否是极端巧合或者恶意的或者由于客户的错误)
③如果最终的一致性不够快,那么可以考虑在写的一端添加一个小的本地读取方面得标。确保聚合的食物插入该表

当我下订单时,如何验证客户ID是否真的存在?

假设客户和订单都聚集在这里,很明显,订单的聚合是不能验证这个的,因为这意味着到达了聚合之外了
在事实之后检查,在一个记录了‘broken’订单的saga或者仅仅在一个读取端。毕竟,订单的最重要的事实完全的记录它,大概任何关于订单的收件人的有趣的数据将会被复制到订单聚合中
(引用到用户去访问其地址是坏的设计,订单总是用来提供一个特定的地址,无论是否在未来客户改变他们的地址)
能够使用那些被记录在破损订单的数据意味着你有机会来拯救它,扭转局面---这使得比下列命令更有意义,因为违反外键约束!

如何使用单个命令更新一组聚合?

单一的命令是不能操作一组聚合的。
首先,问问自己你是不是真的需要一个命令更新多个聚合,是什么情况导致这个需求。
然而,你是可以这么做的。允许一种新的“批量命令”。在概念上包含你想要发布的命令以及一组您要发布的聚合(指定或明确指定)。写入段不够强大到处理这种批量操作,但是它可以创建相应
的”批量事件”。一个saga捕获这个事件,并在每个指定的聚合上执行命令。当命令失败的时候,saga可以视情况调用rollback或者发送一封邮件。
这种方法有一些优点:我们将批量操作的意图存储在事件存储中。saga自动回滚或等效。
尽管如此,不得不诉诸于此解决方案,这表明您的聚合的总体边界并不正确。你可能想考虑改变你的聚合边界,而不是为此建立一个saga。

什么是分片?

一种在多个写入端节点上分发大量聚合的方式。我们可以很容易地分解聚合,因为它们完全是自立的。
我们可以很容易地分割聚合,因为它们没有任何外部引用。

聚合可以将事件发送到另一个聚合?

不可以
你的聚合和命令处理器这些因素代表性的早已在代码中使这个想法无法表达,但是有一个更深层次的哲学原因:
    回去重新读第一个问题“what's an aggregate?”
如果你设法规避命令处理程序,将事件推向另外一个聚合,那么你将会失去聚合的参与验证的变化的机会。这就是为什么我们仅仅允许聚合器上的命令处理程序验证的命令创建事件。

我能从我的聚合中调用一个读取端吗??

不可以

在CQRS系统中我们么发送email

在聚合之外的时间处理器,不要早命令处理程序中执行此操作,就像这个事件由于丢掉了与其他命令竞争而不会被持久化,所以email将会在一个虚假的前提下被发送。

你可能感兴趣的:(聚合Aggregate)