领域驱动设计(DDD,Domain-Driven Design)

news2024/10/1 3:36:41

领域驱动设计

  • 前言
  • 正文
  • 领域驱动设计
    • 基本概念
    • 什么是领域模型?
    • 什么是领域服务(Domain Service)?
    • 什么是领域事件?
  • 秒杀项目中的领域分析
    • 一、秒杀活动领域设计
      • 秒杀活动
      • 领域模型
      • 领域服务
      • 领域事件
    • 二、秒杀品领域设计
      • 领域模型
      • 领域服务
      • 领域事件
    • 三、订单领域设计
      • 领域模型
      • 领域服务
      • 领域事件
  • 总结
    • 参考链接


前言

大家好,我是练习两年半的Java练习生,今天我们来讲一讲关于架构设计中的一种模式,领域驱动设计,也称DDD,Domain-Driven Design。还有介绍一下秒杀项目中领域模型的一些设计。


正文

领域驱动设计

基本概念

领域驱动设计里面包含的概念有:

  1. 领域:指特定业务领域,如银行、电商、医疗等。领域是开发的核心焦点,领域驱动设计通过深入理解和建模领域,将业务逻辑准确地映射到软件系统中。
  2. 领域模型:领域模型是对特定领域的抽象和建模,用于描述和表示领域中的实体、属性、关系和行为。领域模型是领域驱动设计的核心工具,它帮助开发团队更好地理解和设计软件系统,以满足业务需求。
  3. 实体:领域模型中的实体是领域中的具体对象具有唯一的标识和属性。实体可以包含业务逻辑和行为,与其他实体之间可以有关联和交互。
  4. 值对象:值对象是没有唯一标识的对象,它的相等性是通过值的相等性来判断的,而不是通过标识。值对象通常用于表示领域中的一些属性或组合属性,如日期、地址等。
  5. 聚合:聚合是一组相关实体和值对象的集合,它们在领域中具有内聚性,可以作为一个整体进行管理和操作。聚合根是聚合中的一个实体,负责协调聚合内的对象之间的交互。
  6. 领域服务:领域服务是一些无状态的操作或行为,用于处理领域中的复杂业务逻辑或跨多个实体的操作。领域服务可以与实体和值对象进行交互,但不属于它们的一部分。
  7. 领域事件:领域事件是领域中发生的重要事实或状态变化的表示,它可以被其他领域对象订阅和响应,以触发相应的行为或处理。

下面是一些形象的比喻,可以帮助你更好地理解领域驱动设计中的几个概念:

  1. 领域:将领域比喻为一个大象,象征着特定的业务领域。领域驱动设计就是要深入了解这只大象,了解它的特点、行为和需求。
  2. 领域模型:将领域模型比喻为一张地图,它描述了领域中的实体、属性、关系和行为。地图可以帮助我们更好地理解和导航领域,确保软件系统与领域的契合度。
  3. 实体:将实体比喻为人类,每个人都有自己的唯一身份和特定属性。实体可以是领域中的具体对象,如客户、订单等,它们有自己的行为和关系。
  4. 值对象:将值对象比喻为装饰品,它们没有唯一标识,但可以通过它们的值来识别。值对象通常用于表示领域中的一些属性,如电话号码、日期等。
  5. 聚合:将聚合比喻为一个家庭,家庭成员之间有关系和交互。聚合根就像家庭的父母,负责协调家庭内的事务,并保证家庭的完整性和一致性。
  6. 领域服务:将领域服务比喻为一个专业的服务提供者,它可以处理领域中的复杂业务逻辑或跨多个实体的操作,类似于一个医生或律师。
  7. 领域事件:将领域事件比喻为一场重要的演出,演出结束后会触发观众的反应。领域事件可以被其他领域对象订阅和响应,以触发相应的行为或处理。

什么是领域模型?

以一种领域专家、设计人员、开发人员都能理解的通用语言作为相互交流的工具,在交流的过程中发现领域概念,然后将这些概念设计成一个领域模型

领域模型的特点:

  1. 领域模型是对具有某个边界的领域的一个抽象,反映了领域内用户业务需求的本质。
  2. 领域模型只反映业务,与技术实现无关
  3. 领域模型能让领域专家、设计人员、开发人员之间的交流变得方便。

