异常 (Exceptions)

  • 不要把异常用于控制流里 (flow of control)
    [link]

    1. # 错误
    2. begin
    3. n / d
    4. rescue ZeroDivisionError
    5. puts "Cannot divide by 0!"
    6. end
    7. # 正确
    8. if d.zero?
    9. puts "Cannot divide by 0!"
    10. else
    11. n / d
    12. end
  • 避免捕捉 Exception 这个大类的异常
    [link]

    1. # 错误
    2. begin
    3. # an exception occurs here
    4. rescue Exception
    5. # exception handling
    6. end
    7. # 正确
    8. begin
    9. # an exception occurs here
    10. rescue StandardError
    11. # exception handling
    12. end
    13. # 可以接受
    14. begin
    15. # an exception occurs here
    16. rescue
    17. # exception handling
    18. end
  • 传 2 个参数调 raise 异常时不要明确指明RuntimeError。尽量用 error 子类这样比较清晰和明确。[link]

    1. # 错误
    2. raise RuntimeError, 'message'
    3. # 正确一点 - RuntimeError 是默认的
    4. raise 'message'
    5. # 最好
    6. class MyExplicitError < RuntimeError; end
    7. raise MyExplicitError
  • 尽量将异常的类和讯息两个分开作为 raise 的参数,而不是提供异常的实例。[link]

    1. # 错误
    2. raise SomeException.new('message')
    3. # 注意,提供异常的实例没办法做到 `raise SomeException.new('message'), backtrace`.
    4. # 正确
    5. raise SomeException, 'message'
    6. # 可以达到 `raise SomeException, 'message', backtrace`.
  • 避免使用 rescue 的变异形式。
    [link]

    1. # 错误
    2. read_file rescue handle_error($!)
    3. # 正确
    4. begin
    5. read_file
    6. rescue Errno:ENOENT => ex
    7. handle_error(ex)
    8. end