使用
fail
方法来抛出异常。仅在捕捉到异常时使用raise
来重新抛出异常(因为没有失败,所以只是显式地有目的性地抛出一个异常)begin fail "Oops"; rescue => error raise if error.message != "Oops" end
如果
fail/raise
只有两个参数,无需显性指定RuntimeError
。# 差 fail RuntimeError, "message" # 好——默认就是 RuntimeError fail "message"
将异常类和消息作为参数给
fail/raise
,而不是异常类的的实例。# 差 fail SomeException.new("message") # 无法使用 `fail SomeException.new("message"), backtrace`. # 好 fail SomeException, "message" # 可以使用 `fail SomeException, "message", backtrace`.
永远不要从
ensure
区块返回。如果你显式地从ensure
区块中的一个方法返回,那么这方法会如同没有异常般的返回。实际上,异常会被默默丢掉。def foo begin fail ensure return "very bad idea" end end
尽可能使用隐式的
begin
区块。# 差 def foo begin # 此处放主要逻辑 rescue # 错误处理放在此处 end end # 好 def foo # 此处放主要逻辑 rescue # 错误处理放在此处 end
通过 contingency 方法 (一个由 Avdi Grimm 创造的词) 来减少
begin
区块的使用。# 差 begin something_that_might_fail rescue IOError # 处理 IOError end begin something_else_that_might_fail rescue IOError # 处理 IOError end # 好 def with_io_error_handling yield rescue IOError # 处理 IOError end with_io_error_handling { something_that_might_fail } with_io_error_handling { something_else_that_might_fail }
不要抑制异常。
begin # 这里发生了一个异常 rescue SomeError # 拯救子句完全没有做事 end # 差 do_something rescue nil
避免使用
rescue
的修饰符形式。# 差 - 这捕捉了所有的 StandardError 异常。 do_something rescue nil
不要为了控制流程而使用异常。
# 差 begin n / d rescue ZeroDivisionError puts "Cannot divide by 0!" end # 好 if d.zero? puts "Cannot divide by 0!" else n / d end
避免救援
Exception
类别。这会把信号困住,并呼叫exit
,导致你需要kill -9
进程。# 差 begin # 呼叫 exit 及杀掉信号会被捕捉(除了 kill -9) exit rescue Exception puts "you didn"t really want to exit, right?" # 异常处理 end # 好 begin # 一个不明确的 rescue 子句捕捉的是 StandardError, # 而不是许多编程者所设想的 Exception。 rescue => e # 异常处理 end # 也好 begin # 这里发生一个异常 rescue StandardError => e # 异常处理 end
把较具体的异常放在救援串连的较上层,不然它们永远不会被拯救。
# 差 begin # 一些代码 rescue Exception => e # 一些处理 rescue StandardError => e # 一些处理 end # 好 begin # 一些代码 rescue StandardError => e # 一些处理 rescue Exception => e # 一些处理 end
在
ensure
区块中释放你的程式的外部资源。f = File.open("testfile") begin # .. 处理 rescue # .. 错误处理 ensure f.close unless f.nil? end
倾向使用标准库的异常类而不是导入新的异常类。