「プログラミングエラー」の例外-アプローチは適切ですか?


9

私は現在、例外の使用方法を改善しようとしていますが、プログラミングエラーを示す例外(たとえば、誰かが引数としてnullを渡した、またはオブジェクトが破棄された後にメソッドを呼び出した)と、呼び出し側の障害ではない操作(I / O例外など)。

これらの2種類の例外はどのように異なる方法で処理する必要がありますか?エラー例外を明示的に文書化する必要があると思いますか、または関連する前提条件を文書化するだけで十分ですか?また、明らかな場合(たとえば、ObjectDisposedException破棄されたオブジェクトでメソッドを呼び出す場合)、前提条件またはエラー例外のドキュメントを省略できますか?


私は通常、ビジネスの例外という別のカテゴリの例外を区別します。これらは、ユーザーが詳細に関心のあるエラー状態を参照します。私は通常、これらの例外をチェックします。
ベルチン

回答:


2

私はあなたが正しい軌道に乗っていると思います。スローされる可能性のあるすべての例外をスロー、キャッチ、または文書化することは、あまり意味がありません。製品の厳格性により、より高度な例外的な雇用と文書化が必要になる場合があります(システムの特定の安全上重要な側面など)。

契約の概念を使用して、特にダウンストリームの呼び出し元(たとえば、パブリックメンバーまたは保護されたメンバーに似ているもの)の前提条件(および事後条件)を識別する、より防御的な戦略は、多くの場合、より効果的でより柔軟になります。これは実装だけでなくドキュメントにも当てはまります。開発者が何が期待されているかを知っていれば、ルールに従う可能性が高くなり、作成したコードが混乱したり誤用されたりする可能性が低くなります。

文書化する必要がある一般的なものの一部には、nullパラメーターのケースが含まれます。多くの場合、それらを使用すると、通常は予期されない結果が得られますが、さまざまな理由で許可されて使用されるため、場合によっては柔軟性が高くなります。nullまたはその他の特別な非有理値(負の時間や負の数量など)を許可するパラメーターを持つメンバーのコンシューマーとして、それらが識別され、説明されることを期待しています。

