当前位置: 首页 > news >正文

让开发回归简单模式-组件封装

        对于工作年限不长的程序员来说,知识储备是非常关键的。在开发中各种技术的应用已经非常普遍了,例如常见的各种ORM,各种中间件如Redis,MQ等等,又如WebApi路由配置等等,对于常常做开发的程序员来说,都是小事,我们就从小事说起。

        在微服务中,常用到MQ作为微服务之间通讯的桥梁,以RabbitMQ为例,其转发的方式有direct、fanout、topic,而在微服务中的应用,几乎不会使用direct这种交换模式。对于程序员来说,具体使用哪一种交换模式,需要开发时候双方去协商和沟通通讯的数据结构,还要处理通讯过程出现异常的情况,这样下来,从发送和校验到接收和处理,一系列下来,代码少说也有一百几十行,还要话费沟通成本,还需要程序员对mq的掌握。对于组织开发者来说,就是一大堆的培训工作,不培训就要花费时间成本。

        fanout这种交换模式,就如大喇叭,发出去的消息,只要愿意,都能够接收到,是一种比较开放的消息发布模式。例如一个员工的基础信息发生了改变,其他微服务需要更新这个员工的显示信息,那么都来接收就好了,至于接收到怎么处理,那是接收方的事情了,只要接收成功,回应一个ack信号就可以了。

        topic这种交换模式,是具有指定性的,只有匹配到topic字符串的接收方,才能收到消息,就向路由一样。例如做一个系统的内部通知消息,要通知到岗位或者个人,可以使用通配符:

#   匹配多个多个单词,例如message.pos1.emp1 使用message.# 所有消息都能成功匹配上;

*    匹配单个单词,例如message.pos1.* 在pos1下的所有人都能收到这个消息。

        程序员是否需要了解这些?我感觉不需要,我们把发送消息封装成一组类,一个是用于发送,一个是用于接收,例如:

        生产者接口

public interface MQProducer
{void Publish<T>(T body);}

         消费者接口

public interface MQConsumer
{//使用topic订阅消息void Consume(QueueDeclare queue, string topic,Action<string> action);//使用fanout订阅消息void Consume(QueueDeclare queue,Action<string> action);
}

上述方法,只要稍微了解MQ的,都知道这么封装,在微服务中的消息传递相对比较简单的,可以进一步封装。生产者这一端,可以使用AOP方法制作一个发布消息的标签,例如:

public class SaleSerivce : ServiceBase<SaleHdr,SaleDtl>
{//当成功保存单据后,当前微服务ID为AppId,以Sale为资源,SaveBill为action标记发送SaleHdr对象[MQPublish]public RValue<SaleHdr> SaveBill(SaleHdr hdr,List<SaleDtl> dtls){}//这里解释一下RValue<T>这个结构//当方法体出现异常,RValue<T>接收Exception对象,并设置Success=false;//当方法体返回字符串,RValue<T>.Message接收字符串值,并设置Success=false;//当方法体返回SaleHdr对象,RValue<T>.Value接收对象,并设置Success=true;//MQPublish标签,在Success==true时候把SaleHdr对象包装成一个标准的通讯数据格式后,转成json发送出去
}

        接收端就有点复杂了,对不同交换方式,要开发一套对应的数据接收和转发机制。 首先,接收到的消息,否存到一个消息对象中,然后塞到一个Queue对象中,只要向Queue中加元素,则触发出队列的方法,直到读取Queue完成才终止。

       

public class PurService : SeriveBase<PurHdr,PurDtl>
{[MQConsume("saleApp","sale","savebill")] //appid,resource,actionpublic RValue<PurHdr> MQSaleSave(SaleHdr saleHdr){//当新建销售单的时候,采购查询一下是否需要补货}
}

