V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Renco
V2EX  ›  程序员

想问问各位大佬,平日开发异常是怎么处理的。

  •  
  •   Renco · 51 天前 · 3114 次点击
    这是一个创建于 51 天前的主题,其中的信息可能已经有所发展或是发生改变。

    曾经写了一段代码,在最逻辑外层捕获了空指针,因为内部逻辑出现空指针一定是数据查不到导致的异常,所以方便处理,我统一在最外层捕获空指针打印 xxx 数据查不到的日志。结果被项目总监拿出来吐槽了。说空指针为什么要去捕获他。让我调整这段代码。然后我就得在内部逻辑判断多个 if 语句去 isEmpty 判断是否为空。。

    就是想了解下,我原先这种处理方式是不合适还是异常本身就不应该去捕获再做逻辑判断。

    42 条回复    2022-06-21 13:37:50 +08:00
    Renco
        1
    Renco  
    OP
       51 天前
    有时候我会用,异常捕获来做一些逻辑操作,虽然比较少,这种处理模式是比较非主流的么
    abersheeran
        2
    abersheeran  
       51 天前
    不建议最外层捕捉这种通用异常。因为你没办法保证这个异常会不会出现在其他你没想到的地方。

    最外层捕捉异常的逻辑一般都是捕捉自己定义的异常,因为能清楚知道它会在什么时候出现、以及该如何处理。
    jjwjiang
        3
    jjwjiang  
       51 天前   ❤️ 3
    在可能为空的地方处理空值是一个码农的基本素养之一
    Renco
        4
    Renco  
    OP
       51 天前
    @abersheeran 好吧 清楚了。
    Renco
        5
    Renco  
    OP
       51 天前
    @jjwjiang 偷懒了,两年前写的代码被挖出来嘲讽一波 有点难受
    rekulas
        6
    rekulas  
       51 天前
    我也支持你总监的做法,你在外部捕获虽然表面方便但有这样的问题:
    1 你可能很难确定空指针具体是哪个逻辑导致的
    2 正常逻辑执行时如果不及时处理空指针有可能出现数据错误-一些本不应该执行到的逻辑被处理了,从而引起 bug
    可能还有其他问题...
    Renco
        7
    Renco  
    OP
       51 天前
    @abersheeran 那如果我能保证我捕获的这段逻辑出现的空指针是我能确定的,可以这样处理么。
    thinkershare
        8
    thinkershare  
       51 天前
    主要要看你处于什么层次, 你做的这个层的消费者是谁, 如果你作为一个底层库, 要看错误是谁导致的, 如果是用户入参有问题, 我们就是抛出异常, 如果是内部的不受控的上下文依赖导致的问题, 也是直接抛给调用者, 如果是内部业务逻辑错误, 也直接抛给调用者. 如果是外部调用者(普通用户或第三方 API 调用者),那么就需要在外层统一处理一下. 主要是大部分错误就没法处理. 直接返回给调用者. 主要是看是逻辑错误还是其它. 说白了, 异常是一种偷懒的流程控制手段, 看你怎么用.
    Renco
        9
    Renco  
    OP
       51 天前
    @rekulas 明白了,谢谢大佬
    xunbug
        10
    xunbug  
       51 天前
    做法不对,你既然捕获到日志中了,就应该再写个脚本定时删除异常日志,这样就不会发现错误了
    thinkershare
        11
    thinkershare  
       51 天前
    另外, 对外在能考虑到的情况是不会抛出系统级别的异常的. 如果事前没有考虑到, 那么就让他直接奔溃. 由宿主层去考虑要怎么执行下一步操作.
    abersheeran
        12
    abersheeran  
       51 天前   ❤️ 1
    @Renco 你没法保证空指针异常一定出自你的这个逻辑。你不是神,你怎么预测未来的代码不会抛出其他情况的空指针异常?

    如果你坚持在外层捕捉你这段逻辑的异常,我的建议是你在你的代码逻辑那儿捕捉空指针,重新抛出一个你自定义的异常。
    Renco
        13
    Renco  
    OP
       51 天前
    @abersheeran 可以,受教了
    chaoschick
        14
    chaoschick  
       51 天前 via Android
    我也喜欢在 controller 层进行异常捕获,
    chendy
        15
    chendy  
       51 天前
    空指针异常其实不方便统一处理,因为不知道什么东西是 null ,所以通常和其他异常一样,做为“系统异常”处理

    一般做法是,业务逻辑里做 == null 判断然后抛自定义的异常 “未找到 xxx”,外加打日志 “id 是 xxx ,查询条件 xxx 的数据未找到”
    Saxton
        16
    Saxton  
       51 天前
    难怪你被吐槽。。 我最近接手到一个项目全部用 try catch 来判空和判非法值,有几个参数是直接 get 的,但并非必填的, 无语死,整个方法拿个 try 套起来,省了几个 if ,你这确实爽了啊,后期维护的人怎么办,吐血给你看吗
    Saxton
        17
    Saxton  
       51 天前   ❤️ 5
    越想越气,楼主你在哪
    AoEiuV020CN
        18
    AoEiuV020CN  
       51 天前
    不做空判断的话 idea 会有黄色警告,哪怕只是为了消除警告都可以加个空判断,
    Saxton
        19
    Saxton  
       51 天前
    代码一大堆全部是拿 try 来充当 if ,哪里出问题我必须开调试,不然我根本不知道到底是哪一个方法抛的异常,关键还是捕获的 exception ,我该他的代码还得开个 debug 一步一步走看看到底哪里蹦了
    DonaldY
        20
    DonaldY  
       51 天前
    平时代码多考虑会儿,该 throw 的 throw ,该 try 的 try ,有异常的地方打好堆栈。

    蔸底拦截是应该有的,提示需要给用户友好,而不是把错误显示在页面上。
    Renco
        21
    Renco  
    OP
       51 天前
    @Saxton 没。。我就少量代码这样处理了,而且是刚毕业写的,这会已经不写类似的代码了。大佬别来揍我: (
    Renco
        22
    Renco  
    OP
       51 天前
    @Saxton 你这个确实恶心,大多数还是用 if 去判断的,也好定位问题。try catch 维护起来 定位错误会很痛苦
    leafre
        23
    leafre  
       51 天前
    《 effective java 》:对于可恢复的条件使用被检查的异常( CheckedException ),对于程序错误使用运行时异常( RuntimeException )。

    NPE 出现,就说明代码健壮性有问题,逻辑错误,快速定位修复,而不是捕获。
    taest
        24
    taest  
       51 天前
    如果出现未知的系统异常,那就让他抛出就完事了。
    TWorldIsNButThis
        25
    TWorldIsNButThis  
       51 天前 via iPhone
    我用 null safety 语言 没有这个烦恼
    而且所有从 map 取值的操作(都是可为 null 的类型),如果业务上就是不会为 null 的都额外 checknotnull 并捕获上下文里的相关变量抛异常方便排查脏数据的问题
    之前切回 java 写一个要处理 null 和 empty 的接口改了五次才改好
    wonderblank
        26
    wonderblank  
       51 天前
    让它崩掉。
    Morii
        27
    Morii  
       51 天前   ❤️ 3
    @Saxton #17 乍一看我以为你要提刀砍楼主了
    ekoaix
        28
    ekoaix  
       51 天前
    总的原则是:1 、在最贴近代码处、发生处进行处理。2 、你能处理就处理,处理不掉就抛出去处理,到能处理的地方去处理。:)有掉绕
    kidlj
        29
    kidlj  
       51 天前
    if err != nil {
    // handle err
    }
    lihengyu
        30
    lihengyu  
       51 天前
    @Saxton 冷静 XD
    OutOfMemery
        31
    OutOfMemery  
       51 天前
    @Saxton #17 兄弟,刀放下,有话好好说🐶
    dilu
        32
    dilu  
       51 天前
    goer:

    if err != nil {
    log.Errorf();
    }
    vchroc
        33
    vchroc  
       51 天前
    @dilu 写吐了,别到处说了!!!
    dilu
        34
    dilu  
       51 天前
    @vchroc 哈哈哈哈哈哈 问题不大,我还能再写好几年呢
    redorblacck886
        35
    redorblacck886  
       51 天前
    Optional 了解下
    HackerJax
        36
    HackerJax  
       51 天前 via iPhone
    把你的 find 方法封一下叫 findOrThrowException ,在全局统一处理这里抛出的异常,顺便记上日志。这样在业务层就没必要 care 这种问题了
    lmshl
        37
    lmshl  
       51 天前
    我们用 Option / Either ,非必要不抛异常😏
    dddd1919
        38
    dddd1919  
       51 天前
    很多场景的异常是可以预见到的,而且这种异常并称不上是异常,而是合理的逻辑分支,比如 lz 讲到的查不到数据,本来一个判断搞定的事非要抛异常,逻辑不但没有更清晰,还额外增加捕获异常的运行时开销。
    如果想都用异常来处理的话,要把各处的异常做细分,保证哪些是可吞掉的哪些是需要抛出的。与其花精力管理异常,不如从源头处理好。当然从性能的角度讲,避免抛异常
    ferock
        39
    ferock  
       51 天前 via iPhone
    有的时候问题需要暴露的,而不是兜底
    Dogtler
        40
    Dogtler  
       51 天前 via iPhone
    Go 好像没有 try catch ,一般是判断 err panic 业务报错则 log 输出
    pzs
        41
    pzs  
       51 天前
    一种处理方式:SpringBoot 项目进行全局异常的处理 https://www.cnblogs.com/xuwujing/p/10933082.html
    thetbw
        42
    thetbw  
       50 天前
    spring 或者 filter 统一处。然后除了业务的异常,比如用户经行了错误的操作。其他异常都应该后续解决,我是这么觉得
    关于   ·   帮助文档   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   3255 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 05:05 · PVG 13:05 · LAX 22:05 · JFK 01:05
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.