当前位置: 首页 > news >正文

现在公司网站重要吗专门做岛屿的网站

现在公司网站重要吗,专门做岛屿的网站,dz论坛seo,如何建立自己生活网站DDD中的聚合模式是最难弄清楚的一种模式#xff0c;在如何确定聚合边界这个问题上#xff0c;更没有一个明确的指导原则#xff0c;这导致DDD的落地比较难。不过#xff0c;相信你读了这篇文章应该对聚合会有更深刻的理解。 本文分三部分来讲#xff1a; 1、什么是聚合在如何确定聚合边界这个问题上更没有一个明确的指导原则这导致DDD的落地比较难。不过相信你读了这篇文章应该对聚合会有更深刻的理解。 本文分三部分来讲 1、什么是聚合 2、聚合解决了什么问题 3、聚合的边界划分指导原则 1. 什么是聚合 首先我们来看下聚合模式的定义: 将实体和值对象划分为聚合并围绕着聚合定义边界。选择一个实体作为每个聚合的根并仅允许外部对象持有对聚合根的引用。作为一个整体来定义聚合的属性和不变量并把其执行责任赋予聚合根或指定的框架机制。 这是典型的“模式语言”说明了聚合是什么聚合根aggregation root是什么以及如何使用聚合。 但是模式语言的问题在于过度精炼对于还不熟悉这些模式的人根本不知所云。为了能深入理解聚合模式的本质我们还是要一步步回到聚合试图解决的问题上来。 2.聚合解决了什么问题 我们先从一个问题域开始拿大家都能理解的企业采购系统来举例 提交人通过采购系统提交一个采购申请采购申请中包含了本次要采购的若干办公用品称为采购项)和对应的数量主管对采购申请进行审批审批通过后生成订单发送到供应商出货 要设计这样的一个采购系统不同人有不同的方法。 2.1 面向数据库设计 我见过大部分人首先想到的是库表结构的设计也就是面向数据库编程。大部分人都能够设计出如下的几张表如下图所示 可能你会问面向数据库的设计有什么问题呢我一直都是这么做的啊你一直这么做并不代表你的方法就是最合理的。 为了能够保证业务规则的正确性和数据一致性在上面的采购系统中我们需要考虑如下几个问题 如果采购请求被删除则和该采购请求相关的采购项是不是都应该被删除呢如果你的主管正在对采购申请进行审批而你又同时在修改采购申请中的采购项那该如何进行并发处理呢如果设计不当要么你主管审批的就是过期的数据要么你更新采购项会失败。虽然上面的问题都有对应的技术解决办法但是过早地陷入到技术细节的讨论中会让我们错失和业务专家充分讨论的机会而很多业务隐含的概念是在和业务专家协作过程中显现的同时技术复杂性和业务复杂性混合在一起让我们顾此失彼。 总之在简单的场景下采用面向数据库的设计简单直接能快速实现需求。但是在较复杂的业务场景下如果一上来就在数据库这么低的层次上考虑问题我们会花大量的时间在表结构的设计上而没有重视对重要的业务规则的梳理。随着业务的快速发展由于我们最初设计考虑不当我们会疲于应付不断出现的新需求和bug我们会陷入沉重的泥潭最后系统只能推倒重来。 那我们有没有一种方法能够让我们聚焦于问题领域而不是过早地陷入到技术细节中呢答案就是面向对象设计 2.2 面向对象设计 面向对象设计有助于我们提高抽象的层级在面向对象的世界中我们看到的结构是这样的 面向对象的设计方法提高了抽象层级忽略一些不必要的技术细节例如不用再关心表的外键、表的关联关系等技术细节了让我们能够更加专注地聚焦到问题领域同时业务人员也能够看懂技术和业务专家也能够基于统一语言进行持续的交流协作。 但是业务规则如何保证在传统的面向对象的设计中并没有很好的方法能够对业务规则进行约束。例如 从业务规则上来看当采购申请审批通过了就不允许申请者再对采购申请中的采购项进行修改。但是在面向对象的设计中你没法阻止程序员写出如下的代码 PurchaseRequest purchaseRequest getPurchaseRequest(requestId); PurchaseItem item purchaseRequest.getItem(itemId); item.setQuantity(1000); savePurchaseItem(item);语句1取得了采购申请的实例语句2获取了该采购申请中的一个采购项语句34对采购项的数量进行修改并保存。如果该采购申请已经审批通过了那这种修改就违背了业务规则。 可能你会说在修改之前我先对purchaseRequest的状态进行校验如果状态是已审批通过就不允许修改。加上校验的代码如下 PurchaseRequest purchaseRequest getPurchaseRequest(requestId); PurchaseItem item purchaseRequest.getItem(itemId); if (purchaseRequest.status HAS_APPROVED) {throw new BizException(采购申请已审批通过不允许对采购进行修改) }item.setQuantity(1000); savePurchaseItem(item);但是PurchaseItem在任何地方都能够被提取出来并且PurchaseItem对象可以在方法间进行传递。 要满足上述的业务规则你需要在每个对PurchaseItem修改的地方加上上面这段校验代码。如果设计不当那这段校验逻辑就会散落在各个地方未来要修改这段校验逻辑你需要找出散落的每个地方进行修改这成本可想而知。 没有设计上的约束那要保证业务规则的正确性并不是一件很容易的事。 2.3 面向DDD的设计 让我们回到本质问题采购项脱离了采购申请有单独存在的价值吗 答案显然是没有什么卵用。既然采购项没有单独存在的价值那对采购项的修改本质上是不是对采购申请的修改 如果我们认同‘对采购项的修改就是对采购申请的修改’这个结论那我们就不应该将采购项和采购申请分开来看待而应该如下图所示 我们把“采购申请”和“采购项”看做是一个整体这个比对象更大粒度的整体就称为“聚合”。讲了这么多终于看到聚合两个字了 这个聚合内部的业务逻辑例如“采购申请审批通过后不得对采购项进行修改”应该内建于聚合内部。为了实现这一目标我们约定一切对采购项的操作增删改查)都是对采购请求对象的操作。 也就是说在代码中从来就不应该出现savePurchaseItem()这种方法应该用purchaseRequest.modifyPurchaseItem()和purchaseRequest.savePurchaseItem()方法代替。 现在对purchaseItem的访问必须通过purchaseRequest对象purchaseRequest对象作为访问聚合的入口称为“聚合根”又是一个重要的概念。由于聚合是一个整体对聚合的任何操作只能通过聚合根来进行从而业务规则在聚合内部得到了保证。 读到这里大家大致明白聚合是什么了吧。 聚合的本质就是建立了比对象粒度更大的边界聚合了那些紧密联系的对象形成了一个业务上的整体。使用聚合根作为对外交互的入口从而保证了多个互相关联的对象的一致性。 3.聚合的边界划分原则 虽然到目前我们大致理解了聚合模式的概念以及聚合模式解决的问题但聚合的边界又该如何划分呢可能有的人会问 既然采购项是采购申请这个聚合的一部分那产品是不是也是该聚合的一部分如果说是为了业务规则得到保证那审批人、提交人都放到采购申请这个聚合岂不是更好 哪些对象该属于为一个聚合哪些对象不属于一个聚合也就是聚合边界的划分问题有没有一个可指导的原则呢 当然有。聚合边界的划分可以参考如下几个指导原则 1、生命周期一致性原则 2、问题域一致性原则 3、场景一致性原则 4、聚合应尽可能地小 3.1 生命周期一致性原则 生命周期一致性是指聚合内部的对象应该和聚合根具有相同的生命周期聚合根消失则聚合内部的所有对象都应该一起消失。 例如在上面的例子中聚合根采购请求被删除那采购项也就没有存在的意义但是申请人、审批人、产品和采购申请却不存在该关系。 如果违反生命周期一致性原则会带来比较严重的后果。假如提交人也是采购申请这个聚合中的对象代码如下 public class PurchaseRequest {private SetPurchaseItem items;private User submitter;... }其中User对象的生命周期和PurchaseRequest对象的生命周期不一致。 那么当保存采购申请对象时也会保存User对象的信息代码如下 r purchaseRequestRepository.findOne(id); //...一些修改 purchaseRequestRepository.save(r);同时员工管理员也可以对同一个User对象进行修改代码如下 User user userRepo.findOne(r.getSubmitter().getId()); //...一些修改 userRepo.save(user);这将导致严重的后果对于User对象的修改不确定性 因此如果不确定是否应该将某个对象划入某个聚合你不妨问下 这个对象离开了这个聚合是不是还有存在的价值如果这个对象离开了这个聚合有单独存在的意义那就不应该就它划入这个聚合。 回到上面那个例子: Submitter/Approver 对应的 User 对象脱离了 PurchaseRequest仍然有单独存在的价值Product 对象脱离了 PurchaseRequest是可以单独存在的 所以以上两个对象都不属于采购申请这个聚合。 3.2 问题域一致性原则 上面的生命周期一致性只是指导原则之一有时如果只考虑生命周期一致性原则可能会引起问题。 让我们考虑一个在线论坛这样的场景 一个在线论坛用户可以对论坛上用户的文章发表评论。文章显然应该是一个聚合根。如果文章被删除那么用户的评论看起来也要同时消失。那么评论是否可以属于文章这个聚合 现在让我们来考虑评论是否还有其他用处。 例如用户可以对用户的文章发表评论同时也可以对该论坛的电子图书发表评论。如果只是因为文章和评论之间存在逻辑上的关联就让文章聚合持有评论对象那么显然就约束了评论的适用范围。所以我们得到了一个新的、凌驾于原则1之上的原则——不属于同一个问题域的对象不应该出现在同一个聚合中。 在上图中评论这聚合根可以持有其他聚合根的id(可评价对象id), 同时聚合之间的一致性通过最终一致性来保证文章删除发送领域事件通知删除对应的评论)。 3.3 场景一致性原则 通过上面两个原则我们基本能够划分清楚一个聚合的边界但是仍然会存在一些复杂的情况。这时我们可以根据第三个原则来判断场景一致性原则。 什么是场景一致性呢场景一致性就是场景操作频率的一致性。 在很多业务场景中我们会对领域对象进行查看、修改等各种操作。 经常被同时操作的对象应该属于同一个聚合而那些极少被同时关注的对象即使上面两个原则都满足也不应该划为一个聚合。 不在同一个场景下操作的对象放入同一个聚合意味着每次操作一个对象就需要把其他对象的所有信息抓取到这是非常没有意义的。这在日常开发中我也是深有体会。 从实现层次如果不紧密相关的对象出现在同一个聚合中会导致它们经常在不同的场景中被并发修改也增加了这些对象之间冲突的可能性。 所以大多数时候的操作场景都不一致的对象应该把它们分到不同的聚合中 3.4 聚合应尽可能地小 在划分聚合时除了应该满足上面三个指导原则外我们还应该让我们的聚合尽可能地小。 通常较小的聚合会让一个系统变得更快和更可靠因为会传输较小的数据并且引发并发冲突的概率会较小。而设计一个大的聚合会带来各种问题 大聚合会降低性能 聚合中的每个成员会增加数据的量当这些数据需要从数据库中进行加载的时候大聚合会增加额外的查询导致性能降低 大聚合更容易受到并发冲突的影响 大聚合可能包含了很多职责这意味着它要参与多个业务用例。随之而来的就是有很大可能出现多个用户对单个聚合进行变更的情况从而导致了严重的并发冲突影响了程序的可用性和用户体验 大聚合扩展性差 大聚合意味着与更多的模型产生依赖关系这会导致重构和扩展的难度增加。 原文链接 https://blog.csdn.net/u012179540/article/details/115152804
http://wiki.neutronadmin.com/news/370173/