建立一个MQStarter来订阅MQ消息,并根据MQConsume标签上的参数,匹配到方法,可能会匹配到多个方法,没有关系,通通调用一次就可以了。如果RValue<PurHdr>.Success==false ,则做日志,并把消息方到另外一个容器中,允许重试规定次数后再手动重发。

        上述生产者和订阅者,都没有接触到MQ的具体对象和相关代码,只用了两个标签就完成了两个微服务之间的数据交互,只要框架的开发者能够在这个封装中充分考虑到各种情况和处理好各种异常,那么对于程序员来讲是非常轻松的事情,不用考虑通讯协议、结构、方法等等,集中精力编写业务逻辑代码。即使出现通讯问题,只需要反馈就可以了,让开发回归到本质。

        在微服务中,用得最多的就是httpClient、redis这两个组件。

        HttpClient可以根据封装好的WebApi标准接口进行封装,程序员只需要直接调用方法和给参数就可以完成api调用且方便处理好api返回值,转换成所需要的数据结构。

        Redis同理,可以封装成MemoryCache这样的操作方式,分别多String,Hash等数据结构操作。

        为了然程序员最大程度减少对技术依赖,把一些常用或者复杂的工作进行封装,转化为简单的操作方式,例如ORM,特别是使用EF的,往往需要程序员开发时候直接操作EF读写数据,带来的问题,往往没有处理读写时候的异常,导致程序在特定情况下卡死或者报错。这里建议把ORM用一层数据访问层包起来,而这个ORM对象只是一个protected层级的,把常规的读写操作都封装成方法,派生出来的对象,都是使用方法,而不使用ORM对象。即使那天把ORM换掉了,对原来的程序也没有一点影响,例如原来程序使用mysql,后面发现结构很简单,用mongo可能更合适,只要改变一下数据层的实现类就可以了,一般数据层都是注入到系统的,对于部署来说,就只是换了一个dll文件,对于程序员来说,几乎没有影响,除非操作了ORM。

        程序员连最基本的数据库操作对象都不需要了解,甚至可以不知道用了哪种ORM,程序员就纯粹写业务逻辑,可以把业务中的各种复杂情况都考虑仔细。让程序开发真正回归简单化。

        这样带来一个问题,非常不利于程序员的成长,这个就需要程序员在工作过程中注意细节、更多思考,从别人的案例中学习技术技巧,多尝试,转变成真正自己的知识。

        在我的框架中,把事务处理也封装成一个标签,这个是参照java中的写法,只是加了更多自己的想法,把事务嵌套、分布式事务都考虑进去了,例如:

        

[Transaction]  //事务标签,若当前没有在事务中,则发起事务,否则这个标签相当于透明
publice RValue<StoreInHdr> SaveStoreIn(StoreHdr,List<StoreDtl> dtls)
{//这里要处理进仓的操作,同时发起分布式事务标记到货单和采购单//完成库存的更新
}

这样让程序员完全不用考虑事务过程的处理,至于是提交还是回滚,那就看RValue的返回值。

        对于企业来说,用人是一个很大的风险,找水平高的,不愿意带人,写的代码一般程序员还不一定能看懂,自己还有自己的一套风格,换个人维护就很难了。找水平低的,又不按规则来,考虑问题不仔细,会出很多乱子。通过封装,除了简化了开发难度,也制定了开发规则,使用统一标准,有利于项目的持久迭代和发展。

相关文章:

让开发回归简单模式-组件封装

对于工作年限不长的程序员来说&#xff0c;知识储备是非常关键的。在开发中各种技术的应用已经非常普遍了&#xff0c;例如常见的各种ORM,各种中间件如Redis&#xff0c;MQ等等&#xff0c;又如WebApi路由配置等等&#xff0c;对于常常做开发的程序员来说&#xff0c;都是小事&…...

LED显示屏安全亮度参数设置方法和防护

随着LED显示屏应用领域越来越广&#xff0c;但其高亮度造成的光污染&#xff0c;常受到的人们的诟病。为了更好的避免光污染&#xff0c;我整理了一些关于LED显示安全亮度参数设置方法和安全防护措施。你知道LED广告牌是如何工作的吗&#xff1f; 设置LED显示屏的安全亮度参数和…...

数据库sql--关于计算方圆5公里点位编写

当我们计算两个地球上任意两点之间的距离时&#xff0c;可以使用Haversine公式。 下面是每个函数和数值的详细解释&#xff1a; RADIANS(target_latitude)&#xff1a;将目标纬度值转换为弧度制。这是因为Haversine公式以弧度为单位计算角度。RADIANS(latitude)&#xff1a;将…...

嵌入式基础知识-DMA

本篇来介绍DMA的一些基础知识。 1 DMA简介 DMA&#xff08;Direct Memory Access&#xff09;,中文名为直接内存访问&#xff0c;它是一些计算机总线架构提供的功能&#xff0c;能使数据从附加设备&#xff08;如磁盘驱动器&#xff09;直接发送到计算机主板的内存上。对应嵌…...

STM32 软件IIC 控制OLED 显示屏

1. 硬件IIC 实在是太难用了&#xff0c;各种卡死&#xff0c;各种发不出来数据&#xff0c;没那么多时间折腾了&#xff0c;还是用软件IIC 先吧&#xff0c;初始化 void OLED_Software_IIC_Init(void) {GPIO_InitTypeDef GPIO_InitStruct;RCC_AHBPeriphClockCmd(OLED_SOFTWARE…...

