使用?fail
?方法來拋出異常。僅在捕捉到異常時(shí)使用?raise
?來重新拋出異常(因?yàn)闆]有失敗,所以只是顯式地有目的性地拋出一個(gè)異常)
begin
fail 'Oops';
rescue => error
raise if error.message != 'Oops'
end
如果?fail/raise
?只有兩個(gè)參數(shù),無需顯性指定?RuntimeError
。
# 差
fail RuntimeError, 'message'
# 好——默認(rèn)就是 RuntimeError
fail 'message'
將異常類和消息作為參數(shù)給?fail/raise
?,而不是異常類的的實(shí)例。
# 差
fail SomeException.new('message')
# 無法使用 `fail SomeException.new('message'), backtrace`.
# 好
fail SomeException, 'message'
# 可以使用 `fail SomeException, 'message', backtrace`.
永遠(yuǎn)不要從?ensure
?區(qū)塊返回。如果你顯式地從?ensure
?區(qū)塊中的一個(gè)方法返回,那么這方法會(huì)如同沒有異常般的返回。實(shí)際上,異常會(huì)被默默丟掉。
def foo
begin
fail
ensure
return 'very bad idea'
end
end
盡可能使用隱式的?begin
?區(qū)塊。
# 差
def foo
begin
# 此處放主要邏輯
rescue
# 錯(cuò)誤處理放在此處
end
end
# 好
def foo
# 此處放主要邏輯
rescue
# 錯(cuò)誤處理放在此處
end
通過?contingency?方法 (一個(gè)由 Avdi Grimm 創(chuàng)造的詞) 來減少?begin
?區(qū)塊的使用。
# 差
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
# 這里發(fā)生了一個(gè)異常
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
?類別。這會(huì)把信號(hào)困住,并呼叫?exit
,導(dǎo)致你需要?kill -9
?進(jìn)程。
# 差
begin
# 呼叫 exit 及殺掉信號(hào)會(huì)被捕捉(除了 kill -9)
exit
rescue Exception
puts "you didn't really want to exit, right?"
# 異常處理
end
# 好
begin
# 一個(gè)不明確的 rescue 子句捕捉的是 StandardError,
# 而不是許多編程者所設(shè)想的 Exception。
rescue => e
# 異常處理
end
# 也好
begin
# 這里發(fā)生一個(gè)異常
rescue StandardError => e
# 異常處理
end
把較具體的異常放在救援串連的較上層,不然它們永遠(yuǎn)不會(huì)被拯救。
# 差
begin
# 一些代碼
rescue Exception => e
# 一些處理
rescue StandardError => e
# 一些處理
end
# 好
begin
# 一些代碼
rescue StandardError => e
# 一些處理
rescue Exception => e
# 一些處理
end
在?ensure
?區(qū)塊中釋放你的程式的外部資源。
f = File.open('testfile')
begin
# .. 處理
rescue
# .. 錯(cuò)誤處理
ensure
f.close unless f.nil?
end
更多建議: