新手问题 什么时候进行异常捕获

thxagain · 2016年02月01日 · 最后由 thxagain 回复于 2016年02月02日 · 3090 次阅读

Ruby 提供了一种 begin resuce 的简便写法:

def method1
  begin
    do_something
  rescue => e
    #catch exception
  end
end

可以简写为:

def method1
  do_something
rescue => e
  #catch exception
end

于是我在团队项目的代码中经常看到这么一种风格:

def method1
  do_something
  do_another_thing 
  # 20+ lines of code
rescue => e
  #catch exception
end

但我觉得这是一种不好的实践,可能会隐藏掉很多 bug,举个例子:

def index
  @book = Book.where(id: -111).first
  @book_name = @book.name
rescue => e
  logger.info "#{e}"  # undefined method `name' for nil:NilClass
end

虽然这里把这个no method error捕获住了,页面可能并不会挂掉,其实数据是有问题的。但如果不仔细看 log,可能就忽视了这行错误的代码。 想问问大家对于这种代码风格有什么看法。

除非有特定的异常需要处理,其它的一律抛出给 errbit

rescue 要指定类型啊。

谢谢 LS 同学们的回答,明白啦 😄 @elele @rei @hooopo 另外好像现在帖子有回复的通知有些问题,没有提醒有新的回复...

如 rei 所说,问题出在没有指定要捕获的异常类型上(不指定,默认捕获 StandardErrorNoMethodError是其子类),详见https://ruby-china.org/topics/28854 。你后面说的那种风格还是不错的,至少《Confident Ruby》的作者就相当推崇。

hooopo 的那篇文章很赞。有些错误要包容,有些错误要尽早暴露并解决。

个人的经验是,在你需要的地方进行小范围的异常捕获,而不要像上面写的,begin 20+line rescue end 这种,否则你会发现异常的捕获未必是你想象中的情况,又或者太大范围的捕获会使得代码的流程并不顺畅。

我觉得你可以试着这么考虑:异常捕获捕获的是意料之中的错误,典型的分类是 IO 操作都有失败的可能,那么都需要考虑异常处理,比如试图读取一个文件,文件不存在 其他情况,很可能是程序逻辑上的问题,尽量让程序崩溃然后通过异常收集工具或者日志去分析原因作出修正,这也是为什么(最好)要明确指定异常类型,除非你明确是何种异常并不重要

@xiaoronglv @jasl @qinfanpeng @leiz_me 谢谢回复。 总结一下就是尽量要明确地指定希望捕获的异常类型,同时不要尝试去捕获程序逻辑上的问题,要让这些错误尽早暴露出来。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号