Clean Code/代码简洁性Good-Practice:使用统一异常来取代错误处理

news/2025/9/18 23:28:30/文章来源:https://www.cnblogs.com/buguge/p/19099921

Clean Code/代码简洁性Good-Practice:使用统一异常来取代错误处理

通过自定义异常集中处理,将繁琐的参数校验代码转化为清晰、简洁且可维护的艺术。


在Java开发中,参数校验、业务校验等错误情况处理是保证程序健壮性和数据完整性的第一道防线。我们常常会看到代码中充斥着大量的 if条件判断语句来进行参数校验,每个校验逻辑后通常还伴随着类似的错误处理和日志记录。这种重复不仅使代码变得臃肿冗长,还极大地降低了可读性和可维护性。

本文将以一个具体的参数校验代码改造为例,探讨如何利用统一异常处理机制,显著提升代码的简洁性与优雅度。

一、原始代码:冗余的校验与重复的处理

观察改造前的代码,我们发现每个参数校验都遵循着相同的模式:

if (ObjectUtils.isEmpty(funCode)) {log.info("商户API前置请求参数错误返回【接口编码为空】,reqId={}", reqId);resMap.setResCode(Constant.ERROR_6001);resMap.setResMsg("【参数错误】接口编码为空");response.getWriter().write(JsonUtils.toJson(resMap));return;
}if (isReqOverLimit(merId, funCode)) {log.info("商户API前置请求,接口次数超限!接口={},商户号={},reqId={}", funCodeEnum.name(), merId, reqId);resMap.setResCode(Constant.ERROR_6042);resMap.setResMsg(Constant.ERROR_MSG_6042);response.getWriter().write(JsonUtils.toJson(resMap));return;
}// ... 其他多个类似的参数校验块

这种传统处理方式存在几个明显问题

  1. 代码重复严重:相同的错误码设置、响应写入和日志记录逻辑在每个条件判断中重复出现。
  2. 关注点混淆:业务逻辑(参数校验)与技术细节(响应构建、日志记录)紧密耦合。
  3. 可维护性差:如果需要修改错误响应格式或日志记录方式,必须修改多处代码,容易遗漏且繁琐。

