如何一步一步用DDD设计一个电商网站(十二)—— 提交并生成订单

news/2024/5/15 15:32:47/文章来源:https://blog.csdn.net/weixin_33751566/article/details/86232119

本系列所有文章

如何一步一步用DDD设计一个电商网站(一)—— 先理解核心概念

如何一步一步用DDD设计一个电商网站(二)—— 项目架构

如何一步一步用DDD设计一个电商网站(三)—— 初涉核心域

如何一步一步用DDD设计一个电商网站(四)—— 把商品卖给用户

如何一步一步用DDD设计一个电商网站(五)—— 停下脚步,重新出发

如何一步一步用DDD设计一个电商网站(六)—— 给购物车加点料,集成售价上下文

如何一步一步用DDD设计一个电商网站(七)—— 实现售价上下文

如何一步一步用DDD设计一个电商网站(八)—— 会员价的集成

如何一步一步用DDD设计一个电商网站(九)—— 小心陷入值对象持久化的坑

如何一步一步用DDD设计一个电商网站(十)—— 一个完整的购物车

如何一步一步用DDD设计一个电商网站(十一)—— 最后的准备

如何一步一步用DDD设计一个电商网站(十二)—— 提交并生成订单

如何一步一步用DDD设计一个电商网站(十三)—— 领域事件扩展

 

 

阅读目录

  • 前言
  • 解决数据一致性的方案
  • 回到DDD
  • 设计
  • 实现
  • 结语

 

一、前言

  之前的十一篇把用户购买商品并提交订单整个流程上的中间环节都过了一遍。现在来到了这最后一个环节,提交订单。单从业务上看,这个动作的背后包含了多个业务操作,根据用户填写的订单信息生成订单、扣除使用的余额和积分、使用选择的礼券等等。其中涉及到多个上下文的操作,包括新引入的订单上下文,那么如何同时与多个上下文进行数据的写入操作是本篇主要想讨论的问题。

 

二、解决数据一致性的方案

  分布式系统中的多个子系统之间的同时写入问题,也就是所谓的数据一致性问题。讲解决数据一致性方案的文章比较多,我就不赘述了,其中的根本是CAP理论,大家可自行百度/Google下。总结一下一般在分布式场景中无非就是两种方式来解决:2阶段提交的强一致性(选择CP)或者最终一致性(选择AP)。2阶段提交大家都懂,是性能杀手,阻塞式的操作会导致整个系统的瓶颈提早到来。最终一致性是非阻塞式的异步机制,通过消息体在多个系统内流转,并各自根据消息体来处理不同的业务,并且最终一致性有很多种形式来实现,这里暂不展开讨论。

 

三、回到DDD

  在DDD中实现最终一致性需要引入一个之前一直没提到的概念:领域事件。

  问1:什么是领域事件?

  答:领域事件是领域的一部分,表示领域中所发生的事情。

  问2:它存在的作用是?

  答:①作为实现最终一致性的载体

    ②解耦

    ③通过事件让不同的上下文分散处理下游业务,减少对数据的反向获取。处理单元更小化。  

    ④对开闭原则(OCP:Open-Closed Principle)最好体现。

  问3:那么我们如何运用到DDD中?

  答:①哪怕是同一个上下文中的不同聚合也需要通过领域事件来进行同步。

    ②把领域事件设计成聚合,但是其中的大部分代表事件发生与过去的部分属性应该为只读。设计为聚合拥有了唯一标识这样便于跟踪事件、持久化和跨限界上下文交互。

    ③使用发布 —— 订阅的方式来处理事件,降低耦合。

    ④有时,有必要使用领域服务来注册事件订阅方。这样的动机可能和让应用服务来注册订阅方一样,但是此时我们可能有特定于领域的原因。

    ⑤领域事件的一个经验法则是这样的:领域事件中所包含的信息应该满足80%的消费方,虽然对于很多消费方来说,这些信息是多余的。

 

四、设计

  根据上面的描述,设计了以下的几个对象进行实现领域事件的发布和订阅,如下图1:

                  【图1】

  DomainEventBus是一个单例。事件(继承自DomainEvent)的发布全部经由它来处理,分发失败的时候会抛出一个DistributeExceptionEvent的事件,由调用方决定后续的处理方式。另外事件订阅者(继承自DomainEventSubscriber)也通过DomainEventBus来注册订阅。类型依赖图如下图2:

                      【图2】

 

