エラー処理はいろんなパターンがあって、ケースバイケースとぶん投げられることも多いんですが、これ実は3種類に分類して考えるとかなりすっきりします。
その3種類とは
- システムの想定内のエラー
- システムの想定外のエラー
- バグ
です。
1. システムの想定内のエラー
システムの想定内のエラーとは例えば
- 指定のIDのユーザーが見つからない
- 必須の入力パラメータがない
などの事象です。
これらはプログラムコード内ではエラークラスとして返されたり例外としてthrowされることもありますが、実際にはエラーではありません。
なので、これらはアプリケーションとしてその場合どうするか?をちゃんと規定してその通りに実装することが大切です。
Webアプリケーションでは多くの場合40xのレスポンスを返すことになります。
2. システムの想定外のエラー
システムの想定外のエラーとは例えば
- DBが落ちている
- 外部のWebサービスとの通信エラー
などです。
これらはアプリケーション開発者にはどうしようもできないことが多く、できることといえば運用者にすみやかに通知する仕組みを作るぐらいです。
Webアプリケーションでは503を返すことが多いです。
システムをもっと大きな視点から捉えた場合にはDBのダウンまで想定することもありますが、それはアプリケーションの外側の話なのでアプリケーション自体が意識する必要はほとんどありません。
3. バグ
バグは文字通りアプリケーション開発者が仕込んでしまったバグです。
どんなに優れたシステムであっても絶対にバグはありえるものと想定しておくことが大切です。
バグはできるだけ早期に検知できることが大切です。
例えばif〜elseの分岐で最後のelseには絶対に来ることがないとわかっている場合はそこで例外を投げちゃいましょう。
来るはずのないところに来たということはその前段階のどこかにバグがあります。
そこを通してしまうとそれだけバグの検知が遅れることになります。
assertやrequireを使うのも同様にバグの検知をできるだけ早くするためです。
Webアプリケーションの場合は通常500エラーになります。
(ほとんどのWebアプリケーションフレームワークは開発者の書くコードにバグがあることを想定しているので例外をキャッチした場合は500エラーになります。)
同じエラーでも分類が違うことがある
ここでは「ユーザー登録時にメールアドレスの登録をチェックする」という処理を考えてみます。
色々な実装方法がありますが、ここではDBのUnique制約にひっかけてエラーをキャッチするという方法を取ったとします。
この時に発生するUnique制約エラーはエラーではありません。システム内で想定されている挙動だからです。
しかし、ここ以外の想定外の処理でUnique制約エラーが発生した場合はおそらくはバグ(もしくは仕様バグ)です。
このように同じエラーであっても、その意味するところが全く別のものであることがあり得ます。
ここで分類を考えずに目の前のエラーだけを見て「DBのUnique制約エラーはどう処理すれば良いだろう?」とか考えてしまうと迷路にハマることになります。
まとめ
エラー処理でお悩みの人はわりとこの3つをごっちゃにして考えている人が多いです。
- システムの想定内、想定外のエラーを区別していない
- バグがありえることを想定していない
- または、その両方
ここをちゃんと区別すると、かなりスッキリすることが多いです。
まずは目の前のエラーがどこに分類されるものであるかを考えてみましょう。
ここをクリアにしてもそれでもなお悩ましいという人は多分本当に難しいんだと思うので頑張って悩んでください。
おしまい