相关文章:

  • 类似于wordpress的网站吗企业网站傻瓜搭建
  • 福田做网站哪家专业虚拟主机如何安装WordPress
  • 哪个网站学习做辅助长治做网站的公司
  • 网站建设的实习报告wordpress浮动音乐
  • 学校门户网站建设的好处个人做门户网站需要注册
  • 工信部网站备案名单做整站优化
  • 自建网站需要备案吗如何安装织梦做的网站
  • 服务器部署php网站怎么制作公司网页
  • 免费创建个人网站申请wordpress调用代码
  • 外贸营销网站制作购物网站怎么做项目简介
  • 网站建设内容模板深圳做小程序的公司排名
  • 宁波有没有开发网站的公司深圳关键词优化报价
  • h5快速建站国内十大管理咨询公司
  • 登录网站模板wordpress 单点登录
  • 网站源码上传到哪个文件夹重庆市城市建设档案馆网站
  • 上海网站建设流内蒙古建网站
  • 公司网站建设维护合同范本做网站的公司在哪
  • 徐家汇做网站对电子商务网站建设与维护的总结
  • 资兴市网站建设哪个好室内装饰设计说明
  • 黄埔区网站建设长沙seo平台
  • 计算机网站建设员网站建设客户定位
  • iis7.5 添加网站网站建设 金疙瘩计划
  • 滨州网站建设有实力张家口全景网站建设
  • 山如何搭建响应式网站投资网站建设公司多少钱
  • 如何创建旅游网站上海工程咨询行业协会
  • 用asp做网站系统步骤会议专属网站平台建设报价单
  • 手机做网站对比路由器做网站山西省大同市网站建设公司
  • 福田网站建设联系电话域名备案在哪里备案
  • 外国风格网站建设价格网站企业建设公司排名
  • 网站备案以后怎么做房产网站的建设