DDD架构实践

ddd架构浅析

背景介绍

什么是ddd架构,是以ddd思想为参考,做出一份符合ddd思想的框架。

随着技术的迭代升级,越来越多的瓶颈暴露出来,性能瓶颈,系统复杂度瓶颈,这些都逐一被迭代出的技术产物解决。最终的一个产物微服务,几乎完美解决了性能和系统复杂度的问题,保证服务性能的前提下,还简化了系统的复杂度,降低开发难度,让系统更加容易维护。

但是对于B端企业来说,单单解决性能和系统复杂度问题还远远不够,极度复杂的业务,让系统难以维护,动辄几百上千行的方法,让开发人员头疼。每一个简单逻辑的背后,都会存在多个业务方,多个业务方的兼容使得逻辑变得复杂,加上业务的变化频繁这一特点,让系统的复杂度极速提高。

ddd很早就出现了,由于过于复杂难以理解,一直没有很好地最佳实践。ddd的核心思想,就是为了解决B端企业的业务复杂度而生,近些年ddd的突然爆火,是因为有了最佳实践的落地,比较出名的比如cola的应用分层框架。

ddd核心分模块思想

ddd的思想核心是通过领域建模、分层分包的模式来进行降低业务复杂度,简化开发逻辑,清晰业务流向。

通过cola的最佳实践,可以把ddd进行落地,并且由核心和拓展几个点来进行分析。

核心模块

核心分包为 适配器、领域、基建包,

三个包都不相互依赖,形成相互隔离的几个单独模块,让每一个模块都只有很单一的能力,这样就可以很好的把业务限制在领域中,极好的来沉淀建立自己的核心业务能力。

适配器层:

由于B端业务多样性且复杂,所以需要单独的适配器来做,将不同的业务来进行适配,进入自己的核心且单一的能力中。

通过将单一能力,增加多个适配器,提高业务的适配能力。b端业务的多样性,往往体现在数据及命名的多样性,但核心的业务大体相同,所以通过适配器,可以极大降低因多样性带来的复杂度。

领域层:

领域层的单独存在,一方面是为了限制核心业务不会散落的到处都是,另一方面是让开发更加聚焦在核心业务的开发上。通过一些策略及拓展模式,就可以实现核心业务及其不同的特性。

B端企业级对外提供的能力一定是单一的,只有这样才能逐渐沉淀自己在行业内的影响力,如果什么都能支持,反而会觉得什么都不强,都不稳定。而且随着差异太大的业务,会导致成本剧增。

单一的能力,会逐渐去完善产品能力,最终沉淀产出一个标准的行业产品。

在大能力不变的情况下,不同的特性处理,通过一些拓展点,就可以快速实现接手。

基建层:

在B端业务中,三方依赖的侵入性变动也是对业务稳定性的一个侵蚀,比如业务前期,使用某种组件可以满足业务需求,随着发展需要更换另一种组件,这种组件变更给系统带来的稳定性影响是非常重要的,因为组件的变更导致业务宕机是非常不合理的,为了避免这种情况,将三方组件完全隔离是非常必要的。

三方组件包括但不限于:数据库、缓存、mq、三方接口、三方sdk、三方rpc等。

可以认为所有和外部交互的都应该限制在基建层,以此来进行隔离,保证系统的稳定性。

domain模块

domain是三个模块的轴承,通过依赖倒置,让三个模块相互隔离,全都由domain拉着,通过domain进行交互。

domain的必要性:

从物理层面进行隔离,让其他人不能使用其他模块的东西。

pom的变更应该提起cr人员的注意,切实做好每一个pom变更,避免在代码中引入坏味道。

引入之后通过规约来限制是很不合理的,根据墨菲定律,只要存在,就一定会被人使用到。

非核心模块

client模块:

如果系统有对外提供的能力,比如rpc接口,mq实体定义等。

这些内容是切面与系统存在的,需要提供给外部引用,应该单独出来,避免把自己的核心内容给外部使用。

优势:

  1. 避免由于外部使用不当,导致自己内部的实体变更,让交互不稳定。
  2. 避免由于提供依赖太大,导致对方系统的负担
  3. 避免核心能力让对方引用,增加安全风险

遵守规则:

  1. client包中,不应有任何三方依赖,只是一个简单接口及实体的定义
  2. 不应有内部使用的包,只需要提供外部所需的即可,遵守最小可用原则
  3. 统一出参封装,所有对外提供的接口应统一封装,方便框架层面做统一处理。