五、实现

  为了能够比较直观的表达当前这个提交订单业务操作的处理流程,我粗略画了个时序图,如下图3。

                          【图3】

  这里的事件发布是订单上下文内的一个组件,是一个进程内操作。另外事件具体发布的目的地由不同的订阅者控制,暂时就列出了2个。

  好了根据上面的时序图描述,下面贴出其中的核心代码:

  1.事件订阅

            var types = Assembly.Load("Mall.Domain.Order.DomainEventSubscribers").GetTypes().Where(ent => !ent.IsGenericType && ent.GetInterface(typeof(IDomainEventSubscriber).FullName) != null).ToList();foreach (var type in types){var subscriberInstance = Activator.CreateInstance(AppDomain.CurrentDomain, type.Assembly.FullName, type.FullName).Unwrap();var subscriber = (IDomainEventSubscriber)subscriberInstance;DomainEventBus.Instance().Subscribe(subscriber);}

  2.和2个对订单创建事件的订阅者

    public class OrderCreatedSubscriberPaymentContext : DomainEventSubscriber<OrderCreated>{public override void HandleEvent(OrderCreated domainEvent){//TODO anythingthrow new NotImplementedException();}}
    public class OrderCreatedSubscriberSellingPriceContext : DomainEventSubscriber<OrderCreated>{public override void HandleEvent(OrderCreated domainEvent){//TODO anythingthrow new System.NotImplementedException();}}

  3.事件发布

        public Result Create(OrderRequest orderRequest){if (!string.IsNullOrWhiteSpace(orderRequest.CouponId)){var couponResult = DomainRegistry.SellingPriceService().IsCouponCanUse(orderRequest.CouponId, orderRequest.OrderTime);if (!couponResult.IsSuccess)return Result.Fail(couponResult.Msg);}var orderId = DomainRegistry.OrderRepository().NextIdentity();var order = Domain.Order.Aggregate.Order.Create(orderId, orderRequest.UserId, orderRequest.Receiver,orderRequest.CountryId, orderRequest.CountryName, orderRequest.ProvinceId, orderRequest.ProvinceName,orderRequest.CityId, orderRequest.CityName, orderRequest.DistrictId, orderRequest.DistrictName,orderRequest.Address, orderRequest.Mobile, orderRequest.Phone, orderRequest.Email,orderRequest.PaymentMethodId, orderRequest.PaymentMethodName, orderRequest.ExpressId,orderRequest.ExpressName, orderRequest.Freight, orderRequest.CouponId, orderRequest.CouponName, orderRequest.CouponValue, orderRequest.OrderTime);foreach (var orderItemRequest in orderRequest.OrderItems){order.AddOrderItem(orderItemRequest.ProductId, orderItemRequest.Quantity, orderItemRequest.UnitPrice, orderItemRequest.JoinedMultiProductsPromotionId, orderItemRequest.ProductName);}DomainRegistry.OrderRepository().Save(order);DomainEventBus.Instance().Publish(new OrderCreated(order.ID, order.UserId, order.Receiver));return Result.Success();}

  注意其中标红的部分,暂时没有考虑出现异常的情况。另外这里的OrderCreated事件只是象征性的写一下,实际的事件需要哪些属性,只要贯彻好二八原则,设计一个满足80%场景下的直接可用,剩下的20%可以增加一些查询来满足实际业务需要。 

 

六、结语

  如果说领域对象、应用层、仓储层等这些概念还和传统的三层架构傻傻分不清楚的话。那么领域事件应该是整个DDD中最容易理解的一部分概念,因为这一部分是独立于传统的三层架构之外的完全不同的部分,也是整个DDD设计中低耦合的关键。本篇先进行了一个对领域事件最简单的实现,主要阐述了领域事件在整个项目设计过程中的作用和运用的方式。这是一个基础,在这个基础之上已经有很多成熟的解决方案可以让我们的系统做的更好。下篇会主要讲关于异常的处理(上文中标红的那部分),数据一致性的保证等更好的提高系统可用性的部分。谢谢各位看官。

 

 

本文完整的源码地址:https://github.com/ZacharyFan/DDDDemo/tree/Demo12。

 

作者:Zachary_Fan
出处:http://www.cnblogs.com/Zachary-Fan/p/DDD_12.html

 

 

▶关于作者:张帆(Zachary,个人微信号:Zachary-ZF)。坚持用心打磨每一篇高质量原创。欢迎扫描右侧的二维码~。

定期发表原创内容:架构设计丨分布式系统丨产品丨运营丨一些思考。

 

如果你是初级程序员,想提升但不知道如何下手。又或者做程序员多年,陷入了一些瓶颈想拓宽一下视野。欢迎关注我的公众号「跨界架构师」,回复「技术」,送你一份我长期收集和整理的思维导图。

如果你是运营,面对不断变化的市场束手无策。又或者想了解主流的运营策略,以丰富自己的“仓库”。欢迎关注我的公众号「跨界架构师」,回复「运营」,送你一份我长期收集和整理的思维导图。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_764262.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

合理设置应用程序池 保证网站合理运行

一般来说 小的企业网站 10个网站 对应1个程序池 大的网站 1对1 下面举个例子 然后 在IIS站点里面 把网站 分配给 这个应用 程序池 这样 这个网站 就会去使用 我们刚才建立的应用程序池了 放10个左右 如果有新的网站 就再建立一个 应用程序池 如果是大的网站 最好独…

网站中超链接方式直接添加QQ好友

使用情景&#xff1a; 在图中点击图片&#xff0c;会弹出添加qq好友的窗口进行好友添加。 链接如下&#xff1a; tencent://AddContact/?fromId45&fromSubId1&subcmdall&uin888888888 上面链接可以进行直接调用qq&#xff0c;进行添加好友。&#xff08;88888888…

网站设计稿

转载于:https://www.cnblogs.com/yuebing/p/6482835.html

分享100佳精美的作品集网站设计案例

一个精美的个人作品集网站是吸引更多客户的最好方式。如果你正在建设个人作品集网站或者想重新设计的话可以参考本文收集的这些示例&#xff0c;相信这些精美的网站作品会带给你灵感。同时&#xff0c;这些网站中汇集了丰富的设计作品、素材和教程&#xff0c;能为你的设计带来…

10个优秀HTML5网站案例赏析

近期随着Adobe弃Flash转投HTML5开始&#xff0c;HTML5又开始吸引着大众的目光。在几大巨头的推动之下&#xff0c;HTML5将成为下一代Web的标准。与现在使用的HTML标记语言相比&#xff0c;HTML5有更多的标签和属性&#xff0c;使用也更为灵活功能也更强大。现在已经有很多前沿的…

SHAREPOINT2010的网站品牌化(沙盒解决方案)

[转 http://www.cnblogs.com/love007/archive/2012/02/29/2373652.html] 概述Microsoft Visual Studio 2010 中的 SharePoint 开发工具提供了一种简单有效的方法&#xff0c;用来对使用沙盒解决方案将品牌应用到 Microsoft SharePoint 2010 网站所需的文件和代码进行打包和部署…

Jekyll – 基于纯文本的开源静态网站 博客系统

Jekyll 是一个开源的静态网站 & 博客生成工具&#xff0c;类似 WordPress。但是和 WordPress 又有很大的不同&#xff0c;原因是 Jekyll 只是一个生成静态网页的工具&#xff0c;不需要数据库支持。但是可以配合第三方服务&#xff0c;例如disqus。最关键的是 Jekyll 可以免…

Asp.net中使用资源文件实现网站多语言

首先需要新建一个ASP.NET Web Application.然后右键项目文件Add->Add ASP.NET Folder->App-GlobalResources. 新建好资源文件夹后&#xff0c;向文件夹中添加一个resx文件&#xff0c;我这里是添加一个LocalText.resx文件。 如上图所示&#xff0c;设置Name和Value的值。…

黄聪:路由器WIFI连接无法正常访问个别网站及发送图片

打开路由&#xff0c;路由默认MTU是1500&#xff0c;改成1472 就解决了 转载于:https://www.cnblogs.com/huangcong/p/6127762.html

网站优化的3个seo小技巧

网站运营的基础就是优化&#xff0c;对于很多人来讲&#xff0c;想要把网站做好&#xff0c;提升排名&#xff0c;无疑是一件比较苦恼的事。但是做网站优化&#xff0c;实际上也并没有想的那么复杂&#xff0c;有时候我们可以运用一些优化技巧&#xff0c;就可以把网站优化做好…

论坛 newreply.php,Discuz 2.5 留存网站日志源端口号的修改办法

loading...近日&#xff0c;很多站长收到了IDC发来的有关《公安机关要求网站做好日志系统源端口号留存的通知》&#xff0c;要求大致如下&#xff1a;为贯彻落实公安部和省公安厅关于加强互联网行业管理工作的要求&#xff0c;所有网站对相关日志系统要进行升级改造&#xff0c…

发布订阅服务器占用空间吗,网站使用网站空间还是云服务器?如何选择?

原标题&#xff1a;网站使用网站空间还是云服务器&#xff1f;如何选择&#xff1f;网站空间已经有了一段时间的历史&#xff0c;随着其技术的不断成熟&#xff0c;以及其低廉的价格&#xff0c;成为众多站长的首选对象。但近两年云计算的出现&#xff0c;衍生出云服务器这个产…

mvc开发网站打开慢总结

开始学习mvc开发网站的时候&#xff0c;看了传智博客的视频教程&#xff0c;其中学习了一个和牛逼的框架&#xff0c;开始激动的深入学习&#xff0c;学完后却发现其实那套框架太重并不适合一些中小型的网站开发&#xff0c;并且也使用导航属性关联外键&#xff0c;导致打开网站…

python爬虫加密空间_python爬虫反反爬,你几乎可以横扫大部分 css 字体加密的网站...

接下来就是学习 python 的正确姿势有人说了不就是把字体通过 unicode 编码吗&#xff1f;那就简单了啊把每个字的编码找到然后使用字典把编码和对应的字对应起来抓取分析的时候直接替换不就得了有道理是有道理但是如果我每次返回给你的编码都不一样呢&#xff1f;你说死不死好了…

网站性能优化—CRP

为了把HTML、CSS和JavaScript转化成活灵活现、绚丽多彩的网页&#xff0c;浏览器需要处理一系列的中间过程&#xff0c;优化性能其实就是了解这个过程中发生了什么-即CRP(Critical Rendering Path&#xff0c;关键渲染路径)。首先&#xff0c;我们从头开始快速学习一下浏览器是…

云服务器 ECS 建站教程:SVN的搭建和使用

SVN的搭建和使用简介 Subversion(SVN) 是一个开源的版本控制系統, 也就是说 Subversion 管理着随时间改变的数据。 这些数据放置在一个中央资料档案库(repository) 中。 这个档案库很像一个普通的文件服务器, 不过它会记住每一次文件的变动。 这样你就可以把档案恢复到旧的版本…

大型网站的 HTTPS 实践(一): HTTPS 协议和原理

大型网站的 HTTPS 实践&#xff08;一&#xff09;&#xff1a; HTTPS 协议和原理 1 前言 百度已经于近日上线了全站 HTTPS 的安全搜索&#xff0c;默认会将 HTTP 请求跳转成 HTTPS。本文重点介绍 HTTPS 协议, 并简单介绍部署全站 HTTPS 的意义。 2 HTTPS 协议概述 HTTPS 可以认…

自适应网站设计对百度友好的关键:添加applicable-device标签(转)

现在很多网站都使用了自适应网页设计&#xff08;Response-Web-Design&#xff09;&#xff0c;以满足庞大的移动端用户群的需要。但是在技术上设计了自适应的网页之后&#xff0c;出于SEO的考虑&#xff0c;你还要照顾到如何对百度更友好&#xff0c;即告诉百度“我是自适应页…

Ubuntu 网站服务器环境搭建

如果想用Ubuntu作为网站的服务器&#xff0c;一些基本的服务是必备的。本文对环境的搭建做一个简单的整理。 Appach Apache是世界使用排名第一的Web服务器软件。它可以运行在几乎所有广泛使用的计算机平台上&#xff0c;由于其跨平台和安全性被广泛使用&#xff0c;是最流行的W…

一个非常不错的背景纹理图的网站

今天闲逛的时候发现的&#xff1a;http://subtlepatterns.com/。里面的纹理图质量都非常高&#xff0c;并且预览也非常方便&#xff0c;无需注册即可下载&#xff0c;这里强烈推荐下。