アサーションを使用するか、例外をスローするか?


38

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

それで、いつアサーションを使用するのが適切であり、いつ例外をスローするのが適切であるのか、どちらを行う必要がありますか?


3
この質問はstackoverflowで尋ねられるべきだと思いますが、おそらくそこで何十回も質問されているので、あなたはすでに多くの答えを見つけるかもしれません。
user281377

回答:


50

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

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


外部入力に例外を使用することの良い点。私は、あまりにもそれに出力を追加したい-問題をなどのファイル/データベース/書き込みを作成しようとしたとき
ChrisF

13
そして必然的に、これらのアサーションが実稼働環境でトリガーされることに気付くでしょう。アサートで個人的なものを検証するための+1 !「入力を完全に制御しているときにアサートを使用する」と言えますか?
フランクシェラー

1
少なくともJavaでは、通常、-eaコマンドラインパラメーターを使用してアサーションチェックを有効にする必要があります。つまり、アサーションは、明示的に有効にしない限り、実質的にノーオペレーションです。
ビルミシェル

29

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

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


これはかなり良い方法です。ユーザーが間違ったものを入力した場合、例外をスローします。入力は正しいが、何かがまだ間違っている場合は、アサートをスローします。
マーティーンウルハク

3

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

たとえば、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
  ...
}

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


2
同じ条件のアサートの背後に優雅な動作を配置するのは良い考えだとは思いません。必然的に、正常な動作は製品版にのみ存在するため、正常な動作を処理するはずのコードのテストは不十分であり、コードが保護されていなかった場合と同じくらい悪い場合でもクラッシュします。
セバスチャンレッド

0

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

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.