【架构设计】谈谈防腐层的妙用

news2025/6/10 11:37:28

文章目录

  • 前言
  • 一、一个简单的例子
  • 二、防腐层介绍
  • 总结

前言

最近在学习了解领域驱动模型DDD相关的内容,但是由于没有实际的项目支撑,所以大都是停留在一些理论层面。我发现这里面的一些设计思想还是非常有实用价值的,可以直接应用于你目前的项目中,今天我就来谈谈防腐层的妙用。

一、一个简单的例子

大家在做项目中是否有过这样的经历,你的项目中需要调用一个外部服务接口,而这个外部服务接口需要在你的项目中的不同地方被多次使用,比如在公司项目中就出现调用下面获取用户详细信息的外部的接口多达10几次。

SessionUser getUserDetail(String username)SessionUser getUserDetail(String username)

一旦这个外部接口发生变化,那么是不是意味着我就要修改这几十处的地方,简直头大。
那我们是不是可以对外部接口做一层适配封装,隔离这种可能地、不可控的变化。因此在我们的manager层中添加了一个UserManager的类,如下所示:

@Component
public class UserManager() {

    @Autowired
    private UserApi remoteUserApi;

    public UserDTO getUserDetail(String username) {
		SessionUser sessionUser = remoteUserApi.getUserDetail(username);
        UserDTO user = convertUser(sessionUser);
        return user;
    }
}
@Component
public class UserManager() {

    @Autowired
    private UserApi remoteUserApi;

    public UserDTO getUserDetail(String username) {
		SessionUser sessionUser = remoteUserApi.getUserDetail(username);
        UserDTO user = convertUser(sessionUser);
        return user;
    }
}

我们让系统中的业务层从原来直接调用remoteUserApi.getUserDetail(String username)改为调用UserManager#getUserDetail(),这样哪怕有一天外部接口的返回内容、方法名发生变化,我们也只需要修改一下这一个地方,而无需修改上层调用的十几处地方。
另外,我们还可以再这一层加入更多的功能,比如参数校验,日志打印等等,如下代码所示:

@Component
public class UserManager() {

    @Autowired
    private UserApi remoteUserApi;

    public List<UserDTO> getUserDetail(String username) {
        // 参数校验
        if(StrUtils.isBlank(username)) {
            throw new UserException("用户名不能为空")}
        long t1 = System.currentTimeMillis();
		SessionUser sessionUser = remoteUserApi.getUserDetail(username);
        long t2 = System.currentTimeMillis();
        // 打印日志,方便甩锅    
        if(t2 - t1 > 3000L) {
            log.warn("调用外部接口耗时过长,cost:[{}]ms", t2 - t1);
        }
        UserDTO user = convertUser(sessionUser);
        return user;
    }
}
@Component
public class UserManager() {

    @Autowired
    private UserApi remoteUserApi;

    public List<UserDTO> getUserDetail(String username) {
        // 参数校验
        if(StrUtils.isBlank(username)) {
            throw new UserException("用户名不能为空")}
        long t1 = System.currentTimeMillis();
		SessionUser sessionUser = remoteUserApi.getUserDetail(username);
        long t2 = System.currentTimeMillis();
        // 打印日志,方便甩锅    
        if(t2 - t1 > 3000L) {
            log.warn("调用外部接口耗时过长,cost:[{}]ms", t2 - t1);
        }
        UserDTO user = convertUser(sessionUser);
        return user;
    }
}

我们可以加上额外的参数验证,打印调用外部接口的耗时,有理由“甩锅”。

二、防腐层介绍

通过上面一个简单的例子,你是不是对防腐层有了一个初步的认识。通俗的说,我们认为外部系统、接口中间件等都是腐烂的,不可控的,我们需要添加一层去做隔离和防腐,被叫做防腐层。

大多数应用程序依赖于其他系统的某些数据或功能。 例如,旧版应用程序迁移到新式系统时,可能仍需要现有的旧的资源。 新功能必须能够调用旧系统。 逐步迁移尤其如此,随着时间推移,较大型应用程序的不同功能迁移到新式系统中。

这些旧系统通常会出现质量问题,如复杂的数据架构或过时的 API。 旧系统使用的功能和技术可能与新式系统中的功能和技术有很大差异。 若要与旧系统进行互操作,新应用程序可能需要支持过时的基础结构、协议、数据模型、API、或其他不会引入新式应用程序的功能。不仅仅是旧系统,不受开发团队控制的任何外部系统(第三方系统)都可能出现类似的问题,因此引入防腐层去做隔离解决。
在这里插入图片描述