【系统设计系列】 DNS和CDN

系统设计系列初衷 System Design Primer&#xff1a; 英文文档 GitHub - donnemartin/system-design-primer: Learn how to design large-scale systems. Prep for the system design interview. Includes Anki flashcards. 中文版&#xff1a; https://github.com/donnemarti…...

thinkphp中使用Elasticsearch 7.0进行多表的搜索

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、thinkphp中使用Elasticsearch 7.0进行多表的搜索二、使用步骤1.引入库2.读入数据 总结 前言 提示&#xff1a;thinkphp中使用Elasticsearch 7.0进行多表的…...

说说 TCP的粘包、拆包

分析&回答 拆包和粘包是在socket编程中经常出现的情况&#xff0c; 在socket通讯过程中&#xff0c;如果通讯的一端一次性连续发送多条数据包&#xff0c;tcp协议会将多个数据包打包成一个tcp报文发送出去&#xff0c;这就是所谓的粘包。如果通讯的一端发送的数据包超过一…...

PowerToys安装

PowerToys 是微软开发者开发的免费实用工具集&#xff0c;可以用于高级用户调整和简化 Windows 操作&#xff0c;以提高效率。 官网安装方法&#xff1a; https://learn.microsoft.com/zh-cn/windows/powertoys/install 目前安装文件路径&#xff1a; https://github.com/m…...

Unity——LitJSON的安装

一、LitJSON介绍 特点 LitJSON是一个轻量级的C# JSON库&#xff0c;用于在Unity游戏开发中进行JSON数据的序列化和反序列化操作。它提供了简单而高效的接口&#xff0c;帮助开发者处理JSON数据。 以下是LitJSON库的一些主要特点和功能&#xff1a; 1. 高性能&#xff1a;Lit…...

YOLOv5:对yolov5n模型进一步剪枝压缩

YOLOv5&#xff1a;对yolov5n模型进一步剪枝压缩 前言前提条件相关介绍具体步骤修改yolov5n.yaml配置文件单通道数据&#xff08;黑白图片&#xff09;修改models/yolo.py文件修改train.py文件 剪枝后模型大小 参考 前言 由于本人水平有限&#xff0c;难免出现错漏&#xff0c;…...

大数据(八):Pandas的基础应用详解(五)

专栏介绍 结合自身经验和内部资料总结的Python教程,每天3-5章,最短1个月就能全方位的完成Python的学习并进行实战开发,学完了定能成为大佬!加油吧!卷起来! 全部文章请访问专栏:《Python全栈教程(0基础)》 再推荐一下最近热更的:《大厂测试高频面试题详解》 该专栏对…...

【算法】归并排序 详解

归并排序 详解 归并排序代码实现1. 递归版本2. 非递归版本 排序&#xff1a; 排序&#xff0c;就是使一串记录&#xff0c;按照其中的某个或某些关键字的大小&#xff0c;递增或递减的排列起来的操作。 稳定性&#xff1a; 假定在待排序的记录序列中&#xff0c;存在多个具有相…...

linux 进程隔离Namespace 学习

一、linux namespace 介绍 1.1、概念 Linux Namespace是Linux内核提供的一种机制&#xff0c;它用于隔离不同进程的资源视图&#xff0c;使得每个进程都拥有独立的资源空间&#xff0c;从而实现进程之间的隔离和资源管理。 Linux Namespace的设计目标是为了解决多个进程之间…...

【MySQL】事务 详解

事务 详解 一. 为什么使用事务二. 事务的概念三. 使用四. 事务的特性原子性&#xff08;Atomicity&#xff09;一致性&#xff08;Consistency&#xff09;隔离性&#xff08;Isolation&#xff09;持久性&#xff08;Durability&#xff09; 五. 事务并发所带来的问题脏读问题…...

爬虫到底难在哪里?

目录 爬虫到底难在哪里 怎么学习爬虫 注意事项 爬虫工具 总结 学习Python爬虫的难易程度因人而异&#xff0c;对于具备编程基础的人来说&#xff0c;学习Python爬虫并不困难。Python语言本身比较简单易学&#xff0c;适合初学者使用。 爬虫到底难在哪里 爬虫的难点主要包…...

linux常用命令行整理

1、linux的以及目录 bin 二进制可执行文件sbin 二进制可执行文件(root用户权限)etc 系统管理和配置文件,例如常见host文件home 用户文件的根目录usr 用户存放系统应用程序(共享系统资源)opt 可选的应用程序proc 虚拟文件系统root 超级用户dev 存放设备文件mnt 系统管理员安装临…...