common模块

对应本应用而言,在不同模块中都有使用到的工具,分别定义是不合适的,通过common包来抽象出共有能力,来降低代码重复率。

ext模块

如果业务的多样性非常复杂,对每一个特性的处理都需要大量的业务逻辑,那么ext模块单独抽出就很有必要。多样性处理的太多,和核心业务掺杂在一块,随着业务的发展,就会产生特性分支和主分支分不清的情况,混用,职责不清晰,能力不单一。即使规约的再好,根据墨菲定律,这种问题一定会发生。

另外一些高阶的玩法,ext模块外置,核心能力很稳定,拓展能力变动较大时,ext模块会成为热插拔组件,通过快速迭代更新来满足业务,做到完全的系统热插拔,不影响当前业务,新的业务快速上线。

也为了避免不同特性分支相互影响,通过这种做到完全隔离。

sop模块

核心业务稳定,且领域模型较为完善,业务进入后期阶段,新的业务接入就不再依托于编码,而且通过流程引擎来做编排,让新的业务进入。

同一个业务能力,有多种处理,且都为核心能力,此时就应该把这个作为一个sop,把这些提出来一个sop模块单独处理,原本核心的领域层,做流程编排及其他前置业务处理。拓展点再次升级为某个sop的拓展能力。

一般情况下,sop是ext的发展产物,某个ext的特性分支业务发展很好,逐渐成长为核心业务,趋于稳定,此时该特性分支就会成为核心能力分支。

最佳实践讲解

本节主要来解析每一个模块中,应该放些什么,每一层的依赖如何处理等。

分层模块

适配器模块

本层定位是系统入口,所有的业务起点,都应该在这里。

比如:controller接口、rpc接口实现、mq消费者实现等。

本层依赖:

内部依赖:核心领域模块,client模快、common模块。

三方依赖:核心框架、rpc和mq等必要框架、基础组件。

禁止依赖:业务模块、基建模块

特殊说明

本层的模型定义在本层内、或者取自client。

本层调用领域层之前,需要做好模型转换,将模型转换为领域层里面定义的模型,然后再定义,这层的转换器应该写在这层。

业务模块

本层定位为核心业务逻辑处理,所有的业务处理都应在这里。

比如:业务流程判断走向、业务逻辑判断、根据不同的数据做不同的处理、调用数据库接口、调用mq接口、和外部交互的逻辑等。

本层依赖:核心领域模块、common模块。

三方依赖:核心框架

禁止依赖:适配器模块、基建模块、client模块、任何非必要三方依赖

特殊说明

本层不需要做任何类型转换,进来就是自己所需要的模型。

本层不允许引入其他模块的模型,这层的模型都应该非常稳定,不能有三方注解(比如rpc注解、fastjson注解、mybatis注解、mq注解等)

基建模块

本层定位为防腐基础设施,所有和外部的交互都应该在这里,这里应该为单条线的末端。

比如:从数据库中获取数据的最终实现,从缓存中获取数据的最终实现,发送mq的实际实现,调用rpc接口的最终实现等。

本层依赖:核心领域模块、common模块。

三方依赖:核心框架、外部sdk、外部client模块、任何三方所需要的依赖。

禁止依赖:适配器模块、client模块、业务模块

特殊说明

本层的模型可以用到领域模型或者三方交互模型。进来都是领域模型,根据需求转换为对应的三方接口模型。

处理完如果有数据透出,必须要使用类型转换器,不可把本层模型透出,也不能把三方接口模型定义到领域模块中。

领域模块

本层定位是不同模块的轴承,所有的核心交互接口定义及数据模型定义都在这里,这里联通各个模块。

比如:核心业务处理的接口(DomainService),基础建设中的能力透出接口(InnerService/Gateway)。

本层依赖:common模块

三方依赖:无

禁止依赖:几乎不允许依赖任何内容

client模块

本层定位是本系统对外提供的能力点透出。

比如:对外提供的rpc接口,对外提供的mq模型等。

本层依赖:无

三方依赖:无

禁止依赖:几乎不允许依赖任何内容

common模块

本层是不同模块之间通用的工具内容。

比如:字符串处理工具,各种util类,各种通用处理能力。

本层依赖:无

