12

この質問のコードは私に考えさせました

assert(value>0); //Precondition
if (value>0)
{
  //Doit
}

私はifステートメントを決して書きません。主張するだけで十分です/あなたができるすべて。「早くクラッシュし、頻繁にクラッシュする」

CodeCompleteの状態:

  • assert-statementは、アプリケーションを正しくします
  • if-testはアプリケーションを堅牢にします

無効な入力値を修正したり、コードをスキップしたりして、アプリケーションをより堅牢にしたとは思いません。

assert(value >= 0 );  //Precondition
assert(value <= 90);  //Precondition
if(value < 0)         //Just in case
  value = 0;
if (value > 90)       //Just in case
  value = 90;
//Doit

これらの修正は、外界について行った仮定に基づいています。呼び出し元だけがあなたの関数の「有効な入力値」が何であるかを知っており、彼はあなたの関数を呼び出す前にその有効性をチェックしなければなりません。

CodeCompleteを言い換えると、「アサーションだけに依存しないと、実際のプログラムは乱雑になりすぎます。」

質問:私は間違っていますか、頑固で、愚かで、防御的すぎます...

4

9 に答える 9

10

アサートのみを信頼する場合の問題は、実稼働環境ではアサートがオフになる可能性があることです。ウィキペディアの記事を引用するには:

ほとんどの言語では、アサーションをグローバルに、場合によっては独立して有効または無効にすることができます。アサーションは、多くの場合、開発中に有効になり、最終テスト中および顧客へのリリース時に無効になります。アサーションをチェックせず、アサーションを評価するコストを回避しながら、アサーションに副作用がないと仮定すると、通常の条件下でも同じ結果が得られます。異常な状況では、アサーションチェックを無効にすると、中止されたはずのプログラムが引き続き実行される可能性があります。これが望ましい場合があります。 ウィキペディア

したがって、コードの正確性がそこにあるアサートに依存している場合、深刻な問題が発生する可能性があります。確かに、テスト中にコードが機能した場合は、本番環境でも機能するはずです...コードを処理し、小さな問題を修正しようとしている2番目の人を入力してください...

于 2008-09-11T09:58:39.890 に答える
4

制御する入力を検証するためにアサーションを使用します:プライベートメソッドなど。

制御していない入力を検証するためのifステートメントを使用します:ユーザーが使用するために設計されたパブリックインターフェイス、ユーザー入力テストなど。

アサーションが組み込まれたアプリケーションをテストします。次に、アサーションなしでデプロイします。

于 2008-09-11T10:51:35.800 に答える
3

場合によっては、リリース用にビルドするときにアサートが無効になります。これを制御できない場合があるため(そうでない場合は、assertをオンにしてビルドすることができます)、このようにすることをお勧めします。

入力値を「修正」する際の問題は、呼び出し元が期待どおりの結果を得られないことです。これにより、プログラムのまったく異なる部分で問題が発生したり、クラッシュしたりして、デバッグが悪夢になる可能性があります。

私は通常、ifステートメントで例外をスローして、アサーションが無効になっている場合にアサーションの役割を引き継ぎます。

assert(value>0);
if(value<=0) throw new ArgumentOutOfRangeException("value");
//do stuff
于 2008-09-11T09:59:01.263 に答える
2

私はこの声明に同意しません:

呼び出し元だけがあなたの関数の「有効な入力値」が何であるかを知っており、彼はあなたの関数を呼び出す前にその有効性をチェックしなければなりません。

発信者は、入力値が正しいことを知っていると思うかもしれません。メソッドの作成者だけが、それがどのように機能するかを知っています。プログラマーの最善の目標は、クライアントを「成功の落とし穴」に陥らせることです。特定の場合に、どの動作がより適切であるかを決定する必要があります。誤った入力値が許される場合もあれば、exception\returnエラーをスローする必要がある場合もあります。

アサーションについては、他のコメントを繰り返しますが、アサーションはコード作成者のデバッグ時間チェックであり、コードクライアントではありません。

于 2008-09-11T10:09:10.100 に答える
1

CSクラスから正しく覚えていれば

前提条件は、関数の出力が定義される条件を定義します。関数にエラー条件を処理させる場合、関数はそれらの条件に対して定義され、assertステートメントは必要ありません。

だから私は同意します。通常、両方は必要ありません。

Rikがコメントしたように、リリースされたコードでアサートを削除すると、問題が発生する可能性があります。通常、パフォーマンスが重要な場所を除いて、それは行いません。

于 2008-09-11T09:59:31.697 に答える
1

ほとんどの言語でアサーションをオフにできることを忘れないでください...個人的には、無効な入力のすべての範囲から保護するためのテストを作成する準備ができていれば、そもそもアサーションに煩わされることはありません。

一方、すべてのケースを処理するロジックを記述しない場合(おそらく、無効な入力を試して続行するのは賢明ではないため)、アサーションステートメントを使用して「早期に失敗する」アプローチを採用します。

于 2008-09-11T10:06:35.613 に答える
0

内部関数の場合、自分だけが使用する関数は、 assertのみを使用します。アサートは、テスト中にバグを検出するのに役立ちますが、本番環境でのパフォーマンスを妨げることはありません。

if-conditionsを使用して外部から発信された入力を確認します。外部的には、それはあなた/あなたのチームが制御しテストするコードの外のどこかにあります。

オプションで、両方を持つことができます。これは、本番環境の前に統合テストが行​​われる外部向け機能の場合です。

于 2008-09-11T10:08:10.773 に答える
0

私は、本番コードで(ここで)アサートが消えるという事実を知っていたと述べるべきでした。

ifステートメントが実際に本番コードの無効な入力データを修正する場合、これはデバッグコードのテスト中にアサートがオフにならないことを意味します。つまり、実行したことのないコードを記述したことを意味します。

私にとって、それはORの状況です:

(アンドリューの引用)「無効な入力のすべての範囲から保護します。そもそもアサーションを気にしません。」->if-testを記述します。

(quote aku)「誤った入力値は許される可能性があります」->アサートを書き込みます。

両方我慢できない…

于 2008-09-11T10:44:31.543 に答える
-1

アサーションの問題は、コードからコンパイルできる(そして通常はコンパイルされる)ことです。そのため、コンパイラーによって一方が破棄された場合に備えて、両方の壁を追加する必要があります。

于 2008-09-11T10:00:18.827 に答える