読者です 読者をやめる 読者になる 読者になる

Shin x Blog

PHPをメインにWebシステムを開発してます。Webシステム開発チームの技術サポートも行っています。

アプリケーションから例外を投げる派、投げない派

例外をどのような状況に投げるかもしくは投げないか、というのはわりと意見が分かれるところです。もちろん、プログラミング言語によっても異なりますが、同じプログラミング言語ユーザ同士でも様々です。

基本の考え方

ベースとしては、Effective Java の項目 39 にある下記の方針が参考になります。

例外的な状況の時にのみ例外を使う。

Effective Java

禅問答のような定義ですが、これには異論は無いでしょう。例外を正常フローで利用したり、制御構造に用いるべきではありません。

人によって異なるのは「例外的な状況」の解釈です。

例外的な状況

この「例外的な状況」の解釈は人によって異なるようで、これまでも議論になっていました。これまで聞いた解釈を乱暴に分けると以下の 2 パターンに分かれます。

1. アプリケーションから独自の例外を投げる派

ランタイムやミドルウェア連携などプラットフォーム起因のエラーだけではなく、 アプリケーションやドメインにおけるエラーを例外としてスローする派です。例外クラスも必要に応じて定義します。

例外をエラー処理に積極的に利用する考え方ともいえ、例えば、入力値におけるバリデーションエラーやドメインロジックのエラーにおいても例外を利用します。

2. プラットフォームやフレームワークが投げる例外以外は使わない派

ランタイムやミドルウェア連携などプラットフォーム起因のエラーなど深刻なエラーでのみ例外を利用し、アプリケーションにおけるエラーにおいては例外を利用しない考え方です。

この考え方の人の中には、例外クラスはアプリケーション独自で定義せず、アプリケーションからは例外をスローしない(ランタイムやフレームワーク、ライブラリからの例外のみ扱う)という意見もありました。

アプリケーションのエラーは、戻り値で通知することになります。(特殊な値(null や false)を使ったり、原因別に戻り値を返すなど)

アプリケーションから独自の例外を投げる派の意見

私は、前者の「例外を積極的に使う派」です。理由としては、下記のようなメリットを感じています。 (なお、ここでは PHP を対象として、検査例外のことは考えていません。)

  • [実装][利用] エラー処理を例外に統一できる。
  • [利用] 呼び出す側は例外だけ対応すれば良い。(catch する / 対応しない(上位にスロー))
  • [利用] どのレイヤでエラー処理するかを呼び出し側が選べる。(上位レイヤに伝播できるので、フレームワークの統一的なエラー処理に任せてしまうなどが簡単)
  • [実装] エラー時は例外を投げれば良いので、ガード節の代わりにもなる。
  • [実装] テストでは、@expectedException でテストを書けば良いので、何のテストか分かりやすい。(正常時は例外飛ばないので)
  • [利用] try / catch を書けば、try の中は正常系、catch の中は異常系と処理が分かれて分かりやすい。
  • [利用] 戻り値のエラー判定が不要。例外が飛ばなければ正常終了と判断できる。
  • [利用] 例外クラスが持つ情報量が多い。(特にスタックトレース)

さいごに

例外については、人それぞれ思いがあるようで、議論になりやすいところです。この機会に色々な人の意見を聞いてみたいですね。

今日開催の関西 PHP 勉強会でも、話しましょう。

https://kphpug.doorkeeper.jp/events/55554

EFFECTIVE JAVA 第2版 (The Java Series)

EFFECTIVE JAVA 第2版 (The Java Series)

追記

Twitter へ頂いたコメントをまとめました。色々な意見がありますね。

togetter.com

はてぶでも多くのコメントがあったので、こちらも追記。

b.hatena.ne.jp