三方依赖:非常稳定的三方工具包(原则上需要自己重写一套),几乎不能引用其他三方依赖。

start模块:

应用的启动模块,定义启动器及启动所必须得一些内容。

比如:spring boot启动器,启动配置,项目中的一些配置。

本层依赖:所有的模块

三方依赖:基础框架依赖

ddd框架实践

一套最基础的增删改查实践

╔ adapter
║ ╟ java
║ ╟ ╟ RpcXXXServiceImpl.java
║ ╟ ╟ XXXController.java
║ ╟ ╟ XXXConsumer.java
║ ╟ resource
║ ╚ pom.xml
╟ biz
║ ╟ java
║ ╟ ╟ XXXDomainServiceImpl.java
║ ╚ pom.xml
╟ infra
║ ╟ java
║ ╟ ╟ XXXConverter.java
║ ╟ ╟ XXXClient.java
║ ╟ ╟ XXXInnerServiceImpl.java
║ ╟ ╟ XXXDO.java
║ ╟ resource
║ ╟ ╟ mapper
║ ╟ ╟ ╟ xxxMapper.xml
║ ╚ pom.xml
╟ domain
║ ╟ java
║ ╟ ╟ XXXDomainService.java
║ ╟ ╟ XXX.java
║ ╚ pom.xml
╟ client
║ ╟ java
║ ╟ ╟ RpcXXXService.java
║ ╟ ╟ XXXDTO.java
║ ╚ pom.xml
╟ common
║ ╟ java
║ ╟ ╟ XXXUtil.java
║ ╚ pom.xml
╟ start
║ ╟ java
║ ╟ ╟ Application.java
║ ╟ ╟ config
║ ╟ ╟ ╟ Config.java
║ ╟ resource
║ ╟ ╟ application.properties
║ ╟ ╟ META-INF
║ ╚ pom.xml
╚ pom.xml

实际demo

TODO…

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

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

相关文章

SE-Net:Squeeze-and-Excitation Networks(CVPR2018)

文章目录 AbstractIntroduction表征的重要性以前的方向本文提出 Related WorkDeeper ArchitectureAlgorithmic Architecture SearchAttention and gating mechanisms Squeeze-and-Excitation BlocksSqueeze: Global Information EmbeddingExcitation: Adaptive RecalibrationIn…

Python的魔术方法

什么是魔术方法 魔法方法(Magic Method)是python内置方法,格式为:“方法名”,不需要主动调用,存在的目的是为了给python的解释器进行调用,几乎每个魔法方法都有一个对应的内置函数,或者运算符,…

高中信息技术教资科目三

第一章-课程理论知识 学科核心素养 信息意识计算思维数字化学习与创新信息社会责任 教学环节 新课导入新课讲授巩固提高小结作业 第二章-教学实施类 第一节-新课导入 导入原则 针对性原则趣味性原则简洁性原则启发性原则 导入方法 开门见山温故知新生活情境作品情境活…

2023长三角(芜湖)人工智能数字生态峰会成功召开!

聚焦当下,共议数字时代发展;瞩目未来,共谋数字生态蓝图。12月11日,2023长三角(芜湖)人工智能数字生态峰会暨2023长三角(芜湖)人工智能视觉算法大赛颁奖典礼在芜湖宜居国际博览中心盛…

如何使用AnyTXT Searcher实现远程办公速查异地电脑文件提升工作效率

如何使用AnyTXT Searcher实现远程办公速查异地电脑文件提升工作效率 前言1. AnyTXT Searcher1.1 下载安装AnyTXT Searcher 2. 下载安装注册cpolar3. AnyTXT Searcher设置和操作3.1 AnyTXT结合cpolar—公网访问搜索神器3.2 公网访问测试 4. 固定连接公网地址 前言 你是否遇到过…

飞速(FS)100G ZR4 光模块80km长距离传输

