实现领域驱动设计-应用结构

写在前面:

   DDD的一大好处便是它并不需要使用特定的架构。我们可以在整个系统中使用多种风格的架构。有些架构包围着领域模型,能够全局性地影响系统,而有些架构则满足了某些特定的需求。我们的目标是选择适合于自己的架构和架构模式

   在选择架构风格和架构模式时,我们应该将软件质量考虑在内,必须对每种架构做出正确的评估。对架构风格和模式的选择受到功能需求的限制,换句话说,在没有功能需求的情况下,我们是不能对软件质量做出评判的,亦不能做出正确的架构选择。这也说明用例驱动架构在当今的软件开发中依然适用。

传统分层架构

在这里插入图片描述

分层架构原则:
   每一层只能与直接位于其下方的层发生耦合。这确保了各层之间的独立性。

分层架构也分为两种:

  1. 严格分层架构:在严格分层架构中,每一层只能与其下方的层发生耦合,以确保更严格的分离。
  2. 松散分层架构:相比之下,松散分层架构允许任何上方层与下方层发生耦合,通常用于用户界面层和应用服务需要与基础设施互动的系统。

用户界面层
   主要责任是处理用户显示和请求,而不应包含领域或业务逻辑。(用户界面需要对数据进行验证,但和领域内的验证是不同的。)

应用服务(Application Services)

  1. 作用:可以处理持久化事务、安全认证、事件通知、邮件发送等任务。接收来自用户界面的输入参数,再通过资源库获取到聚合实例,然后执行相应的命令操作,
  2. 对接领域模型:应用服务是领域模型的直接客户,用于协调对领域对象的操作,比如聚合(数据聚合、业务操作聚合)。

基于DIP的分层

依赖倒置(DependencyInversionPrinciple)定义:
高层模块不应该依赖于低层模块,两者都应该依赖于柚象。
抽象不应该依赖于细节,细节应该依赖于抽象。

   根据该定义,低层服务(比如基础设施层)应该依赖于高层组件(比如用户界面层、应用层和领域层)所提供的接口。因此架构演变为:
在这里插入图片描述
   当我们在分层架构中采用依赖倒置原则时,我们可能会发现,事实上已经不存在分层的概念了。无论是高层还是低层,它们都只依赖于抽象,好像把整个分层架构给推平了一样。

六边形架构

六边形架构 = 端口与适配器 = Onion架构。DDD首选架构

   该架构中存在两个区域,分别是“外部区域”和“内部区域”.
在这里插入图片描述

  1. 适配器A\B\C使用了HTTP协议来输入,适配器D使用AMQP(如kafka)来输入。
  2. 在外部区域中,不同的客户均可以提交输入;
  3. 而内部的系统,则用于获取持久化数据,并对程序输出进行存储(比如数据库),或者在中途将输出到其他系统(如消息)
  4. 适配器E、F、G使用关系型数据库、基于文档的存储、分布式缓存和内存存储输出数据;适配器H处理消息输出。

如何理解端口、适配器?

  1. 可以将端口想成是HTTP,而将适配器想成是Java的Servlet 、 JAX-RS的REST、Spring-RESTful Web请求处理类。
  2. 为ServiceBus或RabbitMQ创建消息监听器,在这种情况下,端口是消息机制,而适配器则是消息监听器,因为消息监听器将负责从消息中提取数据,并将数据转化为应用层API所需的参数。

REST 架构

REST作为一种架构风格

   架构风格将不同架构实现所共有的东西抽象出来,使得我们在谈及架构时不至于陷入到技术细节中。

   分布式系统架构存在着多种架构风格,包括客户端-服务器架构风格和分布式对象风格。而REST就应该是属于Web架构的一种架构风格