如上图所示,子系统 A 通过防腐层调用子系统 B。子系统 A 与防腐层之间的通信始终使用子系统 A 的数据模型和体系结构。防腐层向子系统 B 发出的调用符合该B子系统的数据模型或方法。 防腐层包含在两个系统之间转换所必需的所有逻辑。 该层可作为应用程序内的组件或作为独立服务实现。

总结

说了那么多,这是不是和设计模式中的适配器模式很像,实际上防腐层也叫适配层。当然写防腐层也是有代价的。最大的代价就是有「额外的开发成本」。所以如果你的上下游比较少,且比较稳定,其实是可以不用防腐层的。但是在大型团队,付出这些额外的开发成本是有价值的,因为大型团队的上下游关系非常复杂,他们可能不是在一个团队,也有可能经常进行迭代升级,通过我自己的经验来看,接口变化是经常会发生的。

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

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

相关文章

基于ssm+mybatis+mysql+jsp机票预定系统

基于ssmmybatismysqljsp机票预定系统 一、系统介绍二、功能展示1.主页2.个人中心3.用户管理(管理员)4.客机管理&#xff08;管理员&#xff09;5.航班管理&#xff08;管理员&#xff09;6.机票管理&#xff08;管理员&#xff09; 三、其它系统四、获取源码 一、系统介绍 系统…

nacos设置服务权重

nacos设置服务权重

飞行动力学 - 第8节-着陆性能 之 基础点摘要

飞行动力学 - 第8节-着陆性能 之 基础点摘要 1. 着陆性能1.1 空中直线段S11.2 拉平段S21.3 地面滑跑段S3 2. 着陆性能改善方法3. 起飞性能列举4. 参考资料 1. 着陆性能 总体距离S S1 S2 S3&#xff0c;越短性能越佳。 1.1 空中直线段S1 1.2 拉平段S2 1.3 地面滑跑段S3 2. 着…

三分钟了解Redis HyperLogLog 数据结构

文章目录 0. 前言1. 原理1.2 原理解析 2.实战案例3. Redis从入门到精通系列文章4. 常见问题4.1. 什么是Redis HyperLogLog&#xff1f;4.2. HyperLogLog算法的核心思想是什么&#xff1f;4.3. HyperLogLog算法的误差率如何控制&#xff1f;4.4. HyperLogLog算法的存储空间大小与…

超图数据集概念学习1

以前写过一些数据源数据集有关的博文&#xff1b;从头学习一下&#xff1b; 数据集是同种类型数据的集合&#xff0c;比如&#xff1a;点数据集、线数据集。根据数据类型的不同&#xff0c;分为矢量数据集、格网数据集和影像数据集&#xff0c;以及为了处理特定问题而设计的如路…

​CentOS防火墙操作命令 ​

CentOS防火墙操作命令 1、查看防火墙服务状态 systemctl status firewalld.service 或者查看防火墙的状态&#xff1a; 1 firewall-cmd --state 2、开启、重启防火墙 启动firewall&#xff1a; 1 systemctl start firewalld.service 设置开机自启或禁用&#xff1a; …

【Ceph】基于ceph-deploy部署Ceph集群详解

基于ceph-deploy部署Ceph集群详解 1. 存储基础1.1 单机存储设备1.1.1 单机存储的问题1.1.2 商业存储解决方案 1.2 分布式存储&#xff08;软件定义的存储SDS&#xff09;1.2.1 分布式存储的类型 2. Ceph简介2.1 Ceph优势2.2 Ceph架构2.2.1 高层应用接口 2.3 Ceph核心组件2.3.1 …

CTFShow-WEB入门篇文件上传详细Wp(151-170)

WEB入门篇--命令执行详细Wp 文件上传&#xff1a;Web151&#xff1a;Web152&#xff1a;Web153&#xff1a;Web154&#xff1a;Web155&#xff1a;Web156&#xff1a;Web157&#xff1a;Web158&#xff1a;Web159&#xff1a;Web160&#xff1a;Web161&#xff1a;Web162&#…

Java:基本数据类型 和 所占大小

目录 java基本程序结构命名注释数据类型 和 大小整数类型浮点char编码boolean 变量常量final 的作用 java基本程序结构 命名 小驼峰&#xff1a;第一个单词小写&#xff0c;后面的单词大写。 大驼峰&#xff1a;每个单词都大写。 变量&#xff0c;方法&#xff1a;小驼峰。 j…