如今,100G QSFP28光模块已经被广泛部署在100m到40km的范围内。然而,传统的100G QSFP28模块面临一个挑战,因为它们的设计仅限于不超过40km的距离。超出此范围,色散、光衰减等问题就会增加,导致信噪比(SNR&am…

八股文打卡day3——计算机网络(3)

面试题:请讲一下四次挥手的过程? 1.客户端发送FIN数据包给服务器,表示客户端不再发送数据给服务器,想要断开这个方向的连接。 2.服务器收到客户端的FIN包之后,发送ACK包给客户端,对收到的FIN包进行收到确认…

Vue3 Element Plus WindiCSS 项目开发环境搭建

一 概述 MVVM 是 Model-View-ViewModel 的简写,它本质上是 MVC 的改进版。MVVM 将其中的 View 的状态和行为抽象化,并且将视图 UI 和业务逻辑分开。 (1)M:即 Model(模型),包括数据和…

13. 从零用Rust编写正反向代理, HTTP中的压缩gzip,deflate,brotli算法

wmproxy wmproxy是由Rust编写,已实现http/https代理,socks5代理, 反向代理,静态文件服务器,内网穿透,配置热更新等, 后续将实现websocket代理等,同时会将实现过程分享出来&#xff…

mysql的索引约束检查触发器

索引: MySQL 索引是一种用于提高查询性能的关键数据库特性。通过在表上创建索引,MySQL 可以更有效地定位和检索数据,从而加速查询操作。以下是关于 MySQL 索引的一些基本信息: 1. **索引类型:** - **单列索引&…

构建智慧储能物联网,4G工业路由器远程监测在线管理

物联网技术的发展为智慧储能管理带来了革命性的变化。其中,4G工业路由器IR5000通过丰富的连接能力如串口RS485/232或网口的方式,实现了与储能现场各设备的连接,包括电表、电能检测器、防孤岛装置、BMS电池管理系统、监控服务器、储能控制器、…

WEB渗透—PHP反序列化(五)

Web渗透—PHP反序列化 课程学习分享(课程非本人制作,仅提供学习分享) 靶场下载地址:GitHub - mcc0624/php_ser_Class: php反序列化靶场课程,基于课程制作的靶场 课程地址:PHP反序列化漏洞学习_哔哩…

xcrun: error: invalid active developer path

macOS升级完成后出现 xcrun: error: invalid active developer path问题。 xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun这是由于 Xcode command line tools 丢…

Python-Selenium-使用 pywinauto 实现 Input 上传文件

当前环境:Win10 Python3.7 pywinauto0.6.8,selenium3.14.1 示例代码 from pywinauto import Desktop import osapp Desktop() dialog app[打开] dialog[Edit].set_edit_text(os.getcwd() .\\example-01.jpg) dialog[Button].click() 其他方法&…

LINUX SD卡备份的镜像+烧录启动时自动扩展最后一个分区

在开发到生产过程中,对系统镜像的备份及再烧录过程是必不可少的。经常看到烧录官方镜像的时候,我们会发现当镜像第一次启动后,磁盘空间会自动扩充到整个TF/SD卡。那么当我们自己制作镜像的时候,能不能去除未使用的空间,制作体积较小的镜像,并在该镜像启动时自动扩展,从而…

【影像组学入门百问】#29---#31

#29-影像组学研究中,消除不同影像间因设备和扫 描参数引起的差异的方法有哪些? 在影像组学研究中,消除不同影像间因设备和扫描参数引起的差异至关重要。以下是一些常用的方法: 1.归一化(Normalization)&a…

喜报|棱镜七彩获评江苏省专精特新中小企业

近日,江苏省工业和信息化厅发布《关于江苏省2023年专精特新中小企业和2020年度专精特新企业复核通过企业名单的公示》,棱镜七彩成功入选2023年江苏省省级专精特新中小企业名单。 图 2023年省级专精特新中小企业公式名单节选 “专精特新”是国家为鼓励中…

Python纯净式下载与安装

1. 下载 Download Python | Python.org 建议下老版本些的,毕竟求稳。 点击需要的版本,然后滑倒最下面,可以看到不同系统对应的下载选项: 2. 安装 如果下载慢的话,可以复制链接到迅雷下载,下载完成后&…

这个食堂管理大招,再不知道就晚了!

随着社会的不断发展,餐饮行业也在不断创新和进步。在这个数字化时代,智能技术为各行各业提供了更高效、便捷的解决方案。 食堂作为人们日常生活中不可或缺的一部分,也迎来了智能化的时代。智慧收银系统不仅提高了食堂的运营效率,还…

应用Transformer和CNN进行计算机视觉任务各自的优缺点

Transformer 和 CNN(卷积神经网络)是用于计算机视觉任务的两种不同的深度学习架构,各自具有一些优点和局限性。 一、Transformer: 优点: 全局信息关系建模: Transformer 通过自注意力机制(self-attentio…