上周code review的时候,发现一个同事把所有异常都用try-catch包起来,然后就ignore了。这种代码怎么能上线?
上周五晚上加班到十点多吧,我们组做 code review 的时候,真是给我看乐了,有个同事直接把一坨业务逻辑,外面套了个巨大的 try-catch,然后 catch 里写了个 // ignore……我当时差点没把电脑合上,这种代码要是上线了,出点线上事故,谁去查日志?鬼都查不出来。

为啥 try-catch ignore 是坑
我知道有些新人写代码的时候,怕抛异常,想着“反正我包住了就不会报错”,心态有点像小孩蒙眼睛过马路。问题是,异常本身就是告诉你程序哪里不正常,你把它吃掉了,不仅自己蒙了,连团队都被蒙在鼓里。
比如一段典型的写法:
try {
doSomething();
} catch (Exception e) {
// ignore
}
这种代码上线之后,假设数据库超时,网络抖动,甚至 NPE,统统被忽略,结果用户那边看到的就是功能没反应或者数据错乱,日志里还什么都没有。到时候排查问题,只能靠猜,靠撞运气。
我以前遇到过一个事故,就是某人写了这种“万能 ignore”,结果导致支付回调失败,用户钱扣了但订单没更新,查了两天才定位到这个点,整个组被客户追着骂。
正确的处理姿势
不是说 try-catch 不能用,而是要用得有价值。通常有几种方式:
-
日志打印至少你要 log 下来。哪怕只是 debug 级别,也能在排查的时候找到线索。
try { processOrder(); } catch (Exception e) { log.error("订单处理失败", e); throw e; // 或者转换成业务异常 } -
转化成业务异常有时候底层抛的是 SQLException 或者 IOException,这些东西直接冒泡给上层没啥意义。可以统一封装成自定义异常:
public class OrderException extends RuntimeException { public OrderException(String message, Throwable cause) { super(message, cause); } }然后 catch 的时候转换:
try { updateOrder(); } catch (SQLException e) { throw new OrderException("更新订单失败", e); } -
兜底但给提示如果确实有些地方“不影响业务主流程”,比如清理缓存失败了,那也别完全忽略,至少 log 一下:
try { cacheService.clear(); } catch (Exception e) { log.warn("清理缓存失败,但不影响主业务: {}", e.getMessage()); }这样后面运维查日志的时候,心里有数。
Code Review 怎么怼回去
当场我就跟那哥们说:异常是软件的报警器,你不能把报警器拆了,还觉得世界一片安静。
团队内部可以约定一些规范,比如:
-
catch 里必须有日志或异常转换
-
不能写
// ignore -
如果确实不想抛出,要写清楚注释:为什么可以忽略,后果是什么
我自己写代码的时候,还喜欢在方法签名里声明更具体的异常,而不是一股脑 throws Exception,比如:
public void saveUser(User user) throws IOException {
// ...
}
这样调用方一看就知道可能会有 IO 层面的异常,不会稀里糊涂。
线上排查靠啥
这里顺便插一句,线上排查异常靠的就是日志和监控。像我们现在接了 ELK,还有 Sentry,异常一抛就会被收集报警。要是都被 ignore,监控那边压根看不到,运维只能盯着用户报障,迟早要出大事。
有时候你 catch 下来,还能打点埋点,顺便加个 traceId,出问题的时候就能串起来整个调用链,这比啥都忽略强一万倍。
=
写代码真的不是说“跑得起来就行”,你得想想后面维护的人怎么活。try-catch ignore 这种写法,短期看好像很省事,长期看就是埋雷。兄弟们 review 的时候碰到这种代码,千万别心软,直接怼回去,宁愿多加几行日志,也别做这种“沉默的炸弹”。
——说到这我想起来,我得去催我们测试组的小王补充下异常场景的用例,上次他又漏了个超时的情况,哎,等下再去群里喊他。
更多推荐



所有评论(0)