プロを目指す人のためのRuby入門・第9章重要ポイントまとめ

「プロを目指す人のためのRuby入門」の第9章を読み終わりました

個人的に重要と判断したポイントをまとめます。

例外処理に対する初心者のスタンス

・例外が発生したら極力、異常終了させる or フレームワークの共通処理に全部丸投げする
  →安易にrescueして処理中のデータ構造が崩れたりなど別の問題が発生する危険性が高いため

・例外処理より条件分岐を使う
  →問題の有無を事前に確認できるメソッドが用意されていないか調べる

・対象範囲と対象クラスを絞り込む
  →異常終了扱いすべき例外まで続行可能な例外として扱われてしまうのを防ぐため

例外処理の流れ

予期せぬ箇所で例外が発生した場合、そこで処理を中断してメソッドの呼び出しを1つずつ戻って、その例外を捕捉するコードを探索します

def method_1
  puts 'method_1 start.'
  begin
    method_2
  rescue
    puts '例外が発生しました'
  end
  puts 'method_1 end.'
end

def method_2
  puts 'method_2 start.'
  method_3
  puts 'method_2 start.'
end

def method_3
  puts 'method_3 start.'
  #ZeroDivisionErrorを発生させる
  1 / 0
  puts 'method_3 end.'
end

#処理を開始
method_1
#=> method_1 start.
#=> method_2 start.
#=> method_3 start.
#=> 例外が発生しました
#=> method_1 end.

method_3が呼ばれると、ZeroDivisionErrorが発生しますが、method_3には例外を捕捉するコードが無いためmethod_2に戻ります。
しかし、method_2にも例外を捕捉するコードが無いためmethod_1に戻ります。
method_1ではmethod_2の呼び出しがbegin~rescueで囲まれているためここで例外が捕捉されました。
method_1では例外が捕捉されたため最後まで処理がされていますが、例外が捕捉されなかったmethod_2、method_3は例外が発生した時点で処理が中断されたままになっています。

例外クラスの継承関係を理解する

・通常発生する可能性の高い例外クラスはStandardErrorクラスを継承するサブクラスになっている
・例外処理の際、rescue節になにもクラスを指定しなかった場合に捕捉されるのはStandardErrorとそのサブクラス
・例外クラスの継承関係に注意してrescue節に指定する例外クラスの順番を決定する

begin
  'abc'.foo
rescue NameError
  puts 'NameErrorです'
rescue NoMethodError
  puts 'NoMethodErrorです'
end

#=> NameErrorです

NameErrorクラスはNoMethodErrorクラスのスーパークラスのため、NoMethodErrorに該当する例外も
その前のNameErrorで捕捉されてしまいます。
スーパークラスよりも前にそのサブクラスを持ってくることでこれを防ぐことができます。

begin
  'abc'.foo
rescue NoMethodError
  puts 'NoMethodErrorです'
rescue NameError
  puts 'NameErrorです'
end

#=> NoMethodErrorです


感想
初級者は例外処理はなるべく使わないほうが良いことが分かりました。
なるべく条件分岐を使いたいと思います。