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

news/2024/5/16 8:14:43/文章来源:https://blog.csdn.net/weixin_30314813/article/details/94945174

 

 

本系列所有文章

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

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

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

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

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

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

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

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

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

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

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

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

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

 

阅读目录

  • 前言
  • 如何在一个项目中实现多个上下文的业务
  • 售价上下文与购买上下文的集成
  • 结语

 

一、前言

  前几篇已经实现了一个最简单的购买过程,这次开始往这个过程中增加一些东西。比如促销、会员价等,在我们的第一篇文章(如何一步一步用DDD设计一个电商网站(一)—— 先理解核心概念)中规划的上下文映射图可以看到,这些都属于一个独立的上下文(售价上下文)。

 

二、如何在一个项目中实现多个上下文的业务

  一般情况下,为了更好的分而治之,把不同的上下文作为单独的service,然后通过rpc框架(如WCF)来对其访问是个比较常见的做法。但是在一些小型团队中,虽然划分出了不同上下文,但是我们的开发团队还是同一个。在这种情况下,我个人一般的做法是直接在同一个解决方案中建立不同的项目去做,但是这里需要在解决方案中明确的划分好不同上下文之间的边界,通过代码审核等手段管理好这个边界不被破坏。

  

                      【图1】

  增加的几个项目如图1所示。

  

三、售价上下文与购买上下文的集成

  根据我们第一篇如何一步一步用DDD设计一个电商网站(一)—— 先理解核心概念所定义的上下文映射图和9种集成模式可以看出,这2个上下文在同一个子域中,并且在我们实际业务场景中,这2者又是相辅相成,所以售价上下文和购买上下文是一种合作关系。确立这个关系之后,那么这个促销的计算逻辑到底是放到哪个上下文种做更合适呢?我们先整理一下几种可能的方式:

  1.购买上下文把购物车中的商品信息丢给售价上下文 --> 售价上下文进行计算 --> 把结果再返回给购买上下文。

  2.购买上下文从销价上下文获取相关会员价和促销信息 --> 再本地的购物车对象基础上进行运算,并直接可运用结果。

  3.再抽出一个专门的计算服务(隶属于售价上下文),去做这个计算的动作。购买上下文把购物车中的商品信息丢给计算服务 --> 计算上下文从销价上下文获取到相关会员价和促销信息 --> 计算 --> 返回结果给购买上下文

  我相信1和2是比较主流的2个方式。但是方式2是把售价上下文仅作为一种数据的提供方,这就把合作关系变成了一个上下游的关系,并且这种方式使得促销规则和购物车强耦合到了一起,不利于促销规则的变化。在这里售价上下文只起了一个简单的数据维护作用,无法完全控制“售价”的定义,没有很好的做到职责分离。方式1和3对购买上下文来说其实是没有区别的,只是方式3让整个数据交互的链路多了一层,会产生额外的开销,好处是服务的粒度更细了,需要结合实际情况权衡一下得失。这里我选择1方式来实现,因为我们在项目初期,还是尽可能的减少非业务目的的拆分导致的额外成本。

  好了,确定了集成方式之后,先把2个上下文之间用于数据交互的DTO模型定一下,如下图2(售价上下文的DTO模型),图3(购买上下文中与前者对应的值对象)。

 

                     【图2】

                  【图3】

  另外在图3中可以发现增加了一个ISellingPriceService,抽象了与售价上下文的交互。那么我们在Mall.Infrastructure.Translators项目中增加对这个上下文的防腐层处理,老3样SellingPriceAdapter(发起上下文数据请求的适配器)、SellingPriceService(实现ISellingPriceService)、SellingPriceTranslator(把远程数据对象转换成本地的值对象),代码很简单大家可以在源码中查看。需要注意的是,这里的Mall.Infrastructure.Translators项目仅增加了对Mall.Application.SellingPrice项目的引用,类似于把它当作一个远程资源来对待(按上面所说,如果实际由不同的团队负责可以物理上的分离到2个解决方案中)。

  最后创建一个CartService,里面的GetCart()方法——获取购物车信息,来作为调用发起方。这其中的实现使用了最简单的方式,本地不做任何的数据冗余,代码如下:

    public class CartService{private readonly static ConfirmUserCartExistedDomainService _confirmUserCartExistedDomainService = new ConfirmUserCartExistedDomainService();public CartDTO GetCart(string userId){var cart = _confirmUserCartExistedDomainService.GetUserCart(userId);if (cart.IsEmpty()){return null;}var sellingPriceCart = DomainRegistry.SellingPriceService().Calculate(cart);return ConvertToCart(cart, sellingPriceCart);}private CartDTO ConvertToCart(Cart cart, SellingPriceCart sellingPriceCart){return new CartDTO{CartItemGroups = sellingPriceCart.CalculatedFullGroups.Select(ent => new CartItemGroupDTO{CartItems = ent.CalculatedCartItems.Select(e => ConvertToCartItem(e, cart.GetCartItem(e.ProductId))).ToArray(),ReducePrice = ent.ReducePrice}).ToArray(),CartItems = sellingPriceCart.CalculatedCartItems.Select(ent => ConvertToCartItem(ent, cart.GetCartItem(ent.ProductId))).ToArray()};}private CartItemDTO ConvertToCartItem(SellingPriceCartItem sellingPriceCartItem, CartItem cartItem){var product = DomainRegistry.ProductService().GetProduct(cartItem.ProductId);return new CartItemDTO{ProductId = cartItem.ProductId,ProductName = product == null ? "商品已失效" : product.SaleName,ReducePrice = sellingPriceCartItem.ReducePrice,SalePrice = cartItem.Price};}}    

 

 四、结语

  这次有个全局改动这里提一下,我在本次编码中把之前所有的Guid标识全部改为了string类型,弱化了对唯一标识的数据类型约束,提高可扩展性(如自增字段、其它自定义的唯一标识等),另外还把购物项中的Price改为了UnitPrice,让语义更加清晰。本篇内容比较粗,欢迎大家探讨。

 

 

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

 

 

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

 

 

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

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

 

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

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