这种代码结构违反了 DRY(Don't Repeat Yourself)原则,是代码优化中首要解决的问题。

二、改造方案:统一异常处理的威力

改造的核心思想是:将参数校验失败视为一种异常情况,通过抛出特定的异常来中断正常流程,并在一处集中处理这些异常

1. 改造校验逻辑——抛出异常

将原有的 if 条件判断改为抛出异常,代码立刻变得清晰简洁:

try {String funCode = requestMessage.getFunCode();if (ObjectUtils.isEmpty(funCode)) {throw BizException.build(Constant.ERROR_6001, "【参数错误】接口编码为空");}if (ObjectUtils.isEmpty(requestMessage.getReqData())) {throw BizException.build(Constant.ERROR_6001, "【参数错误】请求数据为空");}String merId = requestMessage.getMerId();if (ObjectUtils.isEmpty(merId)) {throw BizException.build(Constant.ERROR_6001, "【参数错误】商户号为空");}if (ObjectUtils.isEmpty(requestMessage.getVersion())) {throw BizException.build(Constant.ERROR_6001, "【参数错误】版本信息为空");}if (ObjectUtils.isEmpty(requestMessage.getSign())) {throw BizException.build(Constant.ERROR_6001, "【参数错误】签名为空");}if (isReqOverLimit(merId, funCode)) {log.info("商户API前置请求,接口次数超限!接口={},商户号={},reqId={}", funCodeEnum.name(), merId, reqId);throw BizException.build(Constant.ERROR_6042, Constant.ERROR_MSG_6042);}// ... 其他多个类似的参数校验块} catch (BizException e) {log.error("商户API前置请求业务失败,reqId={},{}-{}", reqId, e.getCode(), e.getMessage());resMap.setResCode(e.getCode());resMap.setResMsg(e.getMessage());response.getWriter().write(JsonUtils.toJson(resMap));return;
}

2. 自定义业务异常

BizException是一个简单的业务异常类,封装错误码和错误信息:

public class BizException extends RuntimeException {@Getterprivate String code;private BizException(String code, String message) {super(message);this.code = code;}public static BizException build(String code, String message) {return new BizException(code, message);}
}

这样改造的主要优势

  • 校验逻辑纯净了if 语句只关心检查条件并抛出异常,职责单一。
  • 消除了重复代码:错误处理逻辑只在一处(catch 块)实现,符合DRY原则。
  • 代码可读性提高:业务主线更加清晰,不会被大量的错误处理代码所淹没。

三、为何这样能提升代码简洁性?

  1. 遵守 DRY 原则(Don't Repeat Yourself):通过将重复的错误处理逻辑抽取到一处(自定义异常),消除了代码冗余。
  2. 关注点分离(Separation of Concerns):业务代码只关注是否校验通过,异常处理则专注如何应对校验失败。这种分离使代码结构更清晰,更易于理解和维护。
  3. 使用异常控制流程:对于像参数错误这类"异常"情况,利用 Java 的异常机制来中断当前流程是更自然、更清晰的做法,避免了多层嵌套的 if-else 语句。
  4. 提升可读性:代码的主干逻辑(校验通过后要做什么)变得更加突出,不会被大量的错误处理代码所淹没。

四、总结

通过统一异常处理自定义异常机制,我们能够将参数校验这类重复且繁琐的代码转化为清晰、简洁且易于维护的形式。

关键的优化步骤包括

  1. 定义代表业务错误的自定义异常。
  2. 将分散的校验失败处理改为抛出异常。
  3. 在一处集中捕获和处理这些异常,构造响应并记录日志。

这种优化不仅减少了代码量,更大幅提升了代码的可读性、可维护性和健壮性,是迈向高质量Java代码的重要一步。这种基于纯Java语言的简单而有效的改造,无需依赖特定框架,在任何Java项目中都能立即应用并带来收益。

感谢阅读!希望本文提供的思路和示例能对您编写clean code有所启发。

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

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

相关文章

U3D动作游戏开发读书笔记--3.1 物理系统详解(上)

第三章 物理系统详解 3.1 物理系统的基本梳理 3.1.1 系统参数设置 了解物理配置:打开Project Settings设置Gravity:重力,常用范围是60~80 Queries Hit Backfaces :进行背面查询,如果需要查询MeshCollider背面的情…

一个联名款电子产品的技术实现和诞生

@目录项目核心亮点(“老年人”非得在地上穿梭也行,恐高嘛)核心技术(技术实现,欢迎各抒己见)市场分析基础核心创新点 项目核心亮点(“老年人”非得在地上穿梭也行,恐高嘛) 欢迎各位青少年小伙伴参与评论互动,…

US$198 Auxiliary Heater Diagnostic Unit for Eberspacher 12V/24V Systems

Auxiliary Heater Diagnostic Unit for Eberspacher 12V/24V SystemsAuxiliary Heater Diagnostic Unit Function:Read out errors from the control boxPerform diagnosis on installed heaterSwitch on heater direc…

JOISC

JOISC开坑。

20250918 之所思 - 人生如梦

20250918 之所思为了改善专注力,到网上找了不少方法,按照教程学习了冥想,但可能是境界不够,效果一直不太好,容易分心,注意力拉不回来,挺沮丧;昨天试验了番茄钟,开始一个任务,接着开始倒计时,发现注意力非常…

初赛知识点复盘

前言 作者觉得自己太菜了,就开始复盘初赛知识点了 接下来是CSP-S/J,虽然在HN很容易进复赛但是还是稳健一点 正文 1.计算机内部结构1.冯诺依曼计算机结构,分为 输入设备,存储器,输出设备,运算器,控制器,其中1.运…

WPF使用Cef加载Vue3页面问题

在WPF中使用CefSharp时遇到两个问题:1.Vue3中使用Ant Design Vue时,table不显示数据 由于之前的老项目用的Vue2框架,数据接口是一样的,页面的功能是差不多的,就把table的columns复制了过来,结果显示不出字段; 数…

curl与wget

wget 和 curl 不是替代关系,而是互补工具。wget 更“傻瓜式”,curl 更“灵活”。 但是curl 支持 40+ 协议,是 API 调试、RESTful 接口测试 的首选工具。HTTP 方法与 API 调用(curl 强项) curl 无法原生实现递归下载…

用 Go 语言与 Tesseract OCR 实现英文数字验证码识别

Go 语言本身不直接支持图像识别,但可以通过调用 Tesseract OCR 引擎来进行图像识别。我们可以使用 Go 的 tesseract 包来实现这一功能。 一、安装与配置 安装 Tesseract OCR 首先,你需要在系统中安装 Tesseract OCR。…

lc1031-两个非重叠子数组的最大和

难度:中等(中期)题目描述给定一个数组和两个长度,找到两个符合长度的不重合的连续子数组,使其和最大示例 输入:nums = [0,6,5,2,2,5,1,9,4], firstLen = 1, secondLen = 2 输出:20 解释:[6, 5] + [9]输入:num…

Segment Analytics-iOS SDK - 专业用户行为追踪解决方案

Segment Analytics-iOS SDK 是一个专业的iOS用户行为分析库,提供完整的事件追踪、用户识别、屏幕浏览统计等功能,支持多种数据集成方式,帮助开发者高效收集和分析用户行为数据。Segment Analytics-iOS SDK Analytic…

我对 WPF 动摇时的选择:.NET Framework 4.6.2+WPF+Islands+UWP+CompostionApi - 行人-

我使用佳能相机,以60FPS高帧率录制视频,来比对 WPF 和 UWP 的动画流畅度,结果: WPF表现吃力和卡顿,UWP表现丝滑和高级。文章是我对.NET Framework 4.6.2框架下的动画方案的选型进行的一些探索和记录。NET Framewo…

US$1198 Xhorse VVDI2 BMW Version With Basic+BMW OBD+BMW CAS4+BMW FEM/BDC

100% Original Xhorse BMW Version With Basic+BMW OBD+BMW CAS4+BMW FEM/BDCThis VVDI2 with Activated Software List:VB-01 BMW OBDVB-02 BMW CAS4VB-03 FEM/BDC FunctionVP-01 Porsche immo data toolVJ-01 Passth…

使用 Rust 与 Tesseract OCR 识别英文数字验证码

一、安装与配置 安装 Tesseract OCR Ubuntu: 更多内容访问ttocr.com或联系1436423940 sudo apt-get update sudo apt-get install tesseract-ocr macOS: brew install tesseract Windows: 从 Tesseract 官方 GitHub…

API安全解决方案选型指南:2025年五大关键维度与厂商推荐

API安全解决方案选型指南:2025年五大关键维度与厂商推荐在数字化转型浪潮中,API已成为连接业务与数据的核心枢纽。随着API数量的爆发式增长,安全威胁也日益复杂:影子API无处不在、敏感数据暴露风险加剧、自动化攻击…

别迷茫了!计算机大一新生这样做,四年后远超同龄人 - 编程实战派

本文是一份专为计算机专业大一新生打造的终极学习指南。文章打破迷茫,从心态重置、学习攻略、实践真知、视野规划四大维度,提供切实可行的建议。强调从“被动学习”转向“主动探索”的思维模式,死磕数学、英语、C语…

解决ifconfig命令没有显示ens33 finalshell连接不上虚拟机

停止并关闭NetworkManager systemctl stop NetworkManagersystemctl disable NetworkManager重启网络服务 systemctl start network

CRM管理专业的系统:从数据收集到价值挖掘

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

什么情况下需要用到xargs

它是 find、grep、ls 等输出类命令的“桥梁”,连接“查找”和“执行”​ xargs 核心作用是:将标准输入(stdin)中的数据转换为命令行参数,并传递给其他命令执行。 总结:当你需要把“文本流”变成“命令参数”时,…