23

パブリックメソッドにアサーションを使用できないのはなぜですか?

私はどこかで読んだ

「メソッドは常に引数チェックを強制することを保証するため、アサーションはパブリックメソッドでは不適切です。パブリックメソッドは、アサーションが有効かどうかにかかわらず引数をチェックする必要があります。さらに、assertコンストラクトは指定されたタイプの例外をスローしません。 「」しかスローできませんAssertionError

それで、それは私的な方法にも適用できるのでしょうか?
私は上記の声明をはっきりと理解していませんでした

4

11 に答える 11

27

重要な違いは、誤った値が次の結果であると信じているかどうかです。

a)コードで修正する必要のあるプログラミングのバグ。

b)コードで防ぐことができず、代わりに実行時に処理する必要がある入力エラー。

最初のケースでは、プログラムコードを修正する必要があるため、assertを使用する必要があります。後者の場合は、適切なランタイムを使用するか、例外を確認する必要があります。


IMHOアサーションは、プログラミングエラーを検出するためのものであり、ユーザー/外部入力を検出するためのものではありません。おそらく、外部入力によって呼び出されないパブリックメソッドがある場合、作成者はパブリックメソッドを外部入力として混乱させています。

アサーションを使用して引数をチェックし、プログラミングエラーを検出します。私見これはしばしば彼らにとって最良の使用法です。比較によるプライベートメソッドは、同じクラスのコードによってのみ呼び出される必要があり、それらが適切な単体テストであり、可能なアクセス/使用法が制限されていることを期待する必要があります。

異なる人々が異なる仮定を行うため、パブリックインターフェイスを介してプログラミングエラーが発生する可能性がはるかに高いことがわかりました(アサーションは仮定を文書化してチェックするための良い方法です)内部チェックは、同じプログラマーがアクセスできると期待するほど有用ではありません内部コードベース全体を記述していない場合は、内部コード。

于 2011-03-23T11:53:27.590 に答える
16

次の理由により、パブリックメソッドの引数をチェックするためにアサーションを使用しないでください。

  • アサーションは無効にすることができ、引数チェックは呼び出し元とのメソッドのコントラクトの一部であるため、無効にしないでください。
  • アサーションの失敗は、無効な引数に対して適切な例外をスローしません。

例:

    /**
     * @throws ArithmeticException if divisor is zero
     */ 
    public void int divide(int divisor) {
        if (divisor == 0) {
            throw new ArithmeticException("Cannot divide by zero");
        }
        ...
    }

ここでアサーションを使用した場合、それをオフにすることができAssertionFailedException、それは役に立たず、有益ではない、をスローします。

于 2011-03-23T14:41:15.013 に答える
3

現状では、あなたが引用した文はナンセンスだと私は信じています。

確かに、assertはパラメータの検証用ではありません。

しかし、すべての重要なプログラムには、多くの不変条件があります(またはそうあるべきです)。これは、アサーションが役立つ場合がある場所です。アサーションで不変条件を表現できる場合は、メソッドがパブリックであるかどうかに関係なく、そうしてください。

次に、次のいずれかが発生します。

a)すべてが正常です。
b)実行時に、プログラムは満たされていないアサーションで失敗します。アサーションが正しければ、不変条件に違反しているので、理由を見つけてバグを修正する(または設計を再考する)機会があります。

于 2011-03-23T12:20:36.023 に答える
2

これはおそらく、JavaSEガイド「アサーションを使用したプログラミング」からの元のソースです。

パブリックメソッドのパラメータをチェックするためにアサーションを使用しないでください。メソッドは常に引数チェックを強制することを保証するため、assertは不適切です。アサーションが有効になっているかどうか、引数をチェックする必要があります。さらに、assertコンストラクトは指定されたタイプの例外をスローしません。AssertionErrorのみをスローできます。

これは、パブリックメソッドでのアサーションを禁止するものではありません。パブリックメソッドの引数をチェックするためだけにそれらを禁止します。

