異常

2018-02-24 16:10 更新
  • 使用?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
  • 傾向使用標(biāo)準(zhǔn)庫的異常類而不是導(dǎo)入新的異常類。
以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)