例外処理で堅牢Ruby
Ruby実践での例外処理の基本
Rubyにおける例外処理は、begin と rescue を組み合わせて行います。begin ブロック内で発生した例外は、rescue で捕捉され、プログラムのクラッシュを防ぎます。例外捕捉は、エラーハンドリングの第一歩であり、堅牢性を高めるために欠かせません。
以下は典型的な例です。
begin
# 何らかの処理
rescue StandardError => e
puts "エラーが発生しました: #{e.message}"
end
ここでは StandardError を捕捉していますが、必要に応じて RuntimeError や ArgumentError など、より具体的な例外クラスを指定することも可能です。
begin・rescue・ensure・retry・raiseの使い分け
例外処理をより細かく制御するために、ensure、retry、raise を使い分けます。
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実践における堅牢性を大幅に向上させることができます。
コメント
コメントを投稿