首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Clean Code系列之异常处理

Clean Code系列之异常处理

作者头像
码农戏码
发布于 2022-11-18 01:43:59
发布于 2022-11-18 01:43:59
44200
代码可运行
举报
文章被收录于专栏:DDDDDD
运行总次数:0
代码可运行

先前已经对异常如何设计,如何实践异常都写了几篇阐述了。再一次从Clean Code角度来谈谈异常的使用。

1、使用异常替代返回错误码

为什么?是从函数的角度去考虑:

函数要么做什么事,要么回答什么事,但二者不可得兼。也就是修改某对象状态,或者是返回该对象的有关信息。也就是指令与询问分隔开来

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
boolean set(String attribute,String value);

该函数设置某个指定属性,如果成功,就返回true,如果不存在那个属性,就返回false。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
if(set("website","zhuxingsheng.com")){
    //
}

但从读者角度考虑一下,它是在问websit属性值是否之前已经设置为zhuxingsheng.com,还是在问websit属性值是否成功设置为zhuxingsheng.com呢?从该行语句很难判断其含义,因为set是动词还是形容词并不清楚。

作者本意是,set是一个动词,但在if语句的上下文中,感觉它是一个形容词。该语句读起来像是在说“如果websit属性值之前已经被设置为zhuxingsheng.com”,而不是“设置websit属性值为zhuxingsheng.com,看看是否可行,然后...”。

要解决这个问题,可以将set函数重命名为setAndCheckIfExists,但这对提高if语句的可读性帮助不大。真正的解决方案是把指令与询问分隔开来,防止产生混淆:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
if(attributeExists("website"){
    setAttribute("website","zhuxingsheng.com");
}

在《领域服务是抛出异常还是返回错误码》[1],提到过如何编写返回错误码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
if(deletePage(page)) == OK){

}

但这样,从指令式函数返回错误码,有些违反指令与询问分隔的规则。

虽然这儿没有像上面的示例一样,引起动词与形容词的混淆,却会导致更深层次嵌套结构

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
if(deletePage(page) == OK){
    if(deleteRefrence(page.name) == OK) {
        if (deleteKey(page.name.key()) == OK) {
            //
        } else {
          //  
        }
    } else {
        //
    }
} else {
    //
}

使用异常替代错误码,错误处理代码能从主路径代码中分离出来:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
try {
    deletePage(page);
    deleteRefrence(page.name);
    deleteKey(page.name.key());
} catch (Exception e) {

}

抽离try/catch 代码块

try/catch代码块丑陋不堪,搞乱了代码结构,把错误处理与正常流程结构分离开来。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
void delete(Page page) {
    try {
        deltePageAndAllReferences(page)
    } catch(Exception e) {
        log;
    }
}

正常流程结构:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
void deletePageAndAllReferences(Page page) {
    deletePage(page);
    deleteRefrence(page.name);
    deleteKey(page.name.key());
}

这样子代码干净了些,而且函数只干一件事。错误处理就是一件事。

想要更简化一下try/catch代码块,可以使用vavr工具包中的Try类

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 Try.of((page) -> deltePageAndAllReferences(page)).onFailure(e -> log(e));

写法详情可观看小视频

ErrorCode枚举类

返回的错误码,我们常会使用一个常量类或者枚举定义所有错误码。

当新增逻辑需要增加新错误码时,就会增加新代码,而且还要来修改这个错误码类。

这样的类被称为依赖磁铁,当这个类修改时,其他所有类都需要重新编译和部署。

使用异常类代替错误码,新异常可以从异常类派生出来,而无须重新编译或重新部署。

2、使用未检查异常

在之前的异常文章中,提到检查异常有很强的穿透力,当类调用链路长,在底层方法上增加新检查异常就会导致上层所有方法修改声明,有点违反OCP。

3、异常防腐

在DDD中有防腐层的概念,通过防腐层去隔离两个界限上下文的变化。

异常也有类似的情况。

当调用第三方API时,会需要处理异常情况。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
ThirdPartAPI third = new ThirdPartAPI();

try {
    third.open();
} catch (Third1Exception e) {
    //
} catch (Thrid2Exception e) {
    //
} catch (Third3Exception e) {
    //
} finally {

}

首先我们需要打包这个第三方API,降低对它的依赖;也不必绑死在某一特定供应商API上,定义自己的API还要抽象异常

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class ThirdPartService {
    public void open() {
        try {
            third.open();
        } catch (Third1Exception e) {
            //
            throw new SelfException(e);
        } catch (Thrid2Exception e) {
            //
            throw new SelfException(e);
        } catch (Third3Exception e) {
            //
            throw new SelfException(e);
        } finally {

        }
    }
}

上面代码,定义了抽象的ThirdPartSevice,并且抽象出SelfException。

总结

经过上面的三种手法,可以让代码在处理异常时,更加整洁。

References

[1] 《领域服务是抛出异常还是返回错误码》: https://www.zhuxingsheng.com/blog/does-the-domain-service-throw-an-exception-or-return-an-error-code.html

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-06-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 码农戏码 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
代码整洁之道-读书笔记之函数
一函数理论上只做一件事情,只做一个抽象层次的事情,通俗的说就是看看当前函数是否还可以拆分出一个函数,如果可以说明就不是做一件事
特特
2022/09/30
5020
函数重构之道
以下代码做了好几件事情。它创建缓冲区、获取页面、搜索继承下来的页面、渲染路径、添加神秘的字符串、生产HTML等等。
栋先生
2018/09/29
5070
WebFlux 全局异常处理实战
前后端分离开发,一般提供 REST API,正常返回会有响应体,异常情况下会有对应的错误码响应。
二哥聊运营工具
2021/12/17
2.7K0
WebFlux 全局异常处理实战
Java统一异常处理(配置文件集中化定义)
无论任何项目,都避免不了在运行期间出现的一些异常,并伴随着因业务逻辑的需要而给出相应的提示,使得系统变得更加友好,这类提示处理,我们统称为异常处理(exceptiona handling)。
xcbeyond
2020/04/01
1.4K0
Java统一异常处理(配置文件集中化定义)
优雅地进行全局异常处理、统一返回值封装、自定义异常错误码——Graceful-Response推荐
Graceful Response是一个Spring Boot体系下的优雅响应处理器,提供一站式统一返回值封装、全局异常处理、自定义异常错误码等功能,使用Graceful Response进行web接口开发不仅可以节省大量的时间,还可以提高代码质量,使代码逻辑更清晰。
用户2865443
2023/11/09
3.3K0
代码整洁之道
1.命名规范 1.1.模糊的命名 //代码的模糊度 public List<int[]> getThem(){ List<int[]> list1 = new ArrayList<int[]>(); for (int[] x : theList){ if (x[0] == 4){ list1.add(x); } } return list1; } 疑问: (1) theList中是什么类型? (2) theList
用户9831583
2022/06/16
2840
【c++】c++异常&&c++的异常处理详解
实际中C语言基本都是使用返回错误码的方式处理错误,部分情况下使用终止程序处理非常严重的错误
用户10925563
2024/08/06
4280
【c++】c++异常&&c++的异常处理详解
Python 工匠:异常处理的三个好习惯
花下猫语: Python 工匠系列的文章很棒,它很好地将实战经验与理论融合起来,它的诚意体现在了写作风格、每个话题关注点与代码用例中。今天,继续给大家分享最新的作品(系列之六):
Python猫
2019/04/23
6930
改进异常处理的 6 条建议
来源:ImportNew - 唐尤华 , 合理地使用异常处理可以帮你节省数小时(甚至数天)调试时间。一个乘法异常会毁掉你的晚餐乃至周末计划。如果处置不及时,甚至对你的名誉都会造成影响。一个清晰的异常处理策略可以助你节省诊断、重现和问题纠正时间。下面是6条异常处理建议。 1. 使用一个系统全局异常类 不必为每种异常类型建立单独的类,一个就够了。确保这个异常类继承RuntimeException,这样可以减少类个数并且移除不必要的异常声明。 我知道你正在想什么:如果类型只有一个,那么怎么能知道异常具体是什么
企鹅号小编
2018/01/26
8840
Clean Code系列之DDD分层参数转换
从代码中,可以明显看出这是一段处理登陆请求的方法。在大多数项目中,这种代码很常见。
码农戏码
2022/04/15
9730
Clean Code系列之DDD分层参数转换
C++异常处理机制
实际中C语言基本都是使用返回错误码的方式处理错误,部分情况下使用终止程序处理非常严重的错误。
南桥
2024/09/20
2340
C++异常处理机制
【C++航海王:追寻罗杰的编程之路】异常——错误处理方式之一
在C++编程中,异常处理是一种重要的技术,用于处理程序在运行时可能出现的错误或意外情况。异常是指在程序执行过程中发生的某种不正常的情况,例如除以零、内存访问错误或无效的输入等。传统的错误处理方式通常涉及使用错误代码或返回特殊值来指示问题,但这种方式可能会导致代码混乱、繁琐,并且容易被忽略或处理不当。
枫叶丹
2024/06/04
1950
【C++航海王:追寻罗杰的编程之路】异常——错误处理方式之一
C++异常
1. 终止程序,如assert,缺陷:用户难以接受。如发生内存错误,除0错误时就会终止程序。
ljw695
2024/10/18
2190
C++异常
三个好习惯,帮你写好Python里的异常处理
如果你用 Python 编程,那么你就无法避开异常,因为异常在这门语言里无处不在。打个比方,当你在脚本执行时按 ctrl+c 退出,解释器就会产生一个 KeyboardInterrupt 异常。而 KeyError、 ValueError、 TypeError 等更是日常编程里随处可见的老朋友。
Python数据科学
2019/09/04
1.3K0
三个好习惯,帮你写好Python里的异常处理
Python 工匠: 异常处理的三个好习惯
如果你用 Python 编程,那么你就无法避开异常,因为异常在这门语言里无处不在。打个比方,当你在脚本执行时按 ctrl+c 退出,解释器就会产生一个 KeyboardInterrupt 异常。而 KeyError、 ValueError、 TypeError 等更是日常编程里随处可见的老朋友。
崔庆才
2019/07/16
9870
C++异常
(1)错误码不好设置。比如除0时,我们不好设置这个返回数,因为并不知道返回的是结果还是错误码。
小灵蛇
2024/06/06
2460
C++异常
Java中异常处理的9个最佳实践
在Java中进行处理异常并非是一件容易的事,初学者经常陷入困惑,甚至有经验的开发者也需要认真研讨哪些异常需要处理,哪些异常需要向上抛出。导致每个开发团队都会自己定制一套特有的异常处理规则,这使得新加入团队的成员都经历一段痛苦的适应期。
码农神说
2020/08/05
7270
Java中异常处理的9个最佳实践
C++异常处理深度探索:从基础概念到高级实践策略
在现代编程实践中,异常处理是一项至关重要的技能,特别是在开发复杂和大型系统时。C++作为一种强大而灵活的编程语言,提供了丰富的异常处理机制,使得开发者能够有效地管理运行时错误和异常情况。本文旨在深入探讨C++中的异常处理机制,从基本的语法结构到实际的应用场景,帮助读者掌握这一关键技能。 本文将从C++异常处理的基本概念出发,逐步介绍如何定义和抛出异常、如何捕获和处理异常,以及如何在复杂项目中有效运用异常处理机制。此外,我们还将讨论一些常见的异常处理策略和最佳实践,帮助读者避免常见陷阱,写出更加健壮和可靠的C++代码。
suye
2024/10/24
5260
十三、异常、类型转换和 lambda
C++ 中的异常处理是一种在程序执行期间处理错误或异常情况的机制。它允许程序在遇到错误时,不是立即崩溃或退出,而是以一种优雅的方式处理错误,可能是记录错误信息、释放资源或尝试恢复。
用户11332765
2024/10/28
5000
【c++】异常处理
在C++项目开发中,异常处理(Exception Handling)是确保程序稳定性和可靠性的重要机制。无论是文件读取失败、内存分配错误,还是网络请求超时,程序运行过程中总会遇到各种意外情况。如果没有合理的异常处理,程序可能会崩溃,导致数据丢失或系统故障,严重影响用户体验。通过C++的异常处理机制,开发者可以在错误发生时优雅地捕获并处理异常,避免程序意外终止,同时提供必要的错误信息以便调试和优化。本篇文章,作者将介绍C++的异常处理基础、常见用法及最佳实践,帮助大家构建更健壮的C++应用程序。
ephemerals__
2025/03/22
3340
【c++】异常处理
相关推荐
代码整洁之道-读书笔记之函数
更多 >
交个朋友
加入腾讯云官网粉丝站
蹲全网底价单品 享第一手活动信息
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档