代码整洁之道读书笔记——第七章:错误处理

本文探讨了在编程中如何优雅地处理错误,提倡使用异常而非错误码,建议先编写try-catch-finally语句,并使用不可控异常。强调提供详细的异常信息和根据调用者需求定义异常类。通过打包第三方API降低对外部库的依赖,避免因库更新导致大规模代码修改。同时,避免返回和传递null值,以增强代码的稳定性和可读性。总结了从混乱的错误处理到整洁代码的进化过程,提倡在健壮性和整洁性之间找到平衡。
摘要由CSDN通过智能技术生成

第七章 错误处理

7.1 使用异常而非返回码

如果给调用者返回某些错误码,可能会导致代码凌乱不堪,我们应该用异常去替代错误码

作者给出的例子就不说了,使用异常后,我们的代码整洁了许多。。。

7.2 先写Try-Catch-Finally语句

在编写可能抛出异常的语句时,最好先写出try-catch-finally语句

7.3 使用不可控异常

可控异常的代驾就是违反开放、闭合原则,对于一般的应用开发,我们尽量使用不可控异常

7.4 给出异常发生的环境说明

应创建信息充分的错误消息,并和异常一起传递出去

比如失败的操作、类型。如果系统有日志系统,传递足够的信息出去

7.5 依调用者需要定义异常类

作者给出了一个例子,这是我们对某个第三方库代码的调用:

ACMEPort port = new ACMEPort(12);

try {
    port.open();
} catch (DeviceResponseException e) {
    reportPortError(e);
} catch (ATM1212UnlockedException e) {
    reportPortError(e);
} catch (GMXError e) {
    reportPortError(e);
} finally {
    ...
}

以上代码包含了一大推重复代码,我们可以通过打包调用API,来确保他返回一个通用的异常

简单来说就是,因为上面那么多异常最后处理的代码都一样,我们可以把这么多个异常整合成一个异常:

ACMEPort port = new ACMEPort(12);

try {
    port.open();
} catch (DeviceResponseException e) {
    reportPortError(e);
} finally {
    ...
}


public class LocalPort {
    private ACMEPort port;

    public LocalPort(int number) {
        port = new ACMEPort(number);
    }
    
    public void open() {
        try {
            port.open();
        } catch (DeviceResponseException e) {
            throw new PortDeviceFailure(e);
        } catch (ATM1212UnlockedException e) {
            throw new PortDeviceFailure(e);
        } catch (GMXError e) {
            throw new PortDeviceFailure(e);
        } finally {
            ...
        }
    }
}

将第三方API打包是一个良好的时间手段,当我们打包一个API的时候,就降低了对它的依赖,未来可以不用太痛苦的改用其他代码库

我的经验之谈:

之前的项目在用Glide,一开始大家写的时候,就开始链式调用往代码里侵入,后来大家都开始这么写了。直到有一天,Glide和另一个三方库有冲突了,必须升级Glide,而且Glide新版本做了很多的优化,也比较吸引我们去升级。但是新版本调用方法跟旧版本不一样,升级以后所有调用Glide的地方全部飚红,一共几百个类,最后是我来完成这项任务的,那叫一个痛苦,最关键的是干这种事的时候就会觉得自己特别傻X,后来改完以后,项目多了一个ImageUtils的工具类,封装了相关图片加载的方法。所以啊,当这节说到这个打包第三方API,真的是经历过的人,经历过这种痛苦的人,才明白打包有多重要。我们加了一个ImageUtils工具类,可以避免现在使用的Glide的API的升级导致整个项目大改动,或者某一天出了一个更加出色的图片加载库,我们可以很轻松的就替换掉了。再比方说,我们的项目要集成IM,当时是选择的网易云信,像这种第三方API也应该打包起来。如果日后我们不再使用网易云信,而换了其它的第三方库,因为侵入更少,我们可以更方便的去替换

7.6 定义常规流程

创建一个类或者配置一个对象,用来处理特例,异常行为被封装到特列对象中

7.7 别返回null值

作者在这里举了一个列子,代码中对每一个对象都进行了判空,充满了大量的判空方法,代码看起来很糟糕

如果我们打算在方法中返回null值,不如抛出异常,或者返回特例对象

如果在调用某个第三方API中可能返回null值的方法,可以考虑用新方法打包这个方法,在新方法中抛出异常或者返回特例对象

比如getEmployees()要返回一个List,那么我们可以抛出异常或者返回一个空列表,那么调用者不需要判空,这样代码更整洁了

7.8 别传递null值

有人传入null值,我们就需要在方法内部进行判空、或者抛出异常、或者使用断言

以上方法都不是完美的解决方法,最恰当的方法就是禁止传入空值

当然在实际情况中我们不可能完全避免这种情况,比方说请求网络的方法可能会返回null值,这就必须要进行判断了

我们可以加上注解@Nullable和@Nonnull来提示调用者,是否可以传入空值

7.9 小结

整洁代码是可读的,但也得强固

将错误处理隔离看待,独立于主要逻辑之外,就能写出强固而整洁的代码

总结

其实我发现大部分人写代码的经历是这样的:

一开始是啥也不懂,啥也不写,代码各种报错,各种空指针,显得特别低级

觉得好代码就是健壮的,强固的,代码各种判空,觉得这样就是高手,从不在乎是否是整洁的,可读的

开始理智的选择使用判空return或者抛出异常,断言,注解等,知道如何在健壮和整洁之间进行平衡

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值