REST和DDD

   不建议将领域模型直接暴露给外界,因为这样会使得系统变得脆弱,原因在于对领域模型的每次改变都会导致对系统接口的改变。将两种方式结合有两种方法。

  1. 第一种方法是为系统接口层单独创建一个界限上下文,再在此上下文中通过适当的策略来访问实际的核心模型。它将系统看做一个整体,通过资源抽象将系统功能暴露给外界,而不是通过服务或者远程接口。

    • 这种方法应该被优先考虑,因为它在核心域和系统接口模型之间完成了解耦,使得我们可以先做修改,再决定哪些修改应该反应到系统接口模型上。
  2. 另一种方法用于需要使用标准媒体类型的时候。我们可以创建一个领域模型来处理每一种媒体类型,并且能在服务器和客户端之间进行重用。

为什么是REST?

   符合REST原则的系统具有更好的 松耦合性和可伸缩性,基于REST的系统被分为很多较小的资源块,每一个资源块都可以独立地测试和调试,并且每一个资源块都表示了一个可重用的入口点。HTTP设计本身以及URI成熟的重写与缓存机制使得RESTful HTTP成为一种不错的架构。

CQRS架构

什么是CQRS?

CQRS(Command Query Responsibility Segregation),Command 与 Query 分离的一种模式。

  • Command:命令则是对会引起数据发生变化操作的总称,即新增,更新,删除这些操作,都是命令
  • Query:查询则不会对数据产生变化的操作,只是按照某些条件查找数据

CQRS 的核心思想是将这两类不同的操作进行分离,可以是两个独立的应用,两个不同的数据源,也可以是同一个应用内的不同接口上。

引入的目的

   一个业务系统会存在各种查询功能,但没有业务逻辑(或者很少),如果按照常规的领域分层会导致大量的模型转换工作,并且存在大量的分页信息(pageSize\pageNo\totalPage等)无处安放,因为它们并不属于Domain内的属性或行为,如果算Domain里的属性,会导致Domain越来越大。

   因此,CQRS旨在解决领域驱动中,数据显示复杂性问题。说白了,就是“数据查询”和“业务操作”分离。

架构图:
请添加图片描述

   CQRS 在 DDD 中是一种常常被提及的模式,它的用途在于将领域模型与查询功能进行分离,让一些复杂的查询摆脱领域模型的限制,以更为简单的 DTO 形式展现查询结果。同时分离了不同的数据存储结构,让开发者按照查询的功能与要求更加自由的选择数据存储引擎。

事件驱动架构

事件驱动架构(Event-Driven Architecture,EDA)是一种用于处理事件的生成、发现和处理等任务的软件架构。

   一个系统的输出端口所发出的领域事件,被发送到另一个系统的输入端口,此后输入端口事件的订阅方将对事件进行处理。

  在一个界限上下文处理某个事件时,应用程序API将采用该事件模型中的属性值来执行响应的操作。应用程序API所执行的命令操作将反映到命令模型中。
在这里插入图片描述

长时处理过程

设计长时处理过程有三种方法:

  • 将处理过程设计成一个组合任务,使用一个执行组件对任务进行跟踪,并对各个步骤和任务完成情况进行持久化。

  • 将处理过程设计成一组聚合,这些聚合在一系列的活动中相互协作。一个或多个聚合实例充当执行组件并维护整个处理过程的状态

  • 设计一个无状态的处理过程,其中每一个消息处理组件都将对所接收到的消息进行扩充一一即向其中加入额外的数据信息,然后再将消息发送到下一个处理组件。在这种方法种,整个处理过程的状态包含在每条消息中。

事件源

   有时,我们的业务可能需要对发生在领域对象上的修改进行跟踪。有如下三种跟踪方式:

  1. 关注于业务数据的创建时间(create_time)、修改时间(modify_time)和删除时间(delete_time),以及相关的操作人。对于这种跟踪不敏感的业务场景,只用多列维护即可

  2. 对于相对敏感的业务场景,每次新增、修改、删除(逻辑删除),我们都会针对其操作时间和操作人记录一条详细的操作记录,这样方便后续对业务数据修改的回溯与跟踪。

  3. 更敏感的场景,就是需要记录对数据的改变前和改变后的状态,通过操作记录,可以实现数据的重放或回滚(和Git、SVN等非常相似)。

   那么我们将第三种概念应用在单个实体或聚合上,这种变化跟踪便是事件源(Event Sourcing)的核心。事件源模式,如下图所示:
在这里插入图片描述
   事件源是对于某个聚合上的每次命令操作,都有至少一个领域事件发布出去,该领域事件描述了操作的执行结果。每一个领域事件都将被保存到事件存储(Event Store)中。每次从资源库中获取某个聚合时,我们将根据发生在该聚合上的历史事件来重建该聚合实例,事件的作用顺序应该与它们的产生顺序相同。

   这种也类似于针对聚合状态的快照(Snapshot),但是对于请求量级比较大的情况,频繁的去创建快照也是非常消耗资源的,所以,我们可以自定义一个阈值(例如:事件数超过50个),当超过这个阈值的时候,我们再创建这个聚合状态的快照,从而获得最优的聚合创建与获取效果。

   事件源有助于获得高吞吐量的领域模型,从而极大地提高事务处理效率。另外,事件源还有助于提高CQRS查询模型的伸缩性,因为此时查询模型的数据源可以在事件存储更新之后得到静默更新。

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

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

相关文章

Java格式化类Format

文章目录 Format介绍Format方法- format(格式化)- parseObject(解析) 格式化分类日期时间格式化1. DateFormat常用方法getInstancegetDateInstancegetTimeInstancegetDateTimeInstance 方法入参styleLocale 2. SimpleDateFormat常…

【HarmonyOS】鸿蒙应用开发基础认证题目

系列文章目录 【HarmonyOS】鸿蒙应用开发基础认证题目; 文章目录 系列文章目录前言一、判断题二、单选题三、多选题总结 前言 随着鸿蒙系统的不断发展,前不久,华为宣布了重磅消息,HarmonyOS next 开发者版本会在明年(…

编写函数实现简单的插值进入有序数组问题

归纳编程学习的感悟, 记录奋斗路上的点滴, 希望能帮到一样刻苦的你! 如有不足欢迎指正! 共同学习交流! 🌎欢迎各位→点赞 👍 收藏⭐ 留言​📝 老骥伏枥,志在千里&…

JVS低代码表单设计:数据联动详解(多级数据级、数据回显等)

在这信息化时代,表单作为数据的收集和展示工具,已经渗透到不同的角落。JVS低代码对表单的设计和操作进行了不断的优化和创新。其中,联动回显作为一项重要的功能,无论是多级数据级联控制、组件的联动控制,还是多表的数据…

Unexpected WSL error

问题描述 启动 Docker Desktop 报错 Unexpected WSL error,报错完整信息如下: Docker Desktop - Unexpected WSL error An unexpected error was encountered while executing a WSL command, Commoncauses include access rights issues, which occur…

[github初学者教程] 分支管理-以及问题解决

作者:20岁爱吃必胜客(坤制作人),近十年开发经验, 跨域学习者,目前于新西兰奥克兰大学攻读IT硕士学位。荣誉:阿里云博客专家认证、腾讯开发者社区优质创作者,在CTF省赛校赛多次取得好成绩。跨领域…

虚拟化逻辑架构: 创建KVM中的VM与实现VNC远程登录

目录 一、实验 1.安装KVM环境管理工具并创建VM(虚拟机) 2.Windows使用VNC Viewer连接KVM中的VM(虚拟机) 二、问题 1.如何下载安装VNC Viewer 一、实验 1.安装KVM环境管理工具并创建VM(虚拟机) (1) 采…

golang学习笔记——日志记录

文章目录 日志与错误log包记录到文件记录框架Contextual LoggingLeveled LoggingSetting Global Log Level Error Logging 日志与错误 通常,发生错误时,最终用户只会看到一条消息,指示程序出现问题。日志是简单错误消息以外的更多信息。 lo…

城市智慧路灯智能照明管理系统简介

城市路灯存在着开关灯控制方式单、亮灯时间不准确、巡查困难、故障处理不及时、亮灯率无法把控等问题,从而导致路灯系统能耗高,维护成本高。传统的路灯控制系统已无法满足智慧城市管理的需要,智能路灯照明控制系统从而得到广泛应用。 叁仟智…

【C++】使用std::vector()函数实现矩阵的加、减、点乘、点除等运算

本文通过vector&#xff08;&#xff09;函数表示矩阵的形式&#xff0c;对 加、减、点乘、点除等运算进行编码和运行&#xff0c;相应结果如下文所述。 #include <iostream> #include <vector>using namespace std;// 矩阵加法 vector<vector<int>> …

buildadmin+tp8表格操作(4) Table组件,baTable类和 elementplus中的属性关系

在buildadmin 中&#xff0c;table组件是封装的 element-plus中的方法&#xff0c; 所以说&#xff0c; 在 buildadmin的table组件中&#xff0c;是可以通用 elementplus中的属性的 以上这些属性&#xff0c; 在buildadmin中都是可以使用的 使用方式和 elementplus el-table用…

linux rsyslog综合实战1

本次我们通过rsyslog服务将A节点服务器上的单个日志(Path:/var/log/245-1.log)实时同步到B节点服务器目录下(Path:/opt/rsyslog/245) 1.rsyslog架构 2.环境信息 环境信息 HostnameIpAddressOS versionModuleNotersyslog1192.168.10.245CentOS Linux release 7.9.2009 (Core)rs…

工作记录---为什么双11当天不能申请退款?(有趣~)

为什么&#xff1f; 服务降级了 服务降级&#xff1a; 当服务器压力剧增的情况下&#xff0c;根据实际业务情况及流量&#xff0c;对一些服务和页面有策略的不处理或换种简单的方式处理&#xff0c;从而释放服务器资源以保证核心交易正常运作或高效运作。 分布式系统的降级…

十四、Docker的基本操作

目录 &#xff08;一&#xff09;镜像命令 一、拉取Nginx 二、查看镜像 三、导出文件 四、删除镜像 五、加载镜像 &#xff08;二&#xff09;容器命令 一、例子&#xff1a;运行一个nginx容器 1、输入运行命令 2、使用命令查看宿主机ip 3、在外部浏览器访问 4、查看…

crmchat安装搭建教程文档 bug问题调试

一、安装PHP插件&#xff1a;fileinfo、redis、swoole4。 二、删除PHP对应版本中的 proc_open禁用函数。 一、设置网站运行目录public&#xff0c; 二、设置PHP版本选择纯静态。 三、可选项如有需求则开启SSL,配置SSL证书&#xff0c;开启强制https域名。 四、添加反向代理。 …

苹果CMS首涂第30套可装修DIY主题模板免授权版

这是一款可以装修的主题&#xff0c;类似淘宝店装修一样&#xff0c;可以针对首页、栏目页、详情页、播放页进行自定义装修&#xff0c;内置10个模块自由选择、添加、修改、删除、排序操作&#xff0c;后续升级还会增加更多实用和个性模块供选择&#xff0c;主题内包含的导航、…

类与对象(上篇)

前言 在之前我们学的C入门主要是为现在学习类与对象打基础&#xff0c;今天我们才算真正开始学习C了。因为类与对象的知识点比较多&#xff0c;所以我们将它分为三部分讲解&#xff0c;今天我们学习类与对象的上篇。 一、面向过程和面向对象的初步认识 1、面向过程 面向过程顾…

基于安卓android微信小程序的个人管理小程序

运行环境 开发语言&#xff1a;Java 框架&#xff1a;ssm JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09; 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&a…

Java架构师软件架构设计导论

目录 1 软件架构设计导论2 HR角度看架构师3 软件架构设计概述4 顶级大师眼中的架构5 建筑中的架构师6 软件架构的发展阶段7 软件架构的意义8 架构是项目干系人进行交流的手段9 架构有助于循序渐进的原型设计10 架构是设计决策的体现11 架构明确系统设计约束条件12 架构与组织结…

【python】直方图正则化详解和示例

直方图正则化&#xff08;Histogram Normalization&#xff09;是一种图像增强技术&#xff0c;目的是改变图像的直方图以改善图像的质量。具体来说&#xff0c;它通过将图像的直方图调整为指定的形状&#xff0c;以增强图像的对比度和亮度。 直方图正则化的基本步骤如下&…