济南 域名注册 网站建设,商城网站建设定制,网站维护怎么学,深圳网页设计公司搜行者seo1.引言
聚合#xff0c;最初是UML类图中的概念#xff0c;表示一种强的关联关系#xff0c;是一种整体与部分的关系#xff0c;且部分能够离开整体而独立存在#xff0c;如车和轮胎。
在DDD中#xff0c;聚合也可以用来表示整体与部分的关系#xff0c;但不再强调部分…1.引言
聚合最初是UML类图中的概念表示一种强的关联关系是一种整体与部分的关系且部分能够离开整体而独立存在如车和轮胎。
在DDD中聚合也可以用来表示整体与部分的关系但不再强调部分与整体的独立性。聚合是将相关联的领域对象进行显示分组来表达整体的概念也可以是单一的领域对象。比如将表示订单与订单项的领域对象进行组合来表达领域中订单这个整体概念。
我们知道领域模型是由一系列反映问题域概念的领域对象实体和值对像组成聚合正是应用在领域对象之上。如果要正确应用聚合我们首先得理清领域对象间的关联关系。
2. 梳理关联关系
在设计领域模型的初期我们习惯专注于领域中的实体和值对象而忽略领域对象之间的关联关系以至于我们会基于现实业务场景或数据模型来建立关联关系。这样就会引入大量不必要的关联比如下图 frameborder0 scrollingno styleborder-width: initial; border-style: none; width: 474px; height: 270px;
然而图中的关联关系都是必要的吗我想未必。这样的关联关系加大了实现领域模型的技术难度。
当我们建立对象的关联关系时思考以下问题
这个关联关系的作用时什么谁需要这个关联关系去发挥作用
而如何简化关联呢
基于业务用例而非现实生活建立必要的关联减少不必要的关联将双向的关联转换为单向关联
如果遵从这个原则那我们的领域模型将会是这样的 frameborder0 scrollingno styleborder-width: initial; border-style: none; width: 539px; height: 321px;
领域对象间清晰的关联关系能够清晰反映领域概念便于我们设计出比较理想的领域模型。理清了领域对象间的关联关系我们下面来应用聚合。
3. 应用聚合
领域对象不是孤立存在的往往几个对象的组合才能表示一个完整的概念如上文所说的订单和订单项。那如何组合对象呢也就是我们本文的主题。聚合是领域对象的显示分组旨在支持领域模型的行为和不变性同时充当一致性和事务性边界。这句话涉及到几个概念我们来拆解一下
领域对象的显示分组领域行为和不变性一致性和事务性边界
其中我们需要澄清下领域不变性 Domain invariants are statements or rules that must always be adhered to.领域不变性指的是必须遵守的陈述或规则。换句话说就是领域内我们关注的业务规则。比如订单必须具有唯一订单编号、订单日期订单必须冗余商品的基本信息名称、价格、折扣订单至少有一个商品删除商品时订单项需要一并删除等等。 前两句话综合来说就是聚合通过对领域对象的封装来体现领域中的业务规则。而边界的目的是分离聚合内外聚合内通过事物来保证强一致性。
总而言之聚合不仅仅是简单的对象组合其主要的目的是用来封装业务和保证聚合内领域对象的数据一致性。
一致性和事务性边界又如何理解呢一致性是指数据一致性事务性指的数据库的ACID原则。下面我们来着重介绍下。
4.一致性边界
为了确保系统的可用性和可靠性我们必须保证数据的一致性。 订单支付成功后订单状态要更新为已支付状态且现有库存要根据订单中商品实际销售数量进行扣减。 下面我们就以这个案例来分析说明。
4.1.事务一致性
针对这个用例传统的做法就是在一个事务中去更新订单状态和扣减库存。这样似乎满足了业务场景需求但是我们不得不考虑另外一个问题——并发冲突。比如在更新订单的同时商城来了一批货要进行库存更新这个时候就存在潜在的冲突而问题可能表现为数据库级别的阻塞或更新失败由于悲观并发如下图 frameborder0 scrollingno styleborder-width: initial; border-style: none; width: 841px; height: 379px;
这个并发问题我们该如何解决呢首先我们要分析问题的原因这个用例陈述了具体的业务规则。我们错误的将业务涉及到的所有领域对象都放到了一个事务性边界中去了。其实这个用例涉及到三个子域销售、商品、库存子域。从领域不变性的角度来看我们应该维护各自子域内业务规则的不变性而不是为了业务场景实现一概而论。按照这个思想我们把订单、商品、库存拆分成三个独立的聚合如下图所示。 frameborder0 scrollingno styleborder-width: initial; border-style: none; width: 841px; height: 442px;
从图中我们可以看出每个聚合都有自己的事务一致性边界。也就是说这三个聚合分别在不同的事务中维持自己的不变性也就是说聚合是用来维护内部事务一致性。那针对以上用例明显需要跨域多个聚合我们又该如何保证一致性呢因为我们不能在一个事务中更新多个聚合所以我们只能实现最终一致性。
4.2. 最终一致性
最终一致性的实现原理是借助领域事件来完成事务的拆分如下图所示。 frameborder0 scrollingno styleborder-width: initial; border-style: none; width: 841px; height: 257px;
而针对我们的用例在更新订单支付状态时发布一个订单已支付的领域事件库存聚合订阅处理这个事件即可完成库存的更新。事务拆分如下图 frameborder0 scrollingno styleborder-width: initial; border-style: none; width: 736px; height: 454px;
4.3. 特殊情况
凡事没有绝对在一个聚合中仅修改一个聚合是最佳方法。但有时候在一个事务中更新多个聚合也是可行的这需要结合具体场景区别对待。另外还有一点需要澄清以上使用一致性的目的主要是针对聚合的修改。在一个事务中加载和创建多个聚合是没有问题的因为并不会导致并发冲突。
5. 聚合的设计
根据上面的阐述聚合不仅仅是简单的对象组合其主要的目的是用来封装业务和保证聚合内领域对象的数据一致性。
那聚合设计时要遵循怎样的原则呢
遵循领域不变性聚合内实现事务一致性聚合外实现最终一致性一个事物一次仅更新一个聚合。当业务用例要跨域多个聚合时使用领域事件进行事务拆分实现最终一致性。基于业务用例而非现实生活场景避免成为集合或容器对聚合的一大误解就是把聚合当作领域对象的集合或容器。当发现这个征兆时你要考虑你聚合是否需要改造。不仅仅是HAS-A关系聚合不是简单的包含关系要确定包含的领域对象是否为了满足某个行为或不变性。不要基于用户界面设计聚合聚合不应该根据UI界面的需求进行设计。而应该通过加载多个聚合数据映射到UI展示需要的视图模型中。创建具有唯一标识的聚合根聚合根作为聚合的网关通过聚合根完成聚合中领域对象的持久化和检索。优先使用值对象聚合根内的其他领域对象优先设计成值对象使用ID关联而非对象引用对象引用不仅会导致聚合边界的模糊而且会导致延迟加载的问题。通过唯一标识引用其他聚合聚合边界之外的对象不能持有聚合内部对象的引用聚合内部的领域对象可以持有其他聚合根的引用。避免在聚合内使用依赖注入对于依赖的对象我们应该在调用聚合方法之前查找获取并通过参数传递。可以在应用服务中通过依赖注入资源库或领域服务获取聚合依赖的对象然后传入聚合。使用小聚合通常较小的聚合使系统更快且更可靠因为更少的数据传输以及更少的并发冲突。大聚合会影响性能聚合的每一个成员都增加了从数据库加载和保存到数据库的数据量直接影响到性能。大聚合容易导致并发冲突大的聚合可能有多个职责意味着它涉及到多个业务用例。我们可以量化一个聚合涉及到的业务用例数数量越大设计的聚合边界越应该被质疑尝试将其细化拆解成小聚合。大聚合扩展性差聚合的设计要关注可扩展性。大聚合可能会跨越多个数据库表或文档这就在数据库级别形成了耦合它将阻碍你对数据子集进行数据迁移。同时在业务改变时大聚合不能很好的适应变化。
6.最后
聚合是一个复杂的概念其正确应用的关键是领域对象间关联关系的把握和领域不变性的理解。其实现的难点在于一致性的维护上聚合内实现事务一致性聚合外实现最终一致性。聚合的设计是一个持续性的活动不可能在初始阶段就能设计出完美的聚合我们应该根据对领域知识的深入和经验的积累持续改进聚合的设计。
相关文章
DDD理论学习系列1-- 通用语言DDD领域驱动之干货 一DDD理论学习系列2-- 领域DDD理论学习系列3-- 限界上下文DDD理论学习系列4-- 领域模型事件总线知多少2DDD理论学习系列5-- 统一建模语言DDD理论学习系列6-- 实体DDD理论学习系列7-- 值对象DDD理论学习系列8-- 应用服务领域服务DDD理论学习系列9-- 领域事件从事件和DDD入手来构建微服务DDD领域驱动之干货 一WeText项目一个基于.NET实现的DDD、CQRS与微服务架构的演示案例【DDD/CQRS/微服务架构案例】在Ubuntu 14.04.4 LTS中运行WeText项目的服务端基于.NET CORE微服务框架 -surging的介绍和简单示例 开源剥析surging的架构思想基于.NET CORE微服务框架 -谈谈surging的服务容错降级我眼中的ASP.NET Core之微服务.NET Core 事件总线,分布式事务解决方案CAP
原文地址http://www.cnblogs.com/sheng-jie/p/7158555.html .NET社区新闻深度好文微信中搜索dotNET跨平台或扫描二维码关注