nullの@Nonnullアノテーションが付けられたパラメーターを確認しますか?


19

FindBugsの使用を開始し、パラメーターに@Nonnull適切な注釈を付けました。サイクルの早い段階でバグを指摘することは非常に効果的です。これまでnullGuava's を使用するためにこれらの引数のチェックを続けてきましたが、エッジcheckNotNullnullのみチェックすることをお勧めしますnull。たとえば、SOAPリクエストのようにチェックされずに値が入る場所です。

// service layer accessible from outside
public Person createPerson(@CheckForNull String name) {
    return new Person(Preconditions.checkNotNull(name));
}

...

// internal constructor accessed only by the service layer
public Person(@Nonnull String name) {
    this.name = Preconditions.checkNotNull(name);  // remove this check?
}

値自体を@Nonnullブロックしないことを理解していnullます。

ただし、FindBugsは値がマークされていないフィールドからマークされたフィールドに転送される場所を指すので、渡さ@Nonnullれるnullすべての場所でこれらの値をチェックすることなく、これらのケースをキャッチするためにそれに依存することはできませんか?システム?ツールを信頼し、これらの詳細なチェックを避けたいですか?

結論:下の2番目のnullチェックを削除しても安全に思えますが、それは悪い習慣ですか?

この質問は、彼がnullを期待していない場合、nullをチェックするべきであるとおそらくあまりにも似ていますが、私は@Nonnull注釈に関連して具体的に尋ねています。

回答:


6

FindBugを信頼していない場合は、アサーションを使用するオプションがあります。この方法により、ユーザーMSaltersが言及する問題を回避できますが、まだチェックがあります。もちろん、このようなフェイルファーストアプローチが実行可能でない場合、つまり、例外をキャッチする必要がある場合、このアプローチは適用できない場合があります。

そして、それが悪い習慣であるかどうかという質問にさらに答えること。まあ、これは議論の余地がありますが、私はそうは思わないでしょう。このFindBugアノテーションは、契約の原則による設計に準拠した軽い仕様であると考えています。

契約による設計では、メソッドとその呼び出し元の間で契約を確立します。契約は、メソッドを呼び出すときに呼び出し元が満たすことに同意する前提条件と、前提条件が満たされた場合に実行後にメソッドによって順番に満たされる事後条件で構成されます。

この開発方法の利点の1つは、いわゆる防御的なプログラミングスタイル(すべての無効なパラメーター値を明示的にチェックするなど)を回避できることです。代わりに、契約に依存し、冗長なチェックを回避してパフォーマンスと可読性を向上させることができます。

コントラクトはランタイムアサーションチェックに使用できます。これは、コントラクトが壊れた場合にプログラムを失敗させる上記のフェイルファースト原則に従い、エラーの原因を特定する手がかりを与えます。(失敗した前提条件は、呼び出し側が何か間違ったことをしたことを意味し、失敗した後条件は、指定されたメソッドの実装エラーを示します)

さらに、コントラクトは静的分析に使用できます。静的分析は、実際に実行せずにソースコードに関する結論を引き出します。

@nonnull注釈は、ツールFindBugsによる静的分析に使用される前提条件と見なすことができます。実行時アサーションチェックなどのアプローチ、つまりフェイルファースト戦略を好む場合は、アサーションステートメントを組み込みJavaとして使用することを検討する必要があります。または、Java Modeling Language(JML)などの動作インターフェース仕様言語を使用して、より洗練された仕様戦略に適応することもできます。

JMLは、特別なJavaコメントに仕様が埋め込まれたJavaの拡張機能です。このアプローチの利点は、実装の詳細ではなく仕様のみに依存し、前述のランタイムアサーションチェックツールなどの仕様を利用するさまざまなツールを使用する開発アプローチを使用しても、洗練された仕様を使用できることです。単体テストまたはドキュメントの自動生成。

@nonnullが(軽い)契約であるという私の見解を共有する場合、この原則の元のアイデアは防御的なプログラミングを回避することであるため、追加のチェックを追加しないのが一般的です。


2
これはまさに@Nonnull契約仕様として私が使用している方法です。私は契約の背後にある防御チェックを削除しており、これまでのところ何の問題もありませんでした。
デビッドハークネス

4

さて、なぜあなたが書かないのかを考えてください

this.name = Preconditions.checkNotNull(name);  // Might be necessary
that.name = Preconditions.checkNotNull(this.name);  // Who knows?

プログラミングは黒魔術ではありません。変数が突然ヌルになることはありません。変数がNullではないことがわかっていて、変数が変更されていないことがわかっている場合はチェックしないでください。

あなたがそれをチェックするなら、将来のプログラマー(おそらくあなた)はそのチェックがそこにある理由を見つけるのに多くの時間を費やすでしょう。結局のところ、小切手はそこにあるに違いありません。それで、あなたは何を見落としていますか?


3
@Nonnull契約規定は、発信者が通過してはならないことをnullコンストラクタに、そしてFindBugsのは許すかもしれません呼び出し見つけるために静的解析を使用していますnull--specificallyマークされていない値を渡す呼び出し@Nonnull自分自身を。ただし、呼び出し元はnullFindBugsからの警告を自由に渡して無視できます。
デビッドハークネス

プログラミングは理想的には黒魔術ではありません。そこ♬〜ᕕ(ᐛ)ᕗうちの同時実行コードの一部を扱うときに残念なことに、警告と驚きは特に、たくさん
ティム・ハーパー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.