领域建模时思考问题的角度:
《老子》讲过:有之以为利,无之以为用。
有之利,这里指建立领域模型;无之用,即包容用户需求。

  1. 领域模型设计的时候,不能以客户为中心作为出发点去思考问题,不能老是想着用户会对系统做什么。而是应该从一个客观的角度,根据用户需求挖掘出领域内相关的事务,思考这些事务的本质关联及变化规律。
  2. 领域模型是排除了人之外的客观世界模型,但领域模型包含人所扮演参与者角色,但是一般不要让参与者角色在领域模型中占据主要位置。如果以人所扮演的参与者角色在领域模型中占据主要位置,那么各个系统的领域模型将变得没有差别,因为软件系统就是一个人机交互的系统,都是以人为主的活动记录或跟踪;比如:论坛中如果以人为主导,那么领域模型就是:人发帖,人回帖,人结贴,等等;

什么是领域服务(Domain Service)?

领域中的一些概念不太适合建模为对象,即归类到实体对象或值对象,因为它们本质上就是一些操作,一些动作,而不是事物。这些操作或动作往往会涉及到多个领域对象,并且需要协调这些领域对象共同完成这个操作或动作。如果强行将这些操作职责分配给任何一个对象,则被分配的对象就是承担一些不该承担的职责,从而会导致对象的职责不明确很混乱

但是基于类的面向对象语言规定任何属性或行为都必须放在对象里面。所以我们需要寻找一种新的模式来表示这种跨多个对象的操作,DDD认为服务是一个很自然的范式用来对应这种跨多个对象的操作,所以就有了领域服务这个模式。
和领域对象不同,领域服务是以动词开头来命名的,比如资金转帐服务可以命名为MoneyTransferService。当然,你也可以把服务理解为一个对象,但这和一般意义上的对象有些区别。因为一般的领域对象都是有状态和行为的,而领域服务没有状态只有行为。

什么是领域事件?

领域事件是领域驱动设计中的一个概念,它表示领域中发生的重要事实或状态变化的表示。领域事件可以被其他领域对象订阅和响应,以触发相应的行为或处理。
在实际项目中,领域事件可以用于解耦领域对象之间的依赖关系,以及实现领域中的异步通信和业务流程的协调。通过引入领域事件,可以实现更灵活、可扩展和松耦合的系统设计。
举个例子,假设有一个电商系统,其中包含商品、订单和库存等领域对象。当用户下单购买商品时,可能会触发以下领域事件:

  1. 订单创建事件:表示一个新订单已被创建,包含订单的相关信息,如订单ID、用户ID、商品ID、数量等。其他领域对象(如库存管理)可以订阅这个事件,在接收到订单创建事件后,更新库存信息。
  2. 订单支付事件:表示一个订单已被成功支付,包含订单的支付状态和支付金额等信息。其他领域对象(如财务管理)可以订阅这个事件,在接收到订单支付事件后,更新财务信息。
  3. 订单取消事件:表示一个订单被取消,包含订单的取消原因和相关信息。其他领域对象(如库存管理)可以订阅这个事件,在接收到订单取消事件后,释放被占用的库存。

通过使用领域事件,订单、库存和财务等领域对象之间可以解耦它们不需要直接依赖对方的状态变化。当一个领域对象发生状态变化时,它只需要发布相应的领域事件,其他对象可以根据自身的业务逻辑进行相应的处理。
这样的设计可以提高系统的灵活性和可扩展性,因为每个领域对象只需要关注自己感兴趣的领域事件,而不需要直接依赖其他对象的状态变化。同时,领域事件也可以用于实现业务流程的协调和跨领域的通信。

秒杀项目中的领域分析

在这里插入图片描述

秒杀系统包含了多个领域,包括核心子域支撑域通用子域等。比如,秒杀系统中的活动域、秒杀品域等属于核心子域,是我们需要重点设计并亲自实现的
而账号子域、交易结算子域等则属于支撑子域,它们具有复用属性,在使用上并不局限于秒杀系统,可以和其他团队和业务共享,这部分可以和其他团队合作完成;最后的风控、缓存、限流等技术型的通用子域则可以通过采用开源产品或购买等引入,不需要我们自己开发。
主要涉及三个领域的设计

  • 秒杀活动领域设计
  • 秒杀品领域设计
  • 订单领域设计

一、秒杀活动领域设计

秒杀活动

秒杀活动是秒杀品的载体,一个秒杀活动可以包含多个秒杀品,并且多个秒杀活动可以同时存在。

领域模型

  • 活动名称:通用名称:activityName. 比如“圣诞节限时秒杀”;
  • 活动开始时间和结束时间:通用名称:startTime与endTime. 在活动期间内,用户才可以进行秒杀,用户下单时将进行活动时间校验;
  • 活动状态:通用名称:status. 分为发布、上线和下线等。只有处于上线状态的活动才对C端用户透出,也只有上线状态的活动才能进行秒杀下单;
  • 活动描述:通用名称:activityDesc. 可选,可为活动添加丰富的图文描述。

