8. 异常 (Exceptions)

  • 不要把异常用于控制流里 (flow of control)
      #  错误
      begin
        n / d
      rescue ZeroDivisionError
        puts "Cannot divide by 0!"
      end
      #  正确
      if d.zero?
        puts "Cannot divide by 0!"
      else
        n / d
      end
    
  • 避免捕捉 Exception 这个大类的异常
      #  错误
      begin
        #  an exception occurs here
      rescue Exception
        #  exception handling
      end
      #  正确
      begin
        #  an exception occurs here
      rescue StandardError
        #  exception handling
      end
      #  可以接受
      begin
        #  an exception occurs here
      rescue
        #  exception handling
      end
    
  • 传 2 个参数调 raise 异常时不要明确指明RuntimeError。尽量用 error 子类这样比较清晰和明确。
      #  错误
      raise RuntimeError, 'message'
      #  正确一点 - RuntimeError 是默认的
      raise 'message'
      #  最好
      class MyExplicitError < RuntimeError; end
      raise MyExplicitError
    
  • 尽量将异常的类和讯息两个分开作为 raise 的参数,而不是提供异常的实例。
      #  错误
      raise SomeException.new('message')
      #  注意,提供异常的实例没办法做到 `raise SomeException.new('message'), backtrace`.
      #  正确
      raise SomeException, 'message'
      #  可以达到 `raise SomeException, 'message', backtrace`.
    
  • 避免使用 rescue 的变异形式。
      #  错误
      read_file rescue handle_error($!)
      #  正确
      begin
        read_file
      rescue Errno:ENOENT => ex
        handle_error(ex)
      end