异常 (Exceptions)

异常 (Exceptions)

  • 不要把异常用于控制流里 (flow of control)
    [link]
  #  错误
  begin
    n / d
  rescue ZeroDivisionError
    puts "Cannot divide by 0!"
  end

  #  正确
  if d.zero?
    puts "Cannot divide by 0!"
  else
    n / d
  end
  • 避免捕捉 Exception 这个大类的异常
    [link]
  #  错误
  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 子类这样比较清晰和明确。[link]
  #  错误
  raise RuntimeError, 'message'

  #  正确一点 - RuntimeError 是默认的
  raise 'message'

  #  最好
  class MyExplicitError < RuntimeError; end
  raise MyExplicitError
  • 尽量将异常的类和讯息两个分开作为 raise 的参数,而不是提供异常的实例。[link]
  #  错误
  raise SomeException.new('message')
  #  注意,提供异常的实例没办法做到 `raise SomeException.new('message'), backtrace`.

  #  正确
  raise SomeException, 'message'
  #  可以达到 `raise SomeException, 'message', backtrace`.
  • 避免使用 rescue 的变异形式。
    [link]
  #  错误
  read_file rescue handle_error($!)

  #  正确
  begin
    read_file
  rescue Errno:ENOENT => ex
    handle_error(ex)
  end