python字符串相关

python字符串相关 一、reverse() 函数 只能反转 列表二、reversed() 反转元组字符串等等 返回迭代器三、join和reversed反转字符串四、join串联字符串&#xff08;join连接对象仅限字符串、储存字符串的元组、列表、字典&#xff09;数字对象可通过str()转化为字符串⭐对象为字…...

JavaScript学习笔记01

JavaScript笔记01 什么是 JavaScript JavaScript 是一门世界上最流行的脚本语言&#xff0c;它是一种弱类型的脚本语言&#xff0c;其代码不需要经过编译&#xff0c;而是由浏览器解释运行&#xff0c;用于控制网页的行为。 发展历史 参考&#xff1a;JavaScript的起源故事…...

golang 通用的 grpc http 基础开发框架

go-moda golang 通用的 grpc http 基础开发框架仓库地址: https://github.com/webws/go-moda仓库一直在更新,欢迎大家吐槽和指点 特性 transport: 集成 http&#xff08;echo、gin&#xff09;和 grpc。tracing: openTelemetry 实现微务链路追踪pprof: 分析性能config: 通用…...

CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型

CVPR 2025 | MIMO&#xff1a;支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题&#xff1a;MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者&#xff1a;Yanyuan Chen, Dexuan Xu, Yu Hu…...

实现弹窗随键盘上移居中

实现弹窗随键盘上移的核心思路 在Android中&#xff0c;可以通过监听键盘的显示和隐藏事件&#xff0c;动态调整弹窗的位置。关键点在于获取键盘高度&#xff0c;并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...

视觉slam十四讲实践部分记录——ch2、ch3

ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...

JavaScript 数据类型详解

JavaScript 数据类型详解 JavaScript 数据类型分为 原始类型&#xff08;Primitive&#xff09; 和 对象类型&#xff08;Object&#xff09; 两大类&#xff0c;共 8 种&#xff08;ES11&#xff09;&#xff1a; 一、原始类型&#xff08;7种&#xff09; 1. undefined 定…...

uniapp 小程序 学习(一)

利用Hbuilder 创建项目 运行到内置浏览器看效果 下载微信小程序 安装到Hbuilder 下载地址 &#xff1a;开发者工具默认安装 设置服务端口号 在Hbuilder中设置微信小程序 配置 找到运行设置&#xff0c;将微信开发者工具放入到Hbuilder中&#xff0c; 打开后出现 如下 bug 解…...

es6+和css3新增的特性有哪些

一&#xff1a;ECMAScript 新特性&#xff08;ES6&#xff09; ES6 (2015) - 革命性更新 1&#xff0c;记住的方法&#xff0c;从一个方法里面用到了哪些技术 1&#xff0c;let /const块级作用域声明2&#xff0c;**默认参数**&#xff1a;函数参数可以设置默认值。3&#x…...

医疗AI模型可解释性编程研究:基于SHAP、LIME与Anchor

1 医疗树模型与可解释人工智能基础 医疗领域的人工智能应用正迅速从理论研究转向临床实践,在这一过程中,模型可解释性已成为确保AI系统被医疗专业人员接受和信任的关键因素。基于树模型的集成算法(如RandomForest、XGBoost、LightGBM)因其卓越的预测性能和相对良好的解释性…...

LangChain【6】之输出解析器:结构化LLM响应的关键工具

文章目录 一 LangChain输出解析器概述1.1 什么是输出解析器&#xff1f;1.2 主要功能与工作原理1.3 常用解析器类型 二 主要输出解析器类型2.1 Pydantic/Json输出解析器2.2 结构化输出解析器2.3 列表解析器2.4 日期解析器2.5 Json输出解析器2.6 xml输出解析器 三 高级使用技巧3…...

PostgreSQL 与 SQL 基础:为 Fast API 打下数据基础

在构建任何动态、数据驱动的Web API时&#xff0c;一个稳定高效的数据存储方案是不可或缺的。对于使用Python FastAPI的开发者来说&#xff0c;深入理解关系型数据库的工作原理、掌握SQL这门与数据库“对话”的语言&#xff0c;以及学会如何在Python中操作数据库&#xff0c;是…...

Qt 按钮类控件(Push Button 与 Radio Button)(1)

文章目录 Push Button前提概要API接口给按钮添加图标给按钮添加快捷键 Radio ButtonAPI接口性别选择 Push Button&#xff08;鼠标点击不放连续移动快捷键&#xff09; Radio Button Push Button 前提概要 1. 之前文章中所提到的各种跟QWidget有关的各种属性/函数/方法&#…...