24

質問をざっと見て、私は最近assertJavaでキーワードを発見しました。最初はワクワクしていました。まだ知らなかった便利なもの!入力パラメータの有効性をチェックするためのより効率的な方法!イェーイ学習!

しかし、それから私は詳しく調べました。私の熱意は、1つの単純な事実によって、「完全に消し去られる」ほど「和らげられる」ことはありませんでした。アサーションをオフにすることができます。*

これは悪夢のように聞こえます。listOfStuff入力がである場合にコードを続行したくないと主張している場合、null一体なぜその主張を無視したいのでしょうか。プロダクションコードの一部をデバッグしlistOfStuffていて、誤って渡された可能性があるがnull、そのアサーションがトリガーされたというログファイルの証拠が見当たらない場合は、listOfStuff実際に有効な値が送信されたとは信じられません。また、アサーションが完全にオフになっている可能性についても説明する必要があります。

そして、これは私がコードをデバッグしていることを前提としています。アサーションに慣れていない人は、それを見て、(かなり合理的に)アサーションメッセージがログに表示されlistOfStuffない場合は問題ではないと想定する可能性があります。あなたの最初の出会いがassert野生であった場合、それが完全にオフにされる可能性があることさえあなたに起こりますか?結局のところ、try/catchブロックを無効にできるコマンドラインオプションがあるわけではありません。

そのすべてが私の質問に私をもたらします(そしてこれ質問であり、暴言の言い訳ではありません!私は約束します!):

私は何が欠けていますか?

assertJavaの実装を、私が認めているよりもはるかに便利にするニュアンスはありますか?コマンドラインから有効/無効にする機能は、実際にはいくつかのコンテキストで非常に価値がありますか?次のようなステートメントの代わりに本番コードで使用することを想定している場合、私はそれをどういうわけか誤解していif (listOfStuff == null) barf();ますか?

私はここで私が得ていない重要な何かがあるように感じます。

*技術的に言えば、実際にはデフォルトでオフになっています。それらをオンにするには、邪魔にならないようにする必要があります。しかし、それでも、それらを完全にノックアウトすることができます。


編集: 悟りが要求され、悟りが受け取られました。

何よりもまずデバッグツールであるという概念assertは、私にとって意味のあるものにするために非常に長い道のりを歩んでいます。

開発者は悪い入力は不可能だと考えているため、本番環境では重要なプライベートメソッドの入力チェックを無効にする必要があるという考えにまだ問題があります。私の経験では、成熟したプロダクションコードは、さまざまな程度の正気度の急速に変化する要件を対象としたさまざまな程度のスキルを持つ人々によって何年にもわたって開発された、狂った、広大なものです。そして、悪い入力が本当に不可能であるとしても、今から6か月後のずさんなメンテナンスコーディングの一部がそれを変える可能性があります。 提供されているリンクgustafc(ありがとう!)には、例としてこれが含まれています。

assert interval > 0 && interval <= 1000/MAX_REFRESH_RATE : interval;

本番環境でこのような単純なチェックを無効にすると、ばかげて楽観的になります。ただし、これはコーディング哲学の違いであり、壊れた機能ではありません。

さらに、私は間違いなくこのようなものの価値を見ることができます:

assert reallyExpensiveSanityCheck(someObject) : someObject;

この機能を理解するのを手伝ってくれたすべての人に感謝します。大変感謝しております。

4

12 に答える 12

23

assertDesign by Contractの便利な部分です。そのコンテキストでは、アサーションは次の場所で使用できます。

  • 前提条件チェック。
  • 事後条件チェック。
  • 中間結果チェック。
  • クラス不変チェック。

アサーションは評価にコストがかかる場合があります (たとえば、クラスのパブリック メソッドを呼び出す前後に保持する必要があるクラス不変条件を考えてみましょう)。通常、アサーションはデバッグ ビルドとテスト目的でのみ必要です。あり得ないこと、つまりバグがあることと同義のことを主張します。アサーションは、独自のセマンティクスに対してコードを検証します。

アサーションは入力検証メカニズムではありません。本番環境で入力が実際に正しいか間違っている可能性がある場合、つまり入出力レイヤーの場合は、例外や古き良き条件付きチェックなどの他の方法を使用してください。

于 2010-05-03T15:52:03.670 に答える
19

Java のアサーションは、実際には引数の検証のために作成されたものではありません。アサーションは古いものの代わりに使用されるべきではないと具体的に述べられてIllegalArgumentExceptionいます(また、C っぽい言語でのアサーションの使用方法でもありません)。それらは内部検証のためにあり、コードを見ても明らかではないコードについて仮定を立てることができます。

それらをオフにすることに関しては、C(++) でもそうしますが、誰かがアサートなしのビルドを持っている場合、それをオンにする方法はありません。Java では、適切な VM パラメーターを使用してアプリを再起動するだけです。

于 2010-05-03T15:47:40.447 に答える
4

アサートの使用法が解釈され、想定される方法だと思います。

実際のプロダクション コードにチェックを追加したい場合は、If を直接使用したり、他の条件ステートメントを使用したりしないでください。

これらは言語に既に存在するため、アサートのアイデアは、開発者がこの状態が発生することを本当に予期していない場合にのみ、開発者にアサーションを追加させることだけでした。

たとえば、オブジェクトが null であることを確認する場合、開発者がプライベート メソッドを作成し、それをクラスの 2 つの場所 (これは理想的な例ではありませんが、プライベート メソッドでは機能する可能性があります) から呼び出したとします。今日の時点で、オブジェクトがnullになる方法がないことがわかっているため、不必要なチェックを追加しますしかし、誰かが明日このメソッドをnull引数で呼び出すと、開発者の単体テストで、これはアサーションの存在のためにキャッチされる可能性があり、最終的なコードではまだ実行しませんif チェックは必要ありません。

于 2010-05-03T15:46:38.110 に答える
4

私がこれまでアサーションで見たすべての言語には、アサーションを遮断する機能が備わっています。アサーションを書くときは、「これはばかげている。これが偽である可能性は世界にない」と考える必要があります。それが偽である可能性があると思われる場合は、エラー チェックを行う必要があります。アサーションは、何かがひどくうまくいかない場合に、開発中にあなたを助けるためのものです。本番用のコードをビルドするときは、それらを無効にして時間を節約し、(できれば)余分なチェックを回避します

于 2010-05-03T15:46:39.793 に答える
4

アサーションは、コードが実際に満たされると確信していることを保証するためのものです。これは、製品の開発段階でのデバッグを支援するものであり、通常、コードがリリースされるときには省略されます。

私は何が欠けていますか?

アサーションを意図したとおりに使用していません。あなたは「入力パラメータの有効性をチェックする」と言った - それはまさにアサーションで検証したくない種類のものです。

アサーションが失敗した場合、コードに 100% バグがあるという考えです。アサーションは、バグが表面化するよりも早くバグを特定するためによく使用されます。

于 2010-05-03T15:50:45.203 に答える
3

アサーションは、コードメンテナにとって本当に優れた簡潔なドキュメントツールです。

たとえば、私は次のように書くことができます。

fooはnull以外で、0より大きい必要があります

または、これをプログラムの本体に入れます。

assert foo != null;
assert foo.value > 0;

これらは、元のプログラマーの不変条件を表現するためのプライベート/パッケージプライベートメソッドを文書化するために非常に価値があります。

追加のボーナスとして、サブシステムが不安定な動作を開始したときに、アサートをオンにして、検証を即座に追加できます。

于 2010-05-03T16:12:14.973 に答える
3

これはほぼ正しいように聞こえます。アサーションは、コードのデバッグに役立つ単なるツールです。特に製品コードでは、常にオンにする必要はありません。

たとえば、C または C++ では、アサーションはリリース ビルドで無効になっています。

于 2010-05-03T15:50:50.177 に答える
2

アサートをオフにできなかった場合、なぜそれらが存在する必要があるのでしょうか。

入力の妥当性チェックを実行したい場合は、簡単に書くことができます

if (foobar<=0) throw new BadFoobarException();

または、メッセージボックスなどのコンテキストで役立つものをポップアップします。

アサートの要点は、デバッグ用にオンにしたり、本番用にオフにしたりできるものであるということです。

于 2010-05-03T17:15:05.657 に答える
1

これは に関するあなたの質問に直接答えるものではありませんが、 guava / google-collectionsのPreconditionsクラスをassert確認することをお勧めします。次のような素敵なものを書くことができます(静的インポートを使用):

// throw NPE if listOfStuff is null
this.listOfStuff = checkNotNull(listOfStuff);

// same, but the NPE will have "listOfStuff" as its message
this.listOfStuff = checkNotNull(listOfStuff, "listOfStuff"); 

このようなものが必要なようです (オフにすることはできません)。

于 2010-05-03T15:49:54.247 に答える
1

アサーションは、エンド ユーザーが見るためのものではありません。これらはプログラマー向けであるため、開発中にコードが正しいことを実行していることを確認できます。テストが完了すると、通常、アサーションはパフォーマンス上の理由からオフになります。

listOfStuff が null になるなど、本番環境で何か問題が発生することが予想される場合は、コードが十分にテストされていないか、コードに入力を許可する前に入力をサニタイズしていません。いずれにせよ、「if (bad stuff) { throw an exception }」の方がよいでしょう。アサーションは、本番用ではなく、テスト/開発用です。

于 2010-05-03T15:50:25.203 に答える
1

assertアサーションが失敗するたびにエンドユーザーに 1 ドル支払う意思がある場合は、を使用します。

アサーションの失敗は、プログラムの設計エラーを示しているはずです。

アサーションは、指定された述語が常に成立することを知り、保証するような方法でプログラムを設計したことを示しています。

アサーションは私のコードの読者にとって有用です。(2)以前の実行とテストケースでは、プロパティは実際に保持されていました。

私の賭けは、私のコードのクライアントが規則を守り、彼と私が合意した契約を順守することを前提としています。このコントラクトは、寛容 (すべての入力値が許可され、有効性がチェックされている) か、要求が厳しい (クライアントと私は、[前提条件として説明されている] 特定の入力値を提供しないことに同意し、これらの値をチェックすることを望まない) 場合があります。何度も何度も)。クライアントが規則を守り、それでも私の主張が失敗した場合、クライアントは何らかの補償を受ける権利があります.

于 2011-07-17T15:46:27.227 に答える
0

アサーションは、回復可能なコードの問題を示したり、デバッグを支援したりするためのものです。プログラムの停止など、より重大なエラーには、より破壊的なメカニズムを使用する必要があります。

また、後でデバッグやテストのシナリオでアプリケーションが失敗する前に回復不能なエラーをキャッチして、問題を絞り込むためにも使用できます。この理由の 1 つは、整合性チェックによって、本番環境で十分にテストされたコードのパフォーマンスが低下しないようにするためです。

また、リソース リークなど、状況が望ましくない場合もありますが、プログラムを停止した場合の結果は、続行した場合の結果よりも悪くなります。

于 2010-05-03T15:45:04.400 に答える