异常 (Exceptions)

优质
小牛编辑
134浏览
2023-12-01
  • 不要把异常用于控制流里 (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