转载于:https://www.cnblogs.com/Zachary-Fan/p/DDD_6.html

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

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

相关文章

码教授告诉你SEO如何维护友情链接

友情链接是网站的一种营销策略,是指互相在自己的网站上放对方网站的链接,通过和权重相当的网站交换友情链接来提升自己网站的权重,也能为网站带来意向客户。和其他网站交换友情链接是免费的,但是交换过程中需要注意几个问题。一:最…

Python爬虫获取招聘网站职位信息

Python爬虫获取招聘网站职位信息 摘要 本文介绍使用Python编写爬虫,获取招聘网站中感兴趣的职位信息。 好的开始,成功一半。另一半呢?知己知彼,百战百胜。 0. 环境 0.1 Python解释器安装 推荐使用Anaconda发行版,其包含…

Redis简单案例(二) 网站最近的访问用户

Redis简单案例(二) 网站最近的访问用户 原文:Redis简单案例(二) 网站最近的访问用户我们有时会在网站中看到最后的访问用户、最近的活跃用户等等诸如此类的一些信息。本文就以最后的访问用户为例, 用Redis来实现这个小功能。在这之前,我们可以先简单了解…

NW.js将网站打包成桌面应用

需求:已有一个网站,因为浏览器兼容性等问题,想自己封装一个浏览器,打开时固定打开这个网站,通过这样的封装,将网站变成桌面应用程序。 1. 下载并安装NW.js的最新稳定版本(NW.js) 2. …

phpcms网站漏洞修复 远程代码写入缓存漏洞利用

SINE安全公司在对phpcms2008网站代码进行安全检测与审计的时候发现该phpcms存在远程代码写入缓存文件的一个SQL注入漏洞,该phpcms漏洞危害较大,可以导致网站被黑,以及服务器遭受黑客的攻击,关于这次发现的phpcms漏洞细节以及如何利…

python 网站的结构

用python怎么做一个网站。 维基百科对网站有如下描述: 网站(英文:Website)是指在互联网上,根据一定的规则,使用HTML等工具制作的用于展示特定内容的相关网页的集合。简单地说,网站是一种通信工具…

ASP.NET MVC 实现页落网资源分享网站+充值管理+后台管理(14)之会员中心管理

源码下载地址:http://www.yealuo.com/Sccnn/Detail?KeyValuec891ffae-7441-4afb-9a75-c5fe000e3d1c 会员中心,主要包含了会员的基本信息维护、充值管理,以及下载充值的日志管理和收藏等功能 首先我们需要在MemberCenterModule区域下的Contro…

中国农产品信息网站scrapy-redis分布式爬取数据

