スキップしてメイン コンテンツに移動

例外処理で堅牢Ruby

例外処理で堅牢Ruby

Ruby実践での例外処理の基本

Rubyにおける例外処理は、beginrescue を組み合わせて行います。begin ブロック内で発生した例外は、rescue で捕捉され、プログラムのクラッシュを防ぎます。例外捕捉は、エラーハンドリングの第一歩であり、堅牢性を高めるために欠かせません。

以下は典型的な例です。

begin
  # 何らかの処理
rescue StandardError => e
  puts "エラーが発生しました: #{e.message}"
end

ここでは StandardError を捕捉していますが、必要に応じて RuntimeErrorArgumentError など、より具体的な例外クラスを指定することも可能です。

begin・rescue・ensure・retry・raiseの使い分け

例外処理をより細かく制御するために、ensureretryraise を使い分けます。

ensure

ensure ブロックは、例外が発生しても必ず実行されるコードを記述します。ファイルを閉じる、ロックを解除するなど、リソースの解放に最適です。

begin
  file = File.open('data.txt', 'r')
  # ファイル読み込み
ensure
  file.close if file
end

retry

retry は、例外が発生した際に処理を再試行したい場合に使用します。ただし、無限ループに陥らないよう注意が必要です。

begin
  # ネットワークリクエスト
rescue TimeoutError
  puts "タイムアウト。再試行します。"
  retry
end

raise

例外を自分で発生させる場合に raise を使います。入力チェックやビジネスロジックの失敗時に有効です。

def divide(a, b)
  raise ArgumentError, 'ゼロ除算は不可' if b.zero?
  a / b
end

堅牢なアプリを作るエラーハンドリングの実践

実際のアプリケーションでは、例外捕捉だけでなく、ログ出力やユーザーへのフィードバックも重要です。以下のポイントを押さえて、堅牢性を高めましょう。

  • 例外は rescue で捕捉し、logger.error で詳細を記録する。
  • ユーザーに対しては、システム内部の情報を隠しつつ、適切なメッセージを表示する。
  • 例外が発生した場合でも ensure で必ずリソースを解放する。
  • 再試行が必要なケースは retry を使い、失敗回数に上限を設ける。
  • 重要な処理は raise で明示的に例外を投げ、呼び出し側で適切に処理できるようにする。

例として、Web APIの呼び出しでタイムアウトが発生した場合の処理を示します。

require 'net/http'

def fetch_data(url)
  uri = URI(url)
  begin
    response = Net::HTTP.get_response(uri)
    raise "HTTP Error: #{response.code}" unless response.is_a?(Net::HTTPSuccess)
    response.body
  rescue Net::OpenTimeout, Net::ReadTimeout => e
    logger.warn("タイムアウト: #{e.message}. 再試行します。")
    retry
  rescue StandardError => e
    logger.error("データ取得失敗: #{e.message}")
    raise
  ensure
    # 必要に応じてクリーンアップ
  end
end

このように、例外処理を体系的に設計することで、Ruby実践における堅牢性を大幅に向上させることができます。

この記事はAIによって作成されました。

コメント