null以外のパラメーターの場合、パブリックまたは保護されたメンバーのコンシューマーとして、nullは許可されないことを知りたいです。特定のコンテキストで有効な値の範囲を知りたい。通常の範囲外の値を使用した場合の結果を知りたいが、それ以外の場合は別の呼び出しコンテキストで有効です(たとえば、型の値は通常、どの操作でも有効ですが、ここでは無効です-ブール値パラメーターのように有効な値としてfalseを期待しないでください。

プラットフォーム、またはよく知られているインターフェースに関する限り、それを文書化するために極端に行く必要はないと思います。ただし、開発者として、プラットフォームのガイダンスと実装を変える機会があるので、ガイダンスが価値あるものであることにどのように従うかをメモしてください。

IDisposableに固有であり、多くの場合、このインターフェイスの実装は、明示的な破棄プロセスよりも優先される代替方法を提供します。これらの場合は、推奨される方法を強調し、明示的な廃棄は推奨されないことに注意してください。


許可される値を文書化する必要性を理解しましたが、関数が表示された場合performReadCommand(ICommand cmd, int replySizeBytes)、cmdにはnullを、replySizeBytesには負の値を指定できると思いますか?IMOのドキュメントは、これらの値が実際に許可されている場合にのみ必要です。おそらく、replySizeBytesに対して0が有効かどうかを確認する必要があります。
Medo42

実装によっては、どちらも「有効」になる場合があります。あなたまたは私であり、ここの誰もがnullまたは負の値がその署名に適切であるとは期待していませんが、そうである可能性があります。リーダーがブロッキングで永続的なプロセスであり、cmdがnullの場合は、リーダーが使用するコマンドを変更せず、前のコマンドを使用して次の読み取りに進む環境を検討してください。その場合、コマンドをパラメーターとして省略したより適切なメソッドシグネチャを定義して使用するのが理想的ですが、そうでない場合もあります。
JustinC、2012年

2

ここに私自身の考えがあります。これが最善の方法であると確信しているわけではないことに注意してください。そのため、最初にこの質問を作成しました。

私が理解している限り、実際の呼び出し元がプログラミングエラーの例外を実際に処理することはほとんど意味がありません。代わりに、前提条件が満たされていることを確認する必要があります。タスクの境界にある「外部」例外ハンドラーのみがそれらをキャッチする必要があるため、タスクが失敗した場合でもシステムを実行し続けることができます。

クライアントコードが誤ってエラー例外をキャッチすることなく「失敗」例外を確実にキャッチできるようにするために、すべての失敗例外に対して独自の例外クラスを作成し、それらをスローするメソッドにドキュメント化します。Javaで例外をチェックするようにします。

最近まで、メソッドがスローする可能性のあるすべての例外を文書化しようとしましたが、エラーが発生しないことを示すことができるまで、呼び出しチェーンのすべてのメソッドで文書化する必要がある不当なリストが作成される場合があります。代わりに、要約/パラメーターの説明で前提条件を文書化し、満たされていない場合に何が起こるかについては触れません。いずれにせよ、人々はこれらの例外を明示的にキャッチしようとすべきではないので、それらのタイプを文書化する必要はありません。

前提条件を文書化するために、明白なことは不必要な混乱を生み出すだけです-メソッドにnullを渡しても意味がない場合、それが文書化されていなくても、呼び出し側がnullを渡すと例外を予期する必要があります。ObjectDisposedExceptionの場合も同じです。このインターフェイスは非常に広く使用されているため、Disposeを呼び出す人は、誰もオブジェクトを使い続けないようにする責任を認識しています。


1

合理的な経験則:

  1. 修正できる例外をすべてキャッチします。
  2. 修正できないが何か有用なことを言うことができる例外をキャッチ、コメント、再スローします。
  3. 処理できない例外をキャッチしたり、デフォルトの処理よりも適切に診断したりしないでください。

トップレベルの致命的ではない例外ハンドラーを使用して、以下で処理できなかったものをトラップして、アプリケーションのフォールオーバーを防止しようとする場合がありますが、これは特定のアプリケーションに強く依存します。たとえば、iOSアプリケーションは可能な限りトラップすることを好みます。コマンドラインアプリは、ほとんど例外をまったくトラップしない場合、完全に問題ない可能性があります。


0

Javaでさえ、すべての例外を「文書化」するわけではありません。すべてのthrown例外がthrows句で言及されるという要件にもかかわらず、コードのどの行でもRuntimeException、メソッドシグネチャでそれを宣言する必要なしにをスローできます。


ただし、これは一般的なアドバイスに反します。具体的には、Effective Java、第2版、アイテム62は「各メソッドによってスローされるすべての例外を文書化する」です。実際、Blochは、チェックされていない例外は一般にプログラミングエラーのためのものであることを認めていますが、メソッドの前提条件を文書化する「最良の方法」であるため、それらも注意深く文書化する必要があります。私が同意するかどうかはわかりません。実行を文書化する場合は、それらをインターフェイスコントラクトの一部にし、実装が変更された場合に同じままにするためにコードを追加する必要がある場合があります。
Medo42

1
すべての専門家には、カウンターエキスパートがいます。かなり有名なThinking in Javaの作者であるBruce Eckelは、かつてプロチェック例外の陣営に属していたが、立場が変わった。Eckelsと C#の作成者であるAnders Hejlsbergの間には、例外をチェックしていない素晴らしい議論があります。
ロスパターソン

0

それを行うための標準的な方法は、Javaアプローチを使用することです。プログラミングエラーは、チェックされていない例外であり、高速な障害を確実にするためにキャッチされるべきではありません。契約エラーはチェックされた例外であり、クライアントが適切に処理する必要があります。


2
(例えば)計算された(またはエラー値の)NULLをプログラミングエラーまたはコントラクトエラーと見なしますか?私はあなたの区別で行きます、しかし境界はそれほど明確ではありません:)
Andrew

渡された引数(null引数や無効なものなど)からnullが計算される場合、それはコントラクトエラーです。不良コードのためにnullが計算された場合、それはプログラミングエラーです。nullが計算されることになっている場合、それはエラーではありません。この例には、あいまいさはほとんど見られません。
J.Ashworth、2012年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.