はじめに
実務で開発を行なっていると、避けて通れないの例外処理。
趣味の範疇では、特段考慮しなくても問題ないかもしれませんが、実際にサービスとして提供するとなるとそうもいきません。
そこで、今一度例外設計について色々調べてみましたが、調べれば調べるほど指針や考え方は多岐にわたり、深い知識と経験が必要です。
そのため、本記事では自分なりの解釈をまとめ、徐々に加筆していくことで、読者の方々に有益な情報を提供できるように努めます。
注意点
本記事では、例外処理の構文についての解説はしません。
また、PHPの使用を前提としております。
そもそも例外とは
例外処理とは、想定できた予期せぬ事態(例外)に備える処理です。
システム的な例外が起きてしまった際には、ソフトウェアが何らかの対処を施す事が要求されます。
具体的には、何らかの理由でDBに接続できない。サーバーが停止しているなどが、それに該当します。
それらは、プログラマが適切にプログラムを修正する事で解決します。
そのため、想定できた予期せぬ事態(例外)に対する処理を我々プログラマは適切に施さねばなりません。
そうでないと、システムが異常終了することがあります。異常終了が発生した場合、エラーを調査するための時間がかかるだけでなく、システムの安定性や信頼性にも悪影響を与える可能性があります。
したがって、想定できた予期せぬ事態(例外)に対する適切な処理が重要です。
いつ使うのか
書籍『達人プログラマー』によると、例外について以下のように記されています。
「すべての例外ハンドラを除去しても、このプログラムは動作可能だろうか?」と自問してください。答えが「ノー」であれば、例外ではない状況下で例外が使われているはずです。
また、具体的な例として、下記のような例が挙げられております。
● ファイルが存在しないという状況が通常起こりえないのであれば、それは例外として処理
● ファイルが存在しないという状況が普通に起こりえるのであれば、例外ではなくエラーとして処理
この例から、例外処理は通常起こらない問題が発生した場合に使用するべきだと言えます。
もう少し、深ぼってみると、通常は起こらない問題が発生した場合というのは、異常な状態であると言えます。
異常な状態であるということは、プログラムの実行を停止しても構わない状態にあると言えます。例えば、下記のような状態。
● 何らかの理由でDBに接続できない
● 必要な戻り値が戻ってこなかった(プログラム上のバグ)
などなど。
アプリケーションが上記のようなDB接続できない状態にもかかわらず、プログラムの実行を続けてしまうと、あたかもDBにデータを保存できたかのような(正常に処理を行なわれたかのように)振る舞ってしまうかもしれません。
そのため、通常は起こらない問題が発生した場合は、プログラムの実行を停止しても構わない状態にあると言えるわけです。もっと言えば、通常通りプログラムを実行できませんね。
こういった普通はおかしくなることがあり得ない状態であり、且つプログラムの実行を停止しても構わない場合に例外を使うべきです。
一方、ユーザーの誤入力や誤操作等については、例外ではなくエラーとして処理します。これは、プログラムの実行を停止せざるを得ない問題ではなく、ユーザーの入力変更によって回復可能な状態であるからです。
ユーザーの入力ミス等が発生した場合にアプリケーションを終了させず、エラーメッセージと共に再入力を促すWebフォームページをユーザーに返すケースがそれにあたると思います。
また、『達人プログラマー』は、例外処理を過剰に使用することが、プログラムの実行効率を低下させることに繋がる可能性があると警告しています。したがって、プログラマーは、例外処理を使うべき場面を正確に判断する必要があります。
対処について
さて、ここではユーザー側で対処する事ができない異常(例外)への対処方法を考えていきます。
対処方法
このような異常への対処方法は、プログラマが適切にプログラムを修正することです。 なぜなら、ユーザーの誤操作が原因の異常であれば、ユーザーに対して誤操作を取り消してもらい、正常な操作を行ってもらう事で対処できますが、そうでないケースではプログラマに状況を報告して対処する必要があります。
また、例外が発生した後にプログラムを実行し続けると、以降のプログラムの実行結果が正しいことが保証できなくなる可能性があるため、プログラムを終了させることが重要です。
メッセージ
ならば、どのようにして状況を伝えるのかというと、発生した内容をログに出力することで伝えます。ここで重要なこととして、出力内容は、開発者向けにするということです。言い換えると、ユーザー向けのメッセージを出すものではありません。
→あくまで、プログラマが適切にプログラムを修正することを必要としているため
好ましくない例
local.ERROR: ユーザーの取得に失敗しました。
好ましい例
local.ERROR: ユーザーの取得に失敗しました。 ["[object] (App\\Exceptions\\TestApplication\\TestException(code: 0):...etc
例外の握り潰し
これは、例外をなかったことにすることです。先にも述べた通り、例外が発生した際には通常通りプログラムを実行できません。そのため、適切なハンドリングが必要になります。
もし、例外が発生したにもかかわらず、握り潰してしまうと、例外が闇に葬られ何事もなかったかのように処理は続行してしまいます。
まとめ
例外設計は非常に奥が深いです。
一般的には、例外は普通はおかしくなることがあり得ない状態であり、且つプログラムの実行を停止せざるを得ない状況
場合に使用されます。
ただし、例外やエラー処理については、プログラミング言語やアプリケーションによって異なる考え方や設計があり、一様な扱いはできません。そのため、悩んだ時は開発メンバーと相談しながら設計することが重要です。
参考サイト
Railsアプリケーションにおけるエラー処理(例外設計)の考え方
例外設計について勉強
エラーと例外とセキュアコーディング/セキュアプログラミング