アサーションは不変条件をテストします。クラスは、そのプライベートメソッドに送信される実際の引数を制御し、不変条件を保証できます。クラスは、パブリックメソッドに送信される実際の引数を制御しないため、前提条件に違反した場合、アサーションがオフになっている場合でも、例外をスローする必要があります。

アサーションをいつ使用するかについての詳細は、こちらをご覧ください。

于 2011-05-17T22:27:02.760 に答える
1

一般的に、それは健全なようです。これが役立つ場合もありますが。

database update存在することがわかっている要素に対して操作を実行したい場合があると考えてください。次に、ルーチンが成功したかどうかを確認すると便利な場合があります。例:

public void update(Object o) {
   int nUpdatedObjects = dao.update(o);
   assert(nUpdatedObjects == 1)
}

この場合、フェイルファストの原理validateを使用してdaoレイヤーに機能します。

于 2011-03-23T11:52:16.520 に答える
1

アサーションはデバッグ用です。パブリックメソッドは通常、デバッグアサーションによって検証するのではなく、適切な引数チェックを実行し、適切な例外をスローすることによって検証する必要があります。内部オブジェクトの状態を検証したいが、パラメータを検証したくない場合は、これを使用してもかまいません。

于 2011-03-23T11:52:48.677 に答える
1

私は正確に要点ではない応答をします。もちろん、パブリックメソッド(または好きな場所)でassertを使用できます。

重要なのは、何をすべきかどうかということです。私自身、アサーションを使用すべきかどうかについての他の人の反応を完全に理解しています。

しかし、私はアサーションを決して使用しないこと、そしてコードにアサーションが表示されることはめったにないことを認めなければなりません。私は数年しか働いていませんでしたが、私が働いていた4つのまったく異なる会社では、コードにアサーションはありませんでした。フライトを予約するための1,000万行を超えるコードWebアプリケーション、宇宙船コントロールセンター、ハイパーマーケットを管理するソフトウェア、またはバグトラッカーなどです。それらのどれもassertを使用しませんでした。すべての企業は異なるニーズと方法を持っていました。使用されたアサートはありません。

私にとってその理由は単純です。ここの人々は、アサーションはデバッグ用であると言います。それはいいです。また、速度を向上させるためにそれらを非アクティブ化することができます。それも結構です...最初は。プログラムが複雑になるほど、デバッグに時間がかかります。また、一部のバグは、コードカバレッジが100%であっても、広範な統合と検証のテストを行ったとしても、本番環境でのみ検出されます。ユーザーがあなたよりもアプリケーションを使用することになったからです。そして、彼らはそれをあなたと同じように使うことはありません。

本番ログでは、次のようなコードからのスタックトレースが引き続き表示されるため、おかしいです。

catch (MyException e) {
  logger.war("This should never happen",e);
}

つまり、本番環境で何が発生する可能性があるかがわからないということです。

そして、あなたがチェックをする機会があれば、それをしてください。もちろん、ログコメントはここで役立つよりも面白いので、例外をポップアップさせる方がよいでしょう。

すべての場合において、本番環境で無効になるアサーションにしないでください。役に立たないから。例外を発生させる通常のコードにします。必要に応じてログに記録されていることを確認してください。UIにエラーが表示されることを確認します。そして、調査する例外とログを取得できることを確認してください。

重要なのは、いつの日か、警告をポップアップさせるようなことをするユーザーがいるということです。ひどく書かれたコードか何かのせいで、あなたはそれを見るでしょう。つまり、2日間を費やして、プログラムがこの奇妙な動作をする理由を見つける代わりに、開始点で完全なスタックトレースを使用して、2時間で問題を修正できるようになります。

アサーションが無効になっているチェックは、チェックがまったくない場合と同じです。それはあなたが書き、読みそして維持しなければならないコードです...無料で。私は、本番環境でのアサーションが物事を遅くするというパフォーマンスの議論全体を理解しています。はい、いくつかのケースでは、パフォーマンスの問題があります。ほとんどの場合、とにかくほとんど何も得られず、貴重なヒントを失います。

于 2011-05-16T08:32:16.033 に答える
1

パブリックメソッドでアサーションを使用することに何の問題もありません。これらは、メソッドを呼び出しているオブジェクトまたはクラスに関する特定の不変条件(真であると信じているもの)が実際に真であることを確認するために使用できます。

たとえば、ビルダーのpublic build()メソッドで行ったようにアサーションを使用して、ビルダーがそのクラスの独自の内部コードによって正しく初期化されたことを確認できます(それ)。

しかし、絶対にすべきではないのは、パブリックメソッドの引数をチェックするためにアサーションを使用することです。重要な違い。ここにある他の回答は、理由をすでに十分に明確に説明していると思うので、何も繰り返すつもりはありません。

于 2014-06-30T14:08:03.473 に答える
0

アイデアは、誰がパブリックメソッドを使用するかわからないということです。したがって、通常のチェックで不適切な使用から身を守る必要があります。

一方、プライベートメソッドは、現在のチームの開発者のみが使用する必要があるため、チェックは必須ではありません(ただし、IMHOを推奨します)。

したがって、プライベートメソッドの引数の有効性をチェックするには、assertで十分です。

于 2011-03-23T11:55:22.263 に答える
0

この禁止事項は、パブリックインターフェイスにのみ適用されます。

http://download.oracle.com/javase/6/docs/technotes/guides/language/assert.html#preconditionsから:

慣例により、パブリックメソッドの前提条件は、特定の指定された例外をスローする明示的なチェックによって適用されます。

基本的に、慣例では、パブリックインターフェイスは、前提条件をチェックし、AssertionErrorの代わりに特定の例外をスローすることを保証しています。

他のすべての場合、アサーションは非常に価値があり、「契約によるプログラミング」の基礎となります。良い紹介については、http://java.sun.com/developer/technicalArticles/JavaLP/assertionsを参照してください。

  1. Javaには、ある理由でチェックされていない例外があります。これらは、通常はキャッチされるべきではない多くの壊滅的な障害です。すべてのメモリ割り当てでOutOfMemoryErrorがスローされる可能性があります。失敗したアサーション(APIに無効な引数を提供したクライアントのコードのバグ)は、それほど壊滅的ではありません。

  2. アサーションをオフにできるのは事実です。ただし、これは絶対に行わないでください。ただそれをしないでください。コードを実行している誰かがアサーションをオフにすることを恐れている場合は、オフにできない独自の簡単なアサーションクラスをいつでも作成できます。アサーションを使用する原則は変更されていません。

  3. 考慮すべきアサーションに関する唯一のことは、インターフェースのパフォーマンス契約です。これは「暗黙の」契約である可能性もあることに注意してください(つまり、明らかな実装が非常に迅速である必要がある場合、1分かかることは暗黙のパフォーマンス契約の範囲外です)。したがって、パフォーマンス契約の下でアサーションを受け入れられることを確認してください。

于 2011-05-18T18:09:58.150 に答える
0

パブリックメソッドは誰でも呼び出すことができ、引数値として渡すことができるものを制御することはできません。

パブリックメソッドでアサーションを使用して入力引数値を検証したとすると、アサーションが無効になっていると、これらのチェック(検証)が行われない(または実行されない)可能性があり、メソッドの実行から望ましくない結果が得られます。このような望ましくない結果を回避するために、パブリックメソッドの引数値を検証するためにアサーションを使用しないでください。

ここで頭に浮かぶ疑問は、なぜアサーションを使用してプライベートメソッドの引数値を検証するのかということです。

その理由は、プライベートメソッドは、定義されているクラス内から呼び出すことができるためです(インスタンスメソッドまたは静的メインメソッドのいずれかから)。クラスの開発者は、プライベートメソッドについてすべてを知っています。それを呼び出し、渡すパラメータ値。したがって、プライベートメソッドの引数値は、アサーションを使用して安全に検証できます。

于 2017-03-14T10:43:53.897 に答える