---恢复内容开始--- 基于scrapy_redis和mongodb的分布式爬虫 项目需求: 1:自动抓取每一个农产品的详细数据 2:对抓取的数据进行存储 第一步: 创建scrapy项目 创建爬虫文件 在items.py里面定义我们要爬取的数据 # -*- coding: utf-…

怎么让你的网站快如飞?

服务器、VPS、空间的介绍 服务器是真实存在的物理设备.无论是性能还是安全方面都是最强大的.VPS是虚拟服务器的意思.它的功能与服务器一模一样.但不同的是它是虚拟的.在同等配置的情况下.性能不如服务器.云主机则是VPS的升级版.相对VPS来讲更稳定.更安全一些.空间和虚拟主机是同…

keepalived + lvs 网站高可用集群

一 ,四台服务器 master 端 : 192.168.206.3 backup 端: 192.168.206.4 REserver1 端 : 192.168.206.5 REserver2 端: 192.168.206.6 二、 开始部署 1> 配置 REserver1 端 REserver2 端 ( 在回环地址配…

部署网站

1,下载tomcat 2 网站内容copy到tomcat classes 文件为编译后代码3将webapp copy 到 C:\apache-tomcat-7.0.85\webapps 修改 webapp 为easy即可 访问地址为 http://10.0.0.96:8080/easy/index.jsp 3 tomcat 修改如果出现有参数的接口请求不到The valid characters a…

大型网站系统架构演化之路

前言 一个成熟的大型网站(如淘宝、天猫、腾讯等)的系统架构并不是一开始设计时就具备完整的高性能、高可用、高伸缩等特性的,它是随着用户量的增加,业务功能的扩展逐渐演变完善的,在这个过程中,开发模式、技…

谈谈个人网站的建立(一)——建站历史和技术架构

首先,帮忙点击一下我的网站http://www.wenzhihuai.com/。谢谢啊,如果可以,GitHub上麻烦给个star,以后面试能讲讲这个项目,GitHub地址https://github.com/Zephery/newblog 大学的时候萌生的一个想法,就是建立…

MacOS网页自动化教程(下)- PySeTest网站自动登录到下单测试手脚架#Python3 + Selenium3+ HTMLTestRunner#工欲善其事

PySeTest网站自动登录到下单测试手脚架#Python3 Selenium3 HTMLTestRunner系统说明如何使用功能说明实现步骤测试路径测试脚本代码实现常用方法封装Selenium基础用法Selenium 中文文档Selenium3 定位方法Selenium的等待自动生成Html测试报告HTMLTestRunner 兼容Python3如何使用…

大型网站架构改进历程:存储的瓶颈(四)

摘要:什么是大型网站,从网站的技术角度考虑这个问题人们很容易犯一个毛病就是认为网站的访问量是衡量的指标,懂点行的人也许会认为是网站在单位时间里的并发量的大小来作为指标,如果按这些标准那么像hao123网站就是了。 本文转自博…

律师所网站建设及律师事务所网站模板整理

律师网站建设的内部系统可以分为很多,根据栏目页的设定可以有不同的系统,而且随着时代的发展以及互联网技术的不断更新,各方面系统管理也在升级,网站建设者或是管理者需要不断的对网站进行优化,使得符合时代发展的要求…

做网站用企业网站模板好不好

现在很过公司企业做网站都一般有两种途径,一种找人量身定制,一种选择现成的企业网站模板,目前来说,这两种网站建设方式价格差异也不大,那么到底是定制好?还是企业网站模板好呢? 其实这个问题没有…

响应式网站建设的优缺点

首先要明白响应式网站概念,响应式网站是国外最先流行的一种网站布局理念,其理念是:集中创建页面的图片排版大小,可以智能地根据用户行为以及使用的设备环境进行相对应的布局,说简单点就是可以在pc和手机及各种浏览设备…

网站建设需要注意的几个重要因素

在互联网发达的时代,网站已经是生活当中必不可少的一个事物了,许许多多的企业都熟悉了网站建设的流程,企业可以通过网站可以自由的发布信息、更新产品、还能够为客户提供一些在线的服务等。成功的网站建设能为企业带来一定的业务和收益&#…

网站建设方案

一、网站目标 网络凭借其卓越的互动性与便捷的交流手段正成为最有发展潜力与前途的新兴媒体,成为众企业倍为关注的宣传热点。许多行业的知名企业已经通过网站建设来为自己的企业带来显著的宣传效果。企业网站为对外宣传、服务和交流的载体,来配合企业的迅…