例外処理で安心なプログラムを作ろう

学習の目標

本章では、以下の内容を学習します。

  • エラーとは何か、プログラムでなぜエラーが起きるのかを理解する
  • 例外処理の基本的な考え方と書き方を習得する
  • begin/rescueを使ったエラー対応の方法を学ぶ
  • メソッド定義での簡単な例外処理の書き方を理解する
  • raiseを使ってエラーメッセージを表示する方法を学ぶ

はじめに

プログラミングを学習していると、必ず「エラー」という壁にぶつかります。

「あれ?なんでエラーになるんだろう…」「また赤い文字が出てきた…」という経験は、誰にでもあるものです。

エラーは一見すると大敵のように思えますが、実はエラーを上手に扱うことで、より安心して動くプログラムを作ることができるんです。

今回は、Rubyでエラーと上手に付き合うための技術「例外処理」について学んでいきましょう。難しそうな名前ですが、考え方はとてもシンプルです。

エラーとは何か

まずは具体的な例を通じて、エラーについて理解していきましょう。

身近なエラー例:0での割り算

シンプルな割り算のメソッドを作ってみます。error.rbというファイルを用意して、以下のコードを書いてみましょう。

def divide(a, b)
a / b
end
puts divide(10, 2) # 5が表示される
puts divide(10, 0) # エラー!

このプログラムを実行すると、最初の divide(10, 2) は問題なく 5 という結果が表示されます。しかし、2番目の divide(10, 0) を実行すると、エラーメッセージが表示されてプログラムが停止します。

0で割ることはできないので、このようなエラーが発生するのです。数学では「無限大」と言いますが、コンピュータはこの計算を正確に処理できないため、エラーとして扱います。

日常生活で見かけるエラー

皆さんも日常生活で、次のようなエラーメッセージを見たことがあるかもしれません。

  • 「インターネットに接続できません」
  • 「ファイルが見つかりません」
  • 「メモリーが不足しています」

これらも一種のエラーです。アプリは単に停止するのではなく、ユーザーに状況を知らせてから、適切に対応していますね。

例外処理の基本

エラーが起きたときの対処方法を「例外処理」と呼びます。これは、「エラーが発生しても、プログラムが途中で止まらないようにする仕組み」です。

例外処理の考え方

例外処理は、日常生活での「もしも対応」に似ています。例えば:

「お店に行ってりんごを買ってくる。もし売り切れていたら、みかんを買ってくる」

これをプログラムで表現したのが例外処理です。Rubyでは、beginrescueというキーワードを使います。

begin/rescueの基本的な使い方

先ほどの割り算のメソッドを修正して、エラーに対処できるようにしてみましょう。

def divide(a, b)
begin
a / b # ここでエラーが起きる可能性がある
rescue
puts "0で割ることはできません"
0 # エラー時の戻り値
end
end
puts divide(10, 2) # 5が表示される
puts divide(10, 0) # "0で割ることはできません"と表示され、0が返される

この例を見てみましょう。beginrescueは、以下のような意味があります。

  • begin:「まずはこの処理を試してみる」
  • rescue:「エラーが起きたら、こちらの処理を行う」

beginブロックの中でエラーが発生すると、プログラムは停止せず、rescueブロックの処理が実行されます。これにより、エラーが発生しても、プログラムが途中で止まることなく処理を続けることができます。

実行結果を確認しよう

このコードを実行すると、次のような結果になります。

  1. divide(10, 2)では、10÷2=5が計算され、5が表示されます。
  2. divide(10, 0)では、0で割ろうとしてエラーが発生しますが、rescueブロックの処理が実行されて、「0で割ることはできません」というメッセージが表示され、0が返されます。

エラーメッセージを表示した上で、プログラムは停止せずに続行されるのです。これが例外処理の基本的な働きです。

メソッド定義での簡単な例外処理

実は、メソッド全体でエラーを処理する場合は、もっと簡単な書き方があります。

beginを省略した例外処理

メソッド定義の中では、beginを省略してrescueだけを書くことができます。

def divide(a, b)
a / b # この行でエラーが起きる可能性がある
rescue
puts "0で割ることはできません"
0 # エラー時の戻り値
end
puts divide(10, 2) # 5が表示される
puts divide(10, 0) # "0で割ることはできません"と表示され、0が返される

この書き方でも、先ほどと同じように動作します。メソッド全体でエラーを処理する場合は、このシンプルな書き方の方が読みやすいでしょう。

例外処理を使った実践例

例外処理は、ユーザーからの入力を処理するときなど、様々な場面で役立ちます。例えば、ユーザーが数値を入力すると期待しているのに、文字列を入力した場合などです。

def get_age
puts "年齢を入力してください:"
age = gets.chomp
return age.to_i # 文字列を数値に変換
rescue
puts "正しい年齢を入力してください"
0 # エラー時のデフォルト値
end

この例では、ユーザーが入力した文字列を数値に変換しようとしています。もし変換できない文字列(例:「abc」など)が入力された場合、エラーが発生しますが、例外処理によってプログラムは停止せず、適切なメッセージを表示して処理を続行します。

エラーメッセージを自分で作る

時には、自分でエラーメッセージを表示したい場合もあります。例えば、ユーザーに適切な入力方法を案内したいときなどです。

raiseを使ったエラーメッセージの表示

Rubyでは、raiseというキーワードを使って自分でエラーメッセージを表示することができます。

def greet(name)
if name.empty?
raise "名前を入力してください" # 空の名前が渡された場合、エラーを発生させる
end
puts "こんにちは、#{name}さん"
end
begin
greet("") # 空の名前を渡す
rescue => e # eにはエラー情報が入る
puts "エラー: #{e.message}" # エラーメッセージを表示
end

この例では、空の名前が渡された場合に「名前を入力してください」というメッセージを含むエラーが発生します。begin/rescueで囲んでいるので、プログラムは停止せずに「エラー: 名前を入力してください」と表示されます。

raiseの使い方について詳しく見てみよう

raiseは、「ここでエラーを発生させてください」という指示です。例えば、ユーザーからの入力値をチェックして、不適切な値が渡された場合にエラーを発生させるといった使い方ができます。

エラーが発生すると、通常はプログラムが停止しますが、begin/rescueで囲んでおくと、プログラムは停止せずにrescueブロックの処理が実行されます。

def check_password(password)
if password.length < 8
raise "パスワードは8文字以上にしてください"
end
puts "パスワードは有効です"
end
begin
check_password("abc") # 短すぎるパスワード
rescue => e
puts "エラー: #{e.message}" # エラーメッセージを表示
end

この例では、短すぎるパスワードが渡された場合にエラーが発生し、「エラー: パスワードは8文字以上にしてください」というメッセージが表示されます。

raiseを使うと、プログラムの中で「このケースは正常ではない」ということを明確に示すことができます。また、エラーメッセージを自分で設定できるので、ユーザーに分かりやすい説明を提供することができます。

例外処理のメリット

例外処理を使うことで、プログラムはより安心して動作するようになります。例外処理のメリットをいくつか見てみましょう。

プログラムの途中停止を防ぐ

例外処理を使わないと、エラーが発生した時点でプログラムが停止してしまいます。多くの処理を行うプログラムでは、一部でエラーが発生しても、残りの処理は正常に実行したいことがよくあります。

例えば、100人分のデータを処理している途中で1人分のデータにエラーがあっても、残りの99人分は正常に処理したいですよね。そこで例外処理を使えば、エラーが発生しても処理を続行することができます。

ユーザーに分かりやすい説明を提供する

プログラム内部のエラーメッセージは、技術的で分かりにくいことが多いです。例外処理を使うと、ユーザーにとって分かりやすいメッセージを表示することができます。

「メモリ不足エラー(コード: E0123)が発生しました」よりも、「画像が大きすぎるため処理できません。もう少し小さい画像を選んでください」の方が、ユーザーにとって親切なのです。

デバッグ情報を記録する

エラーが発生したとき、その情報をログファイルに記録しておくと、後からどのようなエラーが発生したのかを確認することができます。例外処理を使えば、エラー情報を取得してログに記録することができます。

def process_data(data)
begin
# データ処理のコード
rescue => e
puts "エラーが発生しました: #{e.message}"
# ここでログファイルにエラー情報を記録する
end
end

実践的な例:簡単なファイル読み込み

例外処理の実践的な例として、ファイルの読み込みを見てみましょう。ファイルの読み込みでは、ファイルが見つからないなど、様々なエラーが発生する可能性があります。

def read_file(filename)
begin
content = File.read(filename)
return content
rescue
puts "ファイル '#{filename}' の読み込みに失敗しました"
return nil
end
end
content = read_file("example.txt")
if content
puts "ファイルの内容:"
puts content
else
puts "ファイルを読み込めませんでした"
end

この例では、ファイルの読み込みに失敗した場合(ファイルが存在しない場合など)、エラーメッセージを表示してnilを返しています。呼び出し元では、戻り値がnilかどうかをチェックすることで、ファイルの読み込みが成功したかどうかを判断しています。

まとめ

本章では、Rubyにおける例外処理について学びました。例外処理は、エラーが発生してもプログラムが途中で止まらないようにする仕組みです。

以下の内容を理解できたことと思います。

  • エラー(例外)とは、プログラムが正常に実行できない状況のこと
  • begin/rescueを使って例外処理を行うことで、エラーが発生してもプログラムが停止しないようにできる
  • メソッド定義では、beginを省略した簡潔な例外処理が可能
  • raiseを使って意図的にエラーを発生させ、メッセージを表示することができる
  • 例外処理を使うと、プログラムの堅牢性が高まり、ユーザーにも優しいプログラムになる

例外処理は、初めは少し難しく感じるかもしれませんが、使い方を覚えると非常に便利です。エラーをただの「問題」と考えるのではなく、「予期しうる状況」として適切に対処することで、より良いプログラムを作ることができます。

このセクションは有料サブスクリプションへの登録、またはログインが必要です。完全なコンテンツにアクセスするには、料金ページ(/pricing)をご覧ください。購入済みの場合は、ログインしてください。

Starterプランでより詳しく学習

この先のコンテンツを読むにはStarterプラン以上が必要です。より詳細な解説、実践的なサンプルコード、演習問題にアクセスして学習を深めましょう。

作成者:とまだ
Previous
可変長引数で引数の数を柔軟にしよう