046、TiDB特性_内存悲观锁(了解)

悲观锁 传统悲观锁有两个性能问题&#xff1a; 磁盘io 需要将lock 的信息持久化到 lock CF中&#xff0c;这个时候产生磁盘io网络io 因为每个Region都是多副本&#xff0c;需要将信息通过网络 发送到Follower的lock CF中。 内存悲观锁 为了解决上面两个问题。 就有个内存悲观…

RPC学习笔记

1、Remote Procedure Call RPC的主要目标是让构建分布式更容易&#xff0c;在提供强大的远程调用能力时不损失本地调用的语义简洁性。为实现该目标&#xff0c;RPC框架需要提供一种透明的调用机制&#xff0c;让使用者不必显示的区别本地调用和远程调用。RPC不是一个协议或者方…

CodeArts Check系统规则集还不够?带你体验如何创建、启用自定义规则集

代码检查&#xff08;CodeArts Check&#xff09;是基于云端实现的代码检查服务。建立在多年自动化源代码静态检查技术积累与企业级应用经验的沉淀之上&#xff0c;为用户提供代码风格、通用质量与网络安全风险等丰富的检查能力&#xff0c;提供全面质量报告、便捷闭环处理问题…

BTY生态系统DNS关于DeSoc的构想

2022年5月&#xff0c;以太坊创始人Vitalik Buterin与经济学家Glen Weyl和Flashbots研究员Puja Ohlhaver联合发布了《Decentralized Society: Finding Web3’s Soul》。这篇论文的核心是围绕“Web3灵魂”创造出去中心化社会的可能性。 论文中阐述&#xff0c;当下Web3 更多是表…

Java语言基础

目录 一.代码注释 二.变量与常量 1.标识符 2.关键字 3.变量 4.常量 三.基本数据类型 1.整数类型 2.浮点类型 3.字符类型 1.char型 2.转义字符 4.布尔类型 一.代码注释 在代码中添加注释能提高代码的可读性。注释中包含了程序的信息&#xff0c;可以帮助程序员更…

前端学习——JS进阶 (Day3)

编程思想 面向过程编程 面向对象编程 (oop) 构造函数 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport…

第一阶段-第十章 Python基础的综合案例(数据可视化-折线图可视化)

目录 一、本章的案例介绍  1.可视化案例&#xff08;本章&#xff09;的学习目标  2.需要实现的效果图  3.数据来源 二、json数据格式  1.学习目标  2.什么是json  3. json的作用  4.json的语法要求  5.Python数据和json数据的相互转化&#xff08;dumps转json…

卷积神经网络识别人脸项目—使用百度飞桨ai计算

卷积神经网络识别人脸项目的详细过程 整个项目需要的准备文件&#xff1a; 下载链接&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1WEndfi14EhVh-8Vvt62I_w 提取码&#xff1a;7777 链接&#xff1a;https://pan.baidu.com/s/10weqx3r_zbS5gNEq-xGrzg 提取码&#x…

❤️创意网页:打造简洁美观的网页轮播图(HTML简单实现轮播图)操作简单可以直接使用

✨博主&#xff1a;命运之光 &#x1f338;专栏&#xff1a;Python星辰秘典 &#x1f433;专栏&#xff1a;web开发&#xff08;简单好用又好看&#xff09; ❤️专栏&#xff1a;Java经典程序设计 ☀️博主的其他文章&#xff1a;点击进入博主的主页 前言&#xff1a;欢迎踏入…

MQTT协议在物联网环境中的应用及代码实现解析(一)

MQTT协议全称是Message Queuing Telemetry Transport&#xff0c;翻译过来就是消息队列遥测传输协议&#xff0c;它是物联网常用的应用层协议&#xff0c;运行在TCP/IP中的应用层中&#xff0c;依赖TCP协议&#xff0c;因此它具有非常高的可靠性&#xff0c;同时它是基于TCP协议…

macos使用搭建算法竞赛c/c++的g++/gcc编译环境(homebrew,含万能头,改环境变量,vscode/clion可用)

文章目录 1、homebrew安装2、安装g3、改环境变量 1、homebrew安装 我没改镜像&#xff0c;直接网上脚本一键安装的&#xff0c;具体命令忘了&#xff0c;可能是这个 反正装这个的方法很多&#xff0c;网上一搜都有。 成功装上homebrew就行。 /bin/bash -c "$(curl -fsSL…