领域服务

  • 发布秒杀活动:当运营侧需要新的秒杀活动时,可以发布新的秒杀活动。秒杀活动发布后,将不对C端用户透出;
  • 上线活动:当运营侧已确认活动可以上线时,可以对活动执行上线操作。活动上线后,将对C端透出;
  • 下线活动:当活动不需要继续进行时,可以对活动执行下线操作。活动下线后,C端将不可见,同时将不再接收新的秒杀订单;
  • 秒杀活动查询和获取:运营侧和C端用户侧均可以获取秒杀活动集合。不同的是,用户侧仅能看见已上线的活动;
  • 秒杀活动下单条件检查:当用户执行秒杀下单时,秒杀活动可以根据此前配置的规则执行下单前置校验,已确认当前活动是否允许下单。

领域事件

  • 秒杀活动上线:当秒杀活动被执行上线操作时,将发出对应的上线事件,以通知相关订阅者处理;
  • 秒杀活动下线:当秒杀活动被执行下线操作时,将发出对应的下线事件,以通知相关订阅者处理。

二、秒杀品领域设计

秒杀品:可上架进行售卖和预定的商品或其他物品。

领域模型

  • 所属活动:通用名称:activityId. 秒杀品不可以独立存在,需要关联到秒杀活动;
  • 秒杀品标题:通用名称:itemTitle. 秒杀品的主标题;
  • 秒杀品副标题:通用名称:itemSubTitle. 可选,可用于对主标题的补充;
  • 初始库存:通用名称:initialStock. 秒杀品的原始库存,该值在秒杀活动期间不会发生变化;
  • 可用库存:通用名称:availableStock. 秒杀品当前可用库存,该值在初始时与”初始库存“的数值一致,库存扣减将发生该值上。因此,该值会随着用户下单二不断变化,并且是高并发的主要发生字段;
  • 原价:通用名称:originalPrice. 秒杀品在其他渠道的售卖价格,该值在活动期间不会发生变化,仅用于信息展示;
  • 秒杀价:通用名称:flashPrice. 秒杀品的秒杀价格,该值与”原价“可能不同,并参与到价格计算中;
  • 秒杀开始和结束时间:通用名称:startTime与endTime. 当系统时间出于startTime和endTime之间时,秒杀品出于活动中状态,可进行秒杀下单。超过该时间范围后,将不再接收用户下单;
  • 秒杀品状态:通用名称:status. 当前秒杀品的状态,存在发布、上线和下线等不同状态,仅处于”上线“状态的秒杀品才会对用户侧透出并接收下单。

领域服务

  • 发布秒杀品:当需要发布新的秒杀品,可以执行秒杀品发布操作;
  • 上线秒杀品:当确认秒杀品可以上线时,可对其执行上线操作,并在上线后对用户侧透出;
  • 下线秒杀品:当秒杀品不再需要继续上线时,可以对其执行下线操作;
  • 获取秒杀品及列表:对运营侧和用户侧提供秒杀品获取能力,用户侧仅能获取已上线的秒杀品和秒杀活动;
  • 库存扣减:当用户执行下单订单操作时,将进行库存扣减,库存扣减失败时将执行事务回滚;
  • 库存恢复:当用户执行取消订单等相关操作时,将进行库存恢复,只有库存恢复成功时,其他操作才能认定成功或继续操作,否则将执行事务回滚;
  • 秒杀品下单条件检查:当用户执行秒杀下单时,秒杀品可以根据此前配置的规则执行下单前置校验,已确认当前秒杀品是否允许下单。比如,业务规定同一用户仅能下单一次,那么当用户再次下单时即可拒绝;

领域事件

  • 上线秒杀品:当秒杀品被执行上线操作时,将发出对应的上线事件,以通知相关订阅者处理;
  • 下线秒杀品:当秒杀品被执行下线操作时,将发出对应的下线事件,以通知相关订阅者处理。

三、订单领域设计

秒杀订单:秒杀业务中由系统向用户提供的产品确认凭据。

在这里插入图片描述

领域模型

  • 订单ID:通用名称orderId. 订单ID由系统根据业务规则生成,不推荐使用自增ID,极易造成数据安全问题。FlashSale中提供了默认的雪花算法生成规则;
  • 秒杀品ID:通用名称itemId. 当前订单对应的秒杀品ID.FalshSale现有的设计仅支持单品下单,如果要支持多品下单,可以通过创建主子订单的方式实现;
  • 秒杀品标题:通用名称itemTitle. 秒杀品的标题可能会经常变动,因此在下单时冗余了一份秒杀品的标题;
  • 秒杀价:通用名称flashPrice. 下单时的秒杀价;
  • 活动ID:通过名称activityId. 下单时的活动ID,虽然通过itemId也能查到,但itemId对应的活动可能存在变化;
  • 秒杀品数量:通用名称quantity. 下单时的秒杀品数量;
  • 总金额:通用名称totalAmount. 由秒杀价* 数量得到的订单总金额,在实际应用中,总金额的计算可能需要涉及优惠券和其他折扣等;
  • 订单状态:通用名称status. 订单的状态,包括创建、取消等;
  • 订单创建时间:通用名称createTime.

领域服务

  • 下单:订单域的核心服务;
  • 根据用户获取订单:当前用户可以获取个人所创建过的订单;
  • 根据ID获取订单详情:当前用户可以通过订单ID查看订单详情;
  • 根据ID取消订单:当用户不再需要订单时,可以根据ID执行取消操作。当然,是否能取消成功,要看具体的规则。

领域事件

  1. 下单
  • 下单:当用户成功下单后,将发出对应的领域事件,以通知相关订阅者处理。
  1. 取消订单
    取消订单是下单的逆向操作。因此,下单时所发生的数据变更,在订单取消时需要恢复,包括订单数据、库存数据和库存缓存数据。

这部分是我们后面需要关注的重点,包括订单的库存处理、落库处理、预扣缓存、缓存方案等。


总结

好啦,以上就是我们今天要介绍的全部内容,希望能帮助你

如果大家还有什么问题,欢迎私信或者在评论区提出来,让我们一起学习进步!!!
在这里插入图片描述


参考链接

https://zhuanlan.zhihu.com/p/361427612
https://juejin.cn/book/7008372989179723787/section/7020612512164888613

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

开源自动化测试框架介绍

开源自动化测试框架介绍 一、Junit(白盒测试、API自动化、UI自动化)【官网】【简介】【使用场景】 二、Selenium(Web自动化、爬虫)【官网】【简介】【使用场景】 三、TestNG(白盒测试、API自动化、UI自动化&#xff09…

Linux文件系统架构和共享文件方法

我是荔园微风,作为一名在IT界整整25年的老兵,今天来聊聊 Linux文件系统架构和共享文件方法。 在Linux环境中使用文件和目录是工作中不可回避的环节。当然,在我的博客里成立windows程序员看linux这个专题,主要还是因为微软也发布了…

LwIP系列(4):ARP协详解

前言 对于应用程序而言,我们与其他设备、服务通信,主要通过域名、IP进行通信,而以太网底层驱动,最终是通过MAC地址来表示设备的唯一标识,即IP是逻辑地址,并不是物理地址。在上一篇文章中,我们也…

【ArcGIS Pro二次开发】(45):手搓一个工具执行进度框

我在之前做的工具中,UI这部分基本没怎么深入,都是直接用的现成的控件。 其中有一个问题比较突出,就是没有工具执行的进度框提示。曾经也用过系统自带的信息提示框和进度条,但太简陋,确实不好用。于是就想抄一个进度框…

Linux 读文件 - readahead预读算法

顺序读场景 intmain{charc[ 4096];intin -1;in open( "news.txt", O_RDONLY);intindex 0;while(read(in, &c, 4096) 4096){printf( "index: %d,len: %ld.\n",index, strlen(c));memset(c, 0, sizeof(c));index;} 数据结构 /** Track a single fi…

CentOS7 静默方式安装 Oracle19C

CentOS7 静默方式安装 Oracle19C 操作系统:CentOS7 Oracle: 19C 安装常用工具和依赖 yum -y install vim tar net-tools wget perl python3 readline* deltarpm python-deltarpm \zip unzip bc compat-libcap1* compat-libcap* binutils compat-libstdc…

最近的感悟与总结

目录 一、判别填鸭、与被填鸭的思考讲解人:听者: 二、最近感悟:三、再来三道数学题吧:四、总结 一、判别填鸭、与被填鸭的思考 讲解人: 1.是否在讲解过程中增加了知识认识的维度?(具体是什么,…

08_Linux按键输入

目录 Linux下按键驱动原理 修改设备树文件 添加KEY设备节点 按键驱动程序编写 编写测试APP 运行测试 Linux下按键驱动原理 按键驱动和LED驱动原理上来讲基本都是一样的,都是操作GPIO,只不过一个是读取GPIO 的高低电平,一个是从GPIO输出高低电平。实现按键输入,在驱动程序…

nginx的安装与自启动配置

1. nginx源码下载 nginx源码下载 2. nginx编译安装 2.1 解压安装包 tar -zxvf nginx-1.24.0.tar.gz2.2 编译安装 cd nginx-1.24.0 ./configure make make install执行./configure时可能出现如下的error,需要安装依赖库: 缺少pcre库 下载pcre安装包…

链码的安装、实例化、查询、调用

目录 1、首先保证网络已经处于启动状态 2、进入CLI容器 3、检查当前节点已经加入到哪些通道中(刚进来,默认是 peer0.example.com) 链码的安装 1、检查通道名称是否设置正确 2、使用install安装链码 3、实例化链码 4、查詢链码 发起交易 …

English Learning - L3 作业打卡 Lesson7 Day52 2023.6.27 周二

English Learning - L3 作业打卡 Lesson7 Day52 2023.6.27 周二 引言🍉句1: And that is when it dawned on me that I didn’t have to be 5,5 ft. anymore.成分划分弱读连读爆破语调 🍉句2: I could be as tall as I wanted, or as short as I wanted …

【电子学会】2023年05月图形化三级 -- 躲避陨石

文章目录 躲避陨石1. 准备工作2. 功能实现3. 设计思路与实现(1)角色、舞台背景设置a. 角色设置b. 舞台背景设置 (2)脚本编写a. 角色:Rocketshipb. 角色:Ball 4. 评分标准5. 知识块 躲避陨石 飞船在陨石乱飞…

MySQL数据库第一课 ---------安装

作者前言 欢迎小可爱们前来借鉴我的gtiee秦老大大 (qin-laoda) - Gitee.com 目录 虚拟环境虚拟环境 安装虚拟机 自主安装 简易安装 ———————————————————————————————————————— 虚拟环境虚拟环境 我们现在运行代码的环境是在 PyCharm…

大型语言模型作为属性化训练数据生成器

大型语言模型作为属性化训练数据生成器,提出一种使用多样化属性提示的数据生成方法,可以生成具有多样性和属性的训练数据,从而提高了模型的性能和数据生成的效率。 动机:大型语言模型(LLM)最近被用作各种自然语言处理(NLP)任务的…

从零开始——腾讯云服务器安装运行部署教程

一、腾讯云 1、购买腾讯云服务器 现在腾讯云服务器有优惠活动(大家可以在网上搜索各个服务器的优惠活动,有很多) 活动链接:上云精选_云服务器秒杀_开发者上云推荐-腾讯云 (tencent.com) 这里我选2G/2核/4M/50G轻量级服务器 这…

Linux基础服务6——Apache

文章目录 一、基本了解1.1 自带工具1.2 服务配置文件1.3 访问控制法则1.4 web相关的命令1.4.1 curl命令1.4.2 httpd命令 二、安装配置2.1 安装服务2.2 访问网页2.3 虚拟主机配置2.3.1 相同ip,不同端口2.3.2 相同端口,不同ip2.3.3 域名访问 三、https3.1 …

深度剖析 Linux 伙伴系统的设计与实现

目录 伙伴系统的核心数据结构 总结: 到底什么是伙伴 伙伴系统的内存分配原理 伙伴系统的内存回收原理 伙伴系统的实现 从 CPU 高速缓存列表中获取内存页 伙伴系统的核心数据结构 如上图所示,内核会为 NUMA 节点中的每个物理内存区域 zone 分配一个…

《计算机网络--自顶向下方法》第四章--网络层:数据平面

4.1网络层概述 每台路由器的数据平面的主要作用是从其输入链路向其输出链路转发数据报;控制平面的主要作用是协调这些本地路由器转发动作,使得数据报沿着源和目的地主机之间的路由器路径进行端到端传送 路由器具有截断的协议栈,即没有网络层…

[RISC-V]Milk-V开发板 i2c测试oled及波形输出

I2C3 引脚图 修改i2c3复用功能 build\boards\cv180x\cv1800b_sophpi_duo_sd\u-boot\cvi_board_init.c //I2C3 pin6 7 PINMUX_CONFIG(SD1_CMD, IIC3_SCL); PINMUX_CONFIG(SD1_CLK, IIC3_SDA);扫描I2C3上的设备 [rootcvitek]~# i2cdetect -y -r 3 0 1 2 3 4 5 6 7 8 9 a b c …

大数据Doris(五十四):BACKUP数据备份原理和语法

文章目录 BACKUP数据备份原理和语法 一、BACKUP数据备份原理 1、快照及快照上传 2、元数据准备及上传 二、BACKUP数据备份语法 BACKUP数据备份原理和语法 通过Doris数据导出的各种方式我们可以将Doris中的数据进行备份,除了export方式之外,Doris 还…