Published on

写优雅的代码:异常处理

Authors

我打算写一个系列的文章,主要是关于代码风格方面的。先从异常处理开始,这一部分比较容易出问题。原本这些内容是可以写在一篇文章里面的。但是我担心内容太长,大家没有耐心看完。

异常处理最重要的是要正确的区分异常的和错误,比如说 OutOfMemoryError 属于错误,不属于异常。网络连接丢失属于异常,我们需要进行重连。

不要吞掉任何异常

请看下面的代码

try:
    1 / 0
except:
    pass
public bool SomeMethod() {
    try {
       //Some code
       if ("Business Logic Failed") {
            return false;
       }
       //everything passed
       return true;
    }
    catch {
        return false;
    }
}

吞掉异常,往往是假设异常不会发生。这种情况下,在程序执行遇到问题的时候,不会有任何日志输出,很难确定到底是什么问题导致了程序的异常。所以,异常处理的最低底线就是,必须要记录错误发生时的堆栈信息。所以,可以修改为下面的方式。

public bool SomeMethod() {
    try {
       //Some code
       if ("Business Logic Failed") {
            throw new ApplicationException("Business Logic Failed...Give details on what failed");
       }
       return true;
    }
    catch (Exception ex) {
        //Logs StackTrace, Message, and all InnerException Message/StackTrace
        LogMessage(ex);
        return false;
    }
}

不要捕获通用异常,异常处理一定要具体

上面的异常处理方式,虽然比吞掉异常好一点,但还是不够完美,因为捕捉的通用的异常,这并不是一种好的实践。

try:
    1 / 0
except Exception as e:
    _logger.error(e)

不要 catch 整个代码块

实际上,进入到 try-catch 代码块会生成 Exception 对象,这会影响性能,如果不是特别必要,不要把代码放到异常处理的代码块当中。在正常的分支流程当中的代码,性能要比 try-catch 的代码块中高。


版本变化:

  1. 2018年11月16日 发布
  2. 2018年12月10日 更新
  3. 2018年12月12日 更新
  4. 2018年12月16日 更新

参考文章: Do Not Swallow The Exceptions
The Curse of the Swallowed Exception
Swallowing exceptions is hazardous to your health