领域驱动设计(六) - 架构设计浅谈

news2024/11/19 9:22:51

单用一篇文章很难把这个主题描述的清楚,但为了系列的完整性,笔者会围绕DDD中所介绍的内容做下初步总结,使读者有一个连续性。

一、概述

现在不是局部解决问题的时代了要运用新的技术创造新的效率提升,需要整个商业链条一起前进。需要以系统或生态的角度来考虑问题,而不能回到点到点的突破层面。

基于以上背景慢慢的会衍生出新的岗位和角色。技术层面也驱于两级化发展,初级开发越来越倾向于工具的使用,高级研发越来越需要更全面,进而对架构和架构师提出了额外的要求。

1.1、对架构师的要求

  • 全局观:顶层设计+物理架构+应用架构,在顶层设计时充分考虑成本、效率、稳定、性能等因素;
  • 基本要求:前瞻性和解决复杂问题的能力和思路;
  • 能力要求:发现问题、定义问题、解决问题,问题是指一类问题;

1.2、一个良好的架构设计要包含

除了传统意义上所讲的CAP等两高或三高等,笔者认为更应该往下落一点,架构师不能只关心顶层设计,更多的要关心到细节或编码层面,这样才不至于出现实现偏差的问题。以下是笔者总结的几点:

  • 清除单点:系统的每一层级都有不同的集群策略,同时还要考虑容器自动增删功能;
  • 数据一致性:复杂业务可以采用消息中间件再配合不同级别的对帐机制保证;
  • 强弱依赖:在成本可接受的情况下,还可以实现做一套备份流程来临时支撑系统运行,但会导致数据不一致,即一定时间窗口内数据不一致;
  • 热点和极限值处理:a、隔离享用专有资源,适用于大客户的场景与普通客户分离;b、提前预热也可分为大小客户之分;c、简单逻辑、限流、排队等;d、IM这样的场景可以从业务上区分用户极别做到分极处理,在体验上有所侧重;
  • 资损流程:这块的程序对于数据一致性的要求比较高,所以在设计时要额外增加对帐、总额控制、异常、风控等设计;
  • 离线数据流:规模大、来源广、生产链路长,在整体生产和传输链路中,很容易出现数据少量丢失、部分环节失败、数据生产延迟等情况,最终消费在线系统也很难感知少量数据错误进而导致故障。针对离线数据流,要增加不同传输环节数据完整性校验、不同生产环节数据正确性校验、数据延迟监控、数据生产失败监控、端到端数据正确性规则校验、数据错误或延迟兜底预案、数据回滚重刷工具等机制;
  • 异常流程设计:详细可参考笔者的另一篇文章 ​​https://blog.51cto.com/arch/5295170​​ ;

二、SOLID

这个原则,是笔者认为比较好的一种指导思想,这里简单罗列一下概念,有兴趣的读者可深入研究一下,总结如下:

  • 单一职责:单一原则的划分依据并不是根据实体来聚合的,这里是按职责或相互关联的功能来聚合的,职责可以从变化原因的角度来考虑;在落地时可以通过拆分来达到职责的单一;
  • 开闭原则:在实际落地时一般采用抽象的理念,通过继承的方式来扩展功能,同时保证原代码的固化。但一个最重要的前提要考虑到多态的实现,这会直接影响函数的执行顺序;
  • 里氏替换:落地时也是用了抽象和继承思想。它强调的是在不遵循开闭原则的前提下达到一种功能的增强和替换。如果子类不能完整的实现父类的方法,就应该采用依赖、聚合、组合等关系代替继承;
  • 接口隔离:客户端不应该强迫依赖它不需要的接口,类间的依赖关系应该建立在最小的接口上。这个原则多少和单一职责有些关系,我们可以从安全或场景的角度来隔离接口;
  • 依赖倒置:高层模块不依赖低层模块,它们共同依赖同一个抽象,这个抽象接口通常是由高层模块定义,低层模块实现。同时抽象不要依赖具体实现细节,具体实现细节依赖抽象。这个设计原则分了三层:高层-抽象-底层,可以被复用的是高层+抽象。而不是抽象;

三、常用的架构设计

常见的架构一般有经典MVC分层、六边形(又称接口适配器)、CQRS、事件驱动、微服务等,在DDD中主推的是CQRS、六边形、事件驱动三种。从落地情况来看多数会采用分层和六边形架构。

然而现实情况是我们很难去说清我们的系统到底用的是哪种架构模式,多数是一种混合架构,比如任一架构都存在层次、任一架构都可以存在多种服务协议接口。更多的是看如何来表述,架构的表述最重要的一点就是是否能描述清楚层次的职责以及不同层次之间的依赖关系和依赖原则(依赖细节还是依赖抽象)。下面是DDD的经典层次结构:

  • UI表现层:显示信息、解释用户指令,用户指令解释;
  • 用户接口层:提供给UI表现层的数据API接口;
  • 应用接口层:定义软件要完成的任务,指挥领域层来解决问题,它不包含业务规则和状态,但需要管理安全和事务,但可以包含任务的进度状态;而只为下一层中的领域对象协调任务,分配工作,使它们互相协作,只提问;
  • 领域层:也称模型层,控制业务状态,业务状态信息和业务规则,借助基础设施层持久化信息;只回答,内部通过适配器的方式与不同领域交互;
  • 基础设施层:为上面各层提供通用的技术能力;相当于工具和持久层;持久化层的数据模型可以和领域模型完全不同,也可以相同。但要在概念上区分开;

3.1、MVC分层

3.1.1、设计原理

分层架构只有一个约束:上层只能与位于下方的层发生耦合。分为严格分层架构和松散分层架构,通常会采用松散分层架构,通常会遇到逆向调用的问题,一种解决方案是逻辑下沉,也可以采用以下两种方案实现逆向调用:

  • 观察者模式:底层发布事件,高层接收;
  • 调停者模式:底层定义接口,高层实现;同时可把实现做为参数向下传递;

  • 图1:经典松散分层架构,需注意逆向调用的问题;
  • 图2:主要解决领域层依赖基础设施的问题,它是把领域接口实现放在了应用层,由应用层去引用基础设施;
  • 图3:采用依赖倒置的设计,通俗来讲就是:高层模块不依赖低层模块两者都依赖于抽象(接口定义),抽象不依赖细节(接口实现)而细节依赖抽象;

3.1.2、分层架构特殊说明

DDD中应用层一般是很薄的一层,不应该包含业务逻辑,一般用于控制持久化事务和安全认证,或者向其它系统发送消息通知,它主要用于接收端指令,再通过资源库获取聚合实例,然后执行相应的领域服务。

当领域层用于发布领域事件时,应用层可以将订阅方注册到任意数量的事件上,这样的好处是可以对事件进行存储和转发。这时领域层只需关注自己的核心逻辑即可,领域事件发布器也适合做成适配的方式,与底层基础设施间解耦(无论怎么设计领域层就是核心业务不能依赖基础设施层);

3.2、Adapter六边形

3.2.1、设计原理

从分层到六边形需要一个概念上的转换,端口和适配器的功能就是将客户输入转化成能被系统API所理解的参数,实际的操作是委托给内六边形的。这种架构中存在两种适配器:

  • 处理输入:接收用户指令,向应用程序发起请求,调用port;
  • 处理输出:响应请求,输出到外部设备或工具中,实现port;

六边形架构的优点是:

  • 可以轻易开发用于测试的适配器;
  • 应用程序和领域模型可以单独开发;
  • 接入方也可以并行开发,通过适配器方式接入;

3.2.2、六边形架构特殊说明

适配器中的协议部分一般是由公共组件完成。在这种结构中,存储也被认为是一类客户。其存取服务在DDD是用资源库的方式实现。核心域也是通过适配器来与这个客户打交道的(即领域服务如果发布事件也要经过适配器来转发,即图上的颜色区域)。

六边形架构的边界是外六边形,在两个六边形之间应该有一个适配转发器的设计,来自动路由用户的请求到合适的适配器上,再由适配器请求应用程序。同时在适配器和应用程序之间存在一个职责交接的过程。我们也可以换一种图形来表述六边形架构:

3.3、CQRS事件驱动

3.3.1、设计原理

这种架构模式会带来系统的复杂性和基础依赖,但同时也能解决数据显示的复杂性问题,CQRS架构比较适合异构数据和需要读写分离的应用。概要设计如下图所示:

3.3.2、CQRS架构特殊说明

CQRS中存在两种模型,在代码实现时会把除了getById()以外的所有查询方法从原来的查询接口中分离出去;

  • 查询模型:它不是领域模型的一部分只用于显示,设计查询模型时需要注意的是视图的个数;通常会在处理器中内置一个查询过滤器的功能用于减少视图的个数;在查询 时不能直接或间接是修改对象的状态;
  • 命令处理器:专门负责更新对象的状态,当命令执行结束后,实例被更新同时必须发布一个领域事件更新查询模型。详细设计如下图所示:

四、工程设计

有了以上设计后,我们的源码目录一般也要做出相应调整,这一步非常重要因为会涉及到多人开发、打包、发布部署等工作,尤其在跨国时显的会尤为重要,本章是笔者在原来一家公司的落地经验可参考。     模块的设计体现在包路径的结构上,需要和具体的架构结合来设计,比如采用DDD设计,那么DDD从大的方面来讲就是三层:应用服务、领域服务、领域;这就是一层设计。而域内的服务、聚合、实体等可称为二级设计。如果和DDD结合那么建议模块由:

  • 规范:固定顶级  + 上下文名称 + 1级层次(domain|[application/port.adapter]|repository) + [模块] + 2级层次(根据架构来设计service|model|event)
  • 例子:com.xxx   + refund + domain + submodule + service ,com.xxx.refund.domain.service,com.xxx.refund.domain.flowlog.service;

注意事项

  • 不建议用通用的后缀名称,通用的后缀有可能也带来噪音和层次调用限制;而是用模块来区分;
  • 第三层比如domain,这里面可能不包含任何代码;

附、清晰架构完整设计

附一张其它大牛的一张设计图

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

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

相关文章

粉末治金液压系统伺服阀控制器

粉末冶金液压系统是一种应用于粉末治金工艺的液压系统。该系统由液压泵、压力调节器、液压缸、液压管道、电气控制系统等组成。 该系统的优点包括: 工艺动作可靠:粉末冶金液压系统能够精确控制压力和流量,保证工艺动作的可靠性。 提高生产…

分布式存储系统中一致性与可用性核心实战

《高并发系统实战派》-- 你值得拥有 文章目录 副本的喜与忧什么是一致性和可用性?一致性与可用性的较量如何有效权衡,提高系统性能和稳定性?带入实际场景场景案例CAP BASE 双轮指导CAP指导BASE指导 副本的喜与忧 我们要知道,无…

CSDN竞赛68期题解

总结 近几期的题目质量有所提升,数据范围还是一如既往的没给。对于算法题,给定详细的数据范围,规范输入输出,再多给出几个样例以及样例说明,参赛的体验感才会提升。 题目列表 1.小球游戏 题目描述 某台有10个小球的…

[Python] Pylance 插件打开 Python 的类型检查

安装 Python 插件 2.打开一个 Python 文件 可以看到右下角有一个花括号和 Python 字样,点击花括号(不是 Python 字样)打开类型检查即可:

【问题随记】

ubuntu 14.04源更新(sources.list) deb http://mirrors.aliyun.com/ubuntu/ trusty main restricted universe multiverse deb http://mirrors.aliyun.com/ubuntu/ trusty-security main restricted universe multiverse deb http://mirrors.aliyun.com/ubuntu/ trusty-update…

echart图表X轴文字太长被隐藏标签解决方案

在Echart图标中,X轴的标签文字间隔默认是自动计算的,在标签文字长度太长的情况下,有可能标签会被隐藏掉,如图 这种显示显然是不符合严谨的业务需求。以下提供三种解决方案 第一种:竖排显示 效果: 在高度一…

汽车EBSE测试流程分析(四):反思证据及当前问题解决

EBSE专题连载共分为“五个”篇章。此文为该连载系列的“第四”篇章,在之前的“篇章(三)”中已经结合具体研究实践阐述了“步骤二,通过系统调研确定改进方案”等内容。那么,在本篇章(四)中&#…

web爬虫第五弹 - JS逆向入门(猿人学第一题)

0- 前言 爬虫是一门需要实战的学问。 而对于初学者来说,要想学好反爬,js逆向则是敲门砖。今天给大家带来一个js逆向入门实例,接下来我们一步一步来感受下入门的逆向是什么样的。该案例选自猿人学练习题。猿人学第一题 1- 拿到需求 进入页面…

据说这是最全的,App自动化测试思路总结,从0到1实施...

目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 1、编程语言选择 …

Open3d——根据距离参数给点云上渐变色

找了半天网上都没有开源的根据距离进行点云渐变色上色的代码,所以写一个方便自己和大家的使用~ 渐变色生成代码 输入点云shape为[N,3],我这里使用的是nuScenes数据集,生成的点云使用到中心点的距离作为参数,进行渐变,…

XML(eXtensible Markup Language)

目录 为什么需要XML? 一 XML语法 1.文档声明 2.元素 语法: 3.属性 4.注释 5.CDATA节 二 树结构 三 转义字符 四 DOM4J 1.XML解析技术 2.dom4j介绍 3.dom4j基本使用 XML 指可扩展标记语言(eXtensible Markup Language)。 XML 被设计用来传…

SQL-每日一题【1179. 重新格式化部门表】

题目 部门表 Department: 编写一个 SQL 查询来重新格式化表,使得新的表中有一个部门 id 列和一些对应 每个月 的收入(revenue)列。 查询结果格式如下面的示例所示: 解题思路 1.题目要求我们重新格式化表,…

leetcode 1480.一维数组的动态和

⭐️ 题目描述 🌟 leetcode链接:一维数组的动态和 ps: 动态数组求和其实就是当前 i 位置的值等于 0 - i 的求和,控制好循环条件即可。 代码: /*** Note: The returned array must be malloced, assume caller calls…

4000字,详解数据管理之简介篇

DAMA-DMBOK 2.0既 DAMA 数据管理知识体系指南共分为17章,是从事数据治理人员的参考宝典。也CDMP及CDGA、CDGP认证的考试用书。 我在这里将17个章节根据个人理解分为数据管理简介、数据管理框架、数据处理伦理、数据管理组件、数据管理组织、大数据与数据科学和数据…

阿里云容器服务助力极氪荣获 FinOps 先锋实践者

作者:海迩 可信云评估是中国信息通信研究院下属的云计算服务和软件的专业评估体系,自 2013 年起历经十年发展,可信云服务评估体系已日臻成熟,成为政府支撑、行业规范、用户选型的重要参考。 2022 年 5 月国务院国资委制定印发《…

FTP可能是免费且易于使用,但这就是问题所在

当团队里的某个人发现他们需要马上发送的文件太大,无法通过电子邮件发送时,就会陷入困境。另一个同事开始用电子邮件发送账号或密码,然后意识到,也许电子邮件不够安全,FTP替代,托管文件传输。 FTP可能是免费…

线扫激光算法原理

一:线扫激光算法原理 激光器发出的激光束经准直聚焦后垂直入射到物体表面上,表面的散射光由接收透镜成像于探测器的阵列上。光敏面于接收透镜的光轴垂直。如图: 当被测物体表面移动x,反应到光敏面上像点位移为x’。a为接收透镜到物体的距离(物距),b为接收后主面到成像…

HCIE-Security 安全策略技术——流量处理

一、防火墙安全策略原理及配置 1.包过滤技术 对需要转发的数据包,先获取包头信息,然后和设定的规则进行比较,根据比较结果对数据包进行转发和丢弃 2.包过滤技术进阶——安全策略 包过滤:五元组,ACL 安全策略&#…

主动带宽控制工具

停机和带宽过度使用是任何组织都无法避免的两个问题。随着企业采用 BYOD 文化,通过网络的流量负载可能很重,导致网络拥塞并使网络容易受到网络攻击。为了解决这个问题,企业需要全面的监控策略来保护网络,当看似大量的流量进入网络…

通过MySQL删除Hive元数据信息

之前遇到过一个问题,在进行Hive的元数据采集时,因为Hive表的文件已经被删除了,当时是无法删除表,导致元数据采集也发生了问题,所以希望通过删除Hive表的元数据解决上述问题。 之前安装时,经过特定的配置后…