質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
例外

例外(exception)とは、プログラムの処理実行中に発生する、通常の処理の続行を妨げる特殊な事象のことを呼びます。この「例外」が発生した場合に、現在の処理を中断し、変わりに別の処理を実行させる事を「例外処理」と呼びます。

例外処理

例外処理(Exception handling)とは、プログラム実行中に異常が発生した場合、通常フローから外れ、例外として別の処理を行うようにデザインされたプログラミング言語構造です。

Q&A

解決済

5回答

5330閲覧

例外処理は気楽に使っていいものなのでしょうか?

margalet

総合スコア90

例外

例外(exception)とは、プログラムの処理実行中に発生する、通常の処理の続行を妨げる特殊な事象のことを呼びます。この「例外」が発生した場合に、現在の処理を中断し、変わりに別の処理を実行させる事を「例外処理」と呼びます。

例外処理

例外処理(Exception handling)とは、プログラム実行中に異常が発生した場合、通常フローから外れ、例外として別の処理を行うようにデザインされたプログラミング言語構造です。

1グッド

18クリップ

投稿2015/03/19 14:07

ちょっとしたエラーなどで例外を投げていいものなのでしょうか?

例外を投げる場合、投げない場合はどのように区別すればいいのでしょうか?

miyaken912👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答5

0

例外を投げるべきケースとして、いくつか考えてみました。

  • メモリやファイル、通信関係など、外部資源に関わってくるケース

こういったものはエラーが当然起きうるものですし、異常が出ても「無視して続行」したい&それが可能なパターンも少ないでしょうから、例外を使って処理するのが適切でしょう。

  • プログラムのバグでないと起きないような状態に陥った場合

コンパイル時に型チェックしない言語の場合、明らかに処理不能なオブジェクトが引数となってしまったときは、例外を投げるのが、デバッグ時に異常を知らせる手段として適切でしょう(もっとも、不適切なプロパティやメソッド参照で勝手に例外が飛ぶことも考えられますが)。

  • 例外を使うライブラリを内部的に使う場合

この場合、自前で処理できる例外は別として、処理不能な例外は再スローするのが適切と考えます。とはいえ、何もしなくても自動的に上位へ伝わっていくわけですが、それが例外の有利な点とも言えます。

なお、PHPは元がオブジェクト指向でなかったという経緯もあって、SPL系以外のライブラリでは例外を投げず、別枠でエラー処理を行っています。そんなこともあって、PHPでは(例外を多用するようなフレームワーク、ライブラリを使って開発を進める場合はともかく)例外に頼らないほうがいいと考えます。

投稿2015/03/20 08:36

編集2015/03/20 08:39
maisumakun

総合スコア145183

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

ふふふ、このテーマだけで軽く本を書けちゃいますよ。

ちなみに、言語は何を想定して言っていますか?
(HaskellやMLにおける例外と、C++やJavaにおける例外では、ちょっと考え方に違いがありますのでね。)

投稿2015/03/19 14:31

chokojori

総合スコア971

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

margalet

2015/03/19 14:48

PHP と Rubyを想定します。
chokojori

2015/03/19 20:40

PHPとRubyの場合でいうなら、初心者へのアドバイスでは「例外を使わないと表現できない場合にだけ、例外を使う」くらいに慎重で良いかな、と思います。 例外を投げるべきなのは、以下のいずれかの場合だと思います。 1. そのメソッドを呼び出した側に、何らかの後始末をすることなしに先に進んでもらいたくない場合 2. その状況から回復する方法がない場合 PHPやRubyの場合、Javaなどとは異なり、例外が生じる可能性があるメソッドをtry catchせずに呼び出しても、処理系は何も言いません。実行時に、例外が発生したときにだけ、例外が投げられます。逆に言えば、例外をcatchするコードを書かなくても、たまたまた例外が生じなければ、ふつうに動いてしまいます。 例外を生じさせるテストは、得てして網羅的には実施されないので、バグの温床になります。であれば、メソッドの戻り値で結果を返すようにして必ずチェックするように要求しても大差はありません。 上記の2つのケースでは、エラー対応をせずには先に進んでもらうわけに行かないので、例外を投げて、エラー対応していないならプログラムを終了させてかまいません。だから例外を投げるべき、ということになります。 (要するに、安易に例外に頼ると、テストしにくいコードになりますよ、という話です。もちろん、そのことを承知の上で、意図を持って例外を使うのはOKです。)
margalet

2015/03/21 14:19

皆さん、ご回答ありがとうございました。 maisumakun さんのご意見も大変参考になりました。 基本的には返り値でエラーを示唆するものを返すようにし、致命的なもの(プログラムだけで完結しないようなエラーetc...)、処理を確実にしてもらいたいものの場合のみ例外を投げる。 例外と返り値によるエラー判別の使い分けがよくわかりました。
guest

0

PHPのことは知りませんが、Rubyは気軽に例外を使って構いませんよ。
(なんていったってbreakの内部実装が......)


コメントを受けたので追記:

気軽にコードを書いている状態なら気軽に例外を投げて良いと思います。
慎重にコードを書かなくてはいけない状況なら、例外を投げるのも(そしてどのような値を返す場合でも)慎重にすべきです。

投稿2015/03/20 08:02

編集2015/03/20 08:39
hello-world

総合スコア1342

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

chokojori

2015/03/20 08:10

あるメソッドを実装するとき、滅多に生じないケースのために例外を投げるように実装したとして、そのメソッドを利用する側が例外が発生するケースのことを失念していた場合、忘れた頃になって例外がcatchされずにアプリケーションが死ぬことがあると思いますが、それでも気軽に使って良いと言えるのでしょうか。私は、ハッキリとした設計意図を持って、例外を使うようにして、ドキュメントを書くことが大事だと思います。
chokojori

2015/03/20 08:14

言い換えると、メソッドを実装する人が、例外的なケースにおいて、どのように処理すべきかをイメージしないまま、とりあえず例外を投げておけば、そのとき誰かが何とかするだろう...と思って適当に例外を投げるコードを書いたりすることは、私は良いことだと思いません。急いでいるときに、そういうことが仕方なく出てくるのはわかりますが、この質問の文脈では、注意を喚起する方が有益だと思いますが、どうですか?
hello-world

2015/03/20 08:34

例えば文字列を数値に変換する関数を定義したとします。 その関数に不正な文字列(例えば"A"とか)が渡させた場合の戻り値は 1. 0を返す(整数のデフォルト値、ちなみに `to_i` メソッドです) 2. nilを返す 3. 例外を投げる( `Integer`メソッドがコレです) の3通りが考えられます。 しかし結局のところどのような失敗値を返したとしても、プログラマがフォローしない限りバグが生み出されてしまいます。 プログラマが 気軽にデフォルト値を返しても、気軽にnilを返しても、気軽に例外を投げても バグは同様に発生するのです 0を受け取って不正な状態のままプログラムが継続して実行されるよりは停止したほうがまだマシな場合も多くあります。 > 私は、ハッキリとした設計意図を持って、例外を使うようにして、ドキュメントを書くことが大事だと思います。 はい、そのとおりだと思います。 しかしながら例外だけを特別扱いするのではなくどのような値を返す場合でもハッキリとした設計意図をもってドキュメントに書くことが大事だと思います。
chokojori

2015/03/20 13:23

> 不正な状態のままプログラムが継続して実行されるよりは停止したほうがまだマシな場合も多くあります。 はい。しかし、そのことはそれなりにしっかり考えて判断しなければならないわけで「気軽」にどんどん例外を使えば良い、とはならないと思います。 要するに、例外を投げるにせよ、失敗の値を返すにせよ、「気軽」はありえない、相応に「真剣」に検討すべき、ということです。
hello-world

2015/03/20 14:00

> 要するに、例外を投げるにせよ、失敗の値を返すにせよ、「気軽」はありえない、相応に「真剣」に検討すべき、ということです。 はい、それに関しては完全に同意します。 単なる読み取り方の問題ですが、 質問者の「例外処理は気楽に使っていいものなのでしょうか? 」という問いは 「プログラム全体は慎重に書くが、例外だけは気楽に使ってよいか?」ではなく 「例外も他のプログラムの仕組みと同様に気楽に使ってよいか?」という意味だと解釈したので、 「同様でいいよ」のつもりで「気軽に使って構いませんよ」と回答しました。 あと、気楽を気軽と誤読していましたがそれほど意味は変わらないと思うので無視してください。
chokojori

2015/03/20 22:37

例外を特別扱いする必要はなく、戻り値の設計と同様に行なうということに同意です。 個人的には、HaskellやMLをやると、バグのないプログラムを書くにはどのような配慮が必要かがより深く理解できるようになり、例外の使い方もわかるようになると思います。 (もっと言えば、PHPやRubyの持ち味は、未完成のプログラムがともかくも動く、というところにあると思っていて、であれば見通しの良い、その人にとって書きやく読みやすいコードであれば理論にはこだわらなくて良い、ということになるとも思います。)
guest

0

例外を投げることによりthrow以降の処理が飛ばされることになりますが、これを補完するためにcatchの処理が複雑になるようであれば投げるべきではないでしょう。

それでも複数のエラー処理をcatchで効率的にハンドリングできるように書けるのであれば、throwは有効です。throwを多用されているプログラマーはそうしたコーディングをされているかと思います。

それは別としてtry,catchの用法には慣れて積極的に利用した方が良いコーディングになるかと思います。
使用しなければ検知できない事象もありますし、catchにはエラーハンドリングが集約されるので可読性が良いです。catchした例外メッセージをlog出力することでテストにも運用にも有用となるでしょう。

投稿2015/03/20 03:43

BlueMoon

総合スコア1339

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

私は、基本的に、エラー処理を一元化するために、例外を使ってます。

ネストされた一番底で、エラーをはかれても、例えるなら、Cを使っているのに、その奥で動作している機械語からエラーが出るようなものなので。

デバック時の利点としては、
Aの呼び出しで問題なく、Bの呼び出しで問題があるなら原因はネストの底ではなくBなど、原因の追及が楽
場合によっては、Bに合わせてネストの底を修正することもできます。

実環境時の利点としては、エラー処理の一元化
ネストの底でいちいちエラー処理を書いていては、実動作を書いているのか、エラー処理を書いているのかわからなくなるようなこともあります。
理解不能な動作になったら、処理を止めて例外を投げる。例外を投げると処理が止まるのも利点ですね。
そして一番上層で、ファイルに出力するなりなんなり。

デバック環境での例外処理は、実環境では、消える、あるいは、動作しないようにかけると尚いいと思います。

>例外を投げる場合、投げない場合はどのように区別すればいいのでしょうか?
対処できるかできないかで分けたらよいと思います。たとえば、1/0 を、ありえないとするか、∞とするかの違いなど、代替案があるなら、投げる必要はない、は言うまでもないですね。
処理を止める必要があるかどうかも指針になると思います。
それ以降を止めて、別処理に移れるのも例外の利点です。

例外を利用するかしないか、という話になると、また別問題ですが
goto や、returan などを駆使すれば、処理を止めて、も可能ですが、嫌われる以前に複雑になりがちですし、読んだ側は、それがエラーなのか何なのかわかりにくいと思います。
便利なら使えばいいですし、エラーオブジェクトの分メモリを消費するというのも、処理によっては考えないといけないですが、重くて落ちそうなときに吐いたエラーをスローするのもどうかと思います。

投稿2015/03/20 14:18

miya

総合スコア81

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問