web-dev-qa-db-ja.com

アサーションを使用する場合と例外を使用する場合

関数を作成するときは、そのようなエラーをできるだけ早く検出するために、関数への入力が有効であることを確認したいことがよくあります(これらは前提条件と呼ばれていると思います)。前提条件が満たされない場合、私は常に例外をスローしました。しかし、私はこれがベストプラクティスであるかどうか、またそうでない場合はアサーションがより適切であるかどうかを疑い始めています。

それで、私はいつ行うべきですか:アサーションを使用するのが適切な場合と、例外をスローするのが適切な場合は?

45
gablin

アサーションは、論理的に不可能であるはずの条件を検証するためにのみ使用する必要があります(読み取り:健全性チェック)。これらの条件は、独自のコードによって生成された入力にのみ基づいている必要があります。外部入力に基づくチェックでは、例外を使用する必要があります。

私が従う傾向がある単純なルールは、アサートを使用してプライベート関数の引数を検証し、パブリック/保護された関数の引数に例外を使用することです。

アサーションは、プログラミングエラーを見つけるために使用されます。プログラムは、すべてのアサーションが削除されたときにも同様に機能する必要があります。

一方、例外は、プログラムが完全な場合でも起こり得る状況に対するものです。それらは、ハードウェア、ネットワーク、ユーザーなどの外部の影響によって引き起こされます。

34
user281377

典型的なプログラミング方法は、本番/リリースビルドからアサーションをコンパイルすることです。アサーションは、内部テスト中にのみ、仮定の失敗をキャッチするのに役立ちます。外部機関の行動を想定しないでください。そのため、ネットワークまたはユーザーからのイベントをアサートしないでください。また、アサーションが失敗した場合に備えて、プロダクションビルドの処理コードを記述することもお勧めします。

たとえばCでは、

int printf(const char *fmt, ...)
{
  assert(fmt);  // may fail in debug build but not in production build
  if (!fmt) return -1; // handle gracefully in production build
  ...
}

例外は本番ビルドに組み込まれることを意図しています。例外の代替策は、アサーションではなくエラーを返すことです。

3
aufather

answer をstackoverflowサイトに投稿しましたが、それでもここに投稿すると役立つ場合があります。

アサーションが使用され、

  1. 不要な状態を続行するのではなく、プログラムをすぐに停止する場合。これはしばしば Fail-fast の哲学に関連しています [1] システム設計。

  2. アプリケーションを重大な不整合または回復不能な状態に導く可能性がある最初の予期しない状態でカスケード障害(つまり、マイクロサービス)の特定の可能性がある場合。

  3. システムのバグをデバッグ期間のみに検出する場合。言語がサポートしている場合は、本番環境でそれらを無効にすることができます。

  4. 内部の実装ミスにより予期しない状態が発生し、外部システム(つまり、呼び出し元)が不要な状態を制御できないことがすでにわかっている場合。

例外が使用され、

  1. 外部システムの障害(パラメーターの誤り、リソースの不足など)が原因で予期しない状態が発生したことがわかっている場合。

  2. アプリケーションの機能的な品質を維持したまま、条件を代替パスでバックアップできることがわかっている場合(つまり、呼び出し元または外部システムからの適切なパラメーターを使用した別の呼び出しでうまく機能する可能性があります)。

  3. ログに記録し、開発者に不要な状態を知らせたいが、大したことではない場合。

注:「アサーションを使用すればするほど、より堅牢なシステムが得られます」。対照的に、「例外を使用して例外を処理するほど、システムの回復力が向上します」。


[1]フェイルファスト-システム設計では、フェイルファストシステムは、インターフェースを介して、故障を示す可能性のある状態を即座に報告するシステムです。 。フェイルファストシステムは通常、欠陥のある可能性のあるプロセスを続行しようとするのではなく、通常の操作を停止するように設計されています。このような設計では、運用のいくつかのポイントでシステムの状態をチェックすることが多いため、障害を早期に検出できます。フェイルファストモジュールの役割は、エラーを検出し、次に高いレベルのシステムにエラーを処理させることです。

1

私にとってのアサートの1つの問題は、Javaではデフォルトで無効になっていることです。

(予期しない形式で)不良データが発生した場合のデータ破損を回避するために、プログラム(何年も無人で実行されている可能性がある)をできるだけ早くクラッシュさせる必要があるフェイルファースト戦略を使用します。これは、私たちがチェックを使用するものであり、アサートを使用することにより、基本的にそれらがアクティブにならないようにするリスクがあります。

0
user1249