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

真是怕了那些用异常捕捉却不抛出错误的人了!

  •  
  •   LiuSha · 2020-01-09 20:12:51 +08:00 · 7563 次点击
    这是一个创建于 1779 天前的主题,其中的信息可能已经有所发展或是发生改变。

    这两天在改别人写的代码,要增加新的功能,但真是改得太痛苦了,因而想吐槽一下。

    • 一个类几千行( python ),界面和功能写在一个类里了;
    • 大段大段的代码没有注释,还有一些命名类似的方法也没有注释;
    • 最恶心人的地方就是滥用异常捕捉还不抛出错误,导致调试的时候明明程序出 bug 了却没有任何错误信息。

    唉,说完了,明天还得接着改。

    49 条回复    2020-01-12 14:12:09 +08:00
    Raymon111111
        1
    Raymon111111  
       2020-01-09 20:26:38 +08:00   ❤️ 2
    最恶心的应该是第一点吧
    l4ever
        2
    l4ever  
       2020-01-09 20:34:40 +08:00   ❤️ 1
    说的应该不是我, 我一般捕获了错误一定会打日志.
    hmxxmh
        3
    hmxxmh  
       2020-01-09 21:57:07 +08:00 via Android
    Python 写起来是真舒服,维护起来是真要命,唉,动态语言的弊端吧
    sun1991
        4
    sun1991  
       2020-01-09 22:54:44 +08:00
    这种人就是没责任心, 想着只要不出错就可以混过去.
    wdv2ly
        5
    wdv2ly  
       2020-01-10 07:52:21 +08:00 via Android
    逮住再放,那为啥要逮🐶
    chendy
        6
    chendy  
       2020-01-10 08:18:51 +08:00   ❤️ 10
    曾经一个项目( Java ),里面到处都是空的 catch (Exception e) 块
    问那个老哥为啥这么写,他说不这么写编译不了
    zjsxwc
        7
    zjsxwc  
       2020-01-10 08:37:33 +08:00
    和 js 相比,Python 写起来不舒服,维护起来要人命
    ebingtel
        8
    ebingtel  
       2020-01-10 08:41:43 +08:00
    @wdv2ly 可以收敛异常类型的个数、表名错误的原因……总不能在最外层加个 Exception 或者每个异常加个 XXXError
    rooob1
        9
    rooob1  
       2020-01-10 08:50:24 +08:00
    @zjsxwc 引战?
    pmispig
        10
    pmispig  
       2020-01-10 09:12:49 +08:00
    哈哈哈,终于有人开这个标题了,我要狠狠地吐槽一番。
    我们公司几乎大部分的人都是这样做的,
    try {
    }catch (Excetpion){
    log("XX 业务异常异常")
    }
    妈蛋,我简直醉了
    LiuSha
        11
    LiuSha  
    OP
       2020-01-10 09:24:58 +08:00
    @hmxxmh 如果注意代码规范就还好一些,就怕乱写一通的,维护起来要人命了
    zunceng
        12
    zunceng  
       2020-01-10 10:00:53 +08:00
    别吐槽 python 了,
    golang 这么强制的语言还有人不处理 err 呢
    res, _ = sess.Insert(model)
    hdbzsgm
        13
    hdbzsgm  
       2020-01-10 10:17:30 +08:00
    @pmispig #10 对于某些 Checked Exception 这样做是合适的 但是直接 catch Exception 的人 应该立刻辞退
    julyclyde
        14
    julyclyde  
       2020-01-10 10:20:41 +08:00
    @chendy Java 虽然强制 catch,但是依然拯救不了外行
    gam2046
        15
    gam2046  
       2020-01-10 10:25:20 +08:00
    Check Exception 本质上是要求编码人员遵守一定的规范,而人这个变量太无法控制了,导致很多经验不足的人空捕获异常,使得 CE 形同虚设,但我觉得这是人的问题,而不是 CE 本身的问题。
    kop1989
        16
    kop1989  
       2020-01-10 10:26:32 +08:00
    很多语言不支持异常声明吧,导致抛出错误的沟通成本很高。
    laravel
        17
    laravel  
       2020-01-10 10:27:18 +08:00
    php 才是最好的语言,laravel 是最好的框架。
    LuciferGo
        18
    LuciferGo  
       2020-01-10 10:36:04 +08:00   ❤️ 1
    我司引入自动代码检查了,这种全都要打回去重写,不改不准提测,哈哈哈哈
    LiuSha
        19
    LiuSha  
    OP
       2020-01-10 10:56:34 +08:00
    @LuciferGo 厉害了!
    evlos
        20
    evlos  
       2020-01-10 11:00:32 +08:00 via Android
    某大厂的 JS SDK 就是这样,简直不能更弱智了
    pmispig
        21
    pmispig  
       2020-01-10 11:30:21 +08:00
    @hdbzsgm catch Exception 我不反对,问题是你得把异常堆栈抛出来呀,这样直接吃掉了,谁知道底层是什么原因呢。。
    BBCCBB
        22
    BBCCBB  
       2020-01-10 11:35:10 +08:00
    @hmxxmh 我不信加上 type hints 还恼火
    neoblackcap
        23
    neoblackcap  
       2020-01-10 13:06:19 +08:00   ❤️ 1
    因为绝大多数人是不知道错误应该怎么处理。
    举个例子,比如我要处理一下 Excel 文件,然后往里面写入一个名为报告的工作表。
    第一步 Excel 文件就不存在,应该如何处理?

    很多人受不能抛出异常,不能抛出错误的说法影响。好像程序一直跑着就是正常的,就是没有 bug。
    其实有问题不能处理就应该往上层抛,尽量保持事发当时的环境。这样才是正常的做法。假如最上层都不能解决的,那么就应该赶紧打日志然后崩溃。阻止进一步的错误发生。

    正是因为不了解错误处理,所以才那么多那么多空的异常处理,仅仅为了糊弄编译器。
    rioshikelong121
        24
    rioshikelong121  
       2020-01-10 13:35:37 +08:00
    Let it crash.
    augustheart
        25
    augustheart  
       2020-01-10 13:39:41 +08:00
    其实这种情况下很多时候是不知道怎么处理吧……
    要是每个错误都一定有合适的处理方法,一个个处理都没问题,但是问题是相当多的异常根本无从处理,直接崩了拉倒……
    stevenkang
        26
    stevenkang  
       2020-01-10 13:57:23 +08:00
    恕我直言,业务层面处理异常就是渣架构。明明可以靠架构来处理,非得每个业务点都来 try catch 一把。
    CallMeReznov
        27
    CallMeReznov  
       2020-01-10 14:04:11 +08:00
    我自己写的 python 到是直接 try 所有
    不过如果用到线上的话 不精确捕捉的确说不过去吧
    RYAN0UP
        28
    RYAN0UP  
       2020-01-10 14:05:20 +08:00 via iPhone
    同,前公司某同事吧几百行代码写在 try 里面却不处理异常,不打印堆栈。
    Achiii
        29
    Achiii  
       2020-01-10 14:12:54 +08:00
    想去写 py
    miaoxia
        30
    miaoxia  
       2020-01-10 15:07:45 +08:00
    见过最崩溃的代码,就是用 try-catch 当作业务判断,catch 到不同的 exception 处理不同的业务
    因为这事儿大吵一架
    luckylo
        31
    luckylo  
       2020-01-10 15:15:05 +08:00
    我来说一句吧。 一个类 11K 行代码 。 一个函数 四五百行 代码,基本没注释。 Java
    hmxxmh
        32
    hmxxmh  
       2020-01-10 15:48:49 +08:00
    @BBCCBB 类型注解是 3.6 版本之后才有的吧,好像返回类型啥的只能自我约束,程序不会去判断。。。,而且很多项目还是 2.7 的
    AS4694lAS4808
        33
    AS4694lAS4808  
       2020-01-10 15:56:45 +08:00
    给自己挖的坑,本来想写个小测试工具,catch 块就直接空着了。后来忘了并且把这个功能合并到生产版本。。花了几天在线上找问题,找到后差点打死自己。。
    BBCCBB
        34
    BBCCBB  
       2020-01-10 16:32:50 +08:00
    @hmxxmh 嗯嗯, 3.5 开始加的..
    arrow2015
        35
    arrow2015  
       2020-01-10 18:36:52 +08:00 via Android
    我司代码有安全规范,不让 catch 中打印堆栈错误信息。
    Biscuits
        36
    Biscuits  
       2020-01-10 18:39:14 +08:00
    每次我想吐槽同事的时候就会想到:我怎么会和他是同事的?
    sessionreckon
        37
    sessionreckon  
       2020-01-10 18:43:49 +08:00
    这种还好吧...
    来了头条之后,我才发现原来代码可以写的那么烂
    if else 里面的代码有的是不能跑的,class 没有定义,对象没有定义,func 不存在
    大部分看起来都是代码在迭代的时候,原来的代码不删导致的,维护者知道进不去就不管了
    所以代码在 IDE 上到处飘红...
    但是又不是不能用,Python 跑的挺正常的....
    LiuSha
        38
    LiuSha  
    OP
       2020-01-10 20:21:57 +08:00
    @sessionreckon 大厂也会有这种情况吗。。。
    MonoLogueChi
        39
    MonoLogueChi  
       2020-01-10 20:27:39 +08:00 via Android
    我以前也经常这么做,就是为了程序运行的时候不被卡死了
    darrenfang
        40
    darrenfang  
       2020-01-11 09:25:29 +08:00
    @pmispig #10 我司上古代码连 log 都没有,哈哈哈哈
    mostkia
        41
    mostkia  
       2020-01-11 12:11:42 +08:00
    @neoblackcap 是的,发生了没法处理的错误,首先得保留现场,一般是抛出错误,这样后期维护调试时才能发现问题所在。其次,假如已经发生了致命错误,就不能够继续执行下去,因为后续的程序不知道会因为当前的错误而发生什么更严重的异常,同时及时停止出错的程序,也能减少报错量,吧问题停止在出问题的地方,而不是到最后得到一长串莫名其妙的报错,利于后期快速定位排查问题。
    mostkia
        42
    mostkia  
       2020-01-11 12:14:07 +08:00
    @pmispig 直接自己定义一个自己当时能看懂的错误,然后把宝贵的编译器报错直接丢掉,牛批。
    zappos
        43
    zappos  
       2020-01-11 12:55:22 +08:00 via Android
    python 没有 partial class,写成两个类只能用继承了
    zappos
        44
    zappos  
       2020-01-11 12:57:01 +08:00 via Android
    @darrenfang 如果能自定义流也成。。。有些上古程序硬是往 stderr 里面写,我这边 popen 总是捕获不到。
    zappos
        45
    zappos  
       2020-01-11 12:59:55 +08:00 via Android
    @neoblackcap gui 是 longrunning 的东西,不崩才比较重要吧。。。

    一个回调出了异常,为什么要整个 ui 都崩掉,就好比服务器,一个 handler 出了异常,为啥要让整个服务器都崩掉?

    再说了异常这种东西,没准过段时间就好了。
    neoblackcap
        46
    neoblackcap  
       2020-01-11 13:16:34 +08:00
    @zappos 我由头自尾都没有谈到 GUI 的问题。

    处理不了就要崩掉,你数据库连接不了。不崩掉,然后能正常运行?每个程序总有你处理不了的异常,这个时候不打日志崩掉还追求所谓 long running,那才是奇怪。

    记住不是盲目追求长时间运行,或者一小问题都要崩掉。这是两个极端。

    错误处理应该是,这层不能处理就应该往上层传递,最上层都处理不了了那么就要打日志崩掉。能处理的话,那么就正常处理就好了。好比你举得例子,你 handler 抛出的异常,你能处理,那么就处理啊。不能处理就打日志崩掉啊。难道你还想说不能处理的就当没事发生?
    zappos
        47
    zappos  
       2020-01-11 19:25:19 +08:00 via Android
    @neoblackcap 哦?? spring 是这么做的嘛? apache server 是这么做的嘛?
    zappos
        48
    zappos  
       2020-01-11 19:29:36 +08:00 via Android
    gui 程序控制在回调一级就够了。可以把每个回调视为独立的东西,彼此不互相影响。

    由于 gui 框架基本不提供 spring 那种异常统一处理的功能,回调级的 try-catch 根本不能避免。而且除了打 log 也没别的办法。
    realpg
        49
    realpg  
       2020-01-12 14:12:09 +08:00
    个人开发规范:

    因为传进来的外部数据非法原因导致的错误
    比如类型不对 比如传进了空 比如传进了的数据库连接异常
    扔异常 大部分是自定义异常 class

    因为自身逻辑失败导致的异常,如果功能自身是主线逻辑,直接 crash
    如果自身是支线逻辑 扔异常 依然是自定义异常 class

    比如一个数据存储模块,目标目录不可写或者已满导致写不进去,直接 crash
    如果是一个存日志的支线模块,同样目标目录不可写,丢个 OPLogDirCannotWriteException 让上层决定这个日志不可写是不是重要要不要中断程序
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3101 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 00:15 · PVG 08:15 · LAX 16:15 · JFK 19:15
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.