メソッドがnullを返す可能性があるかどうかを表示する方法
-
03-07-2019 - |
質問
投稿後この質問とそのメソッドがnullを返すことになっているかどうか、またはこれがエラー状態と見なされて例外がスローされるべきかどうかを知ることが非常に重要であることに気付きました。 return <!>#8216; null <!>#8217;または例外をスロー。
メソッドを作成していますが、nullを返すか例外をスローするかをすでに知っています。つまり、契約を文書化するという、意思決定を表現する最良の方法は何ですか?
考えられるいくつかの方法:
- 仕様/ドキュメントに書き留めてください(誰か読んでくれますか?)
- メソッド名の一部にする(ここ)
- 例外をスローするすべてのメソッドはnullを返さないと仮定し、 'not'をスローしない might はnullを返すと仮定します。
私は主にJavaについて話していますが、他の言語にも適用される可能性があります:なぜ例外がスローされるか(throws
キーワード)を表現する正式な方法がありますが、nullが返される?
そのようなものがない理由:
public notnull Object methodWhichCannotReturnNull(int i) throws Exception
{
return null; // this would lead to a compiler error!
}
概要と結論
契約を表現する多くの方法があります:
- IDEが(IntelliJとして)サポートしている場合は、
@NotNull
のような注釈を使用することをお勧めします。これは、プログラマに表示され、自動コンパイル時チェックに使用できるためです。これらのサポートを追加するための Eclipse用プラグインがありますが、そうではありませんでした私のために働きます。 - これらがオプションではない場合、
Option<T>
やNotNull<T>
などのカスタムタイプを使用します。これにより、明確さと少なくともランタイムチェックが追加されます。 - とにかく、JavaDocで契約を文書化することは決して痛くなく、時には役立つこともあります。
- メソッド名を使用して戻り値の nullability を文書化することは、私以外は提案しませんでした。非常に冗長であり、必ずしも有用ではないかもしれませんが、
解決
非常に良いフォローアップの質問。 null
は真に特別な値であり、メソッドが@return some value ..., or null if ...
を返す場合は、Javadocで明確に文書化する必要があります(<=>)。コーディングするとき、私は防御的であり、できないと確信しない限り、メソッドが<=>を返すかもしれないと仮定します(たとえば、Javadocがそう言ったため)。
人々はこれが問題であることを認識し、提案された解決策は、注釈を使用して意図を自動的に確認できる方法で述べることです。 JSR 305:ソフトウェア欠陥検出のアノテーション、 JSR 308:Java型の注釈および JetBrainのNullable How-To 。
あなたの例はこのように見えるかもしれませんが、IDE、コンパイラまたは他のコード分析ツールによって拒否されました。
@NotNull
public Object methodWhichCannotReturnNull(int i) throws Exception
{
return null; // this would lead to a compiler error!
}
他のヒント
Option
タイプ。0個または1個の要素を持つリストに非常によく似ています。戻りタイプOption<Object>
は、メソッドがObject
を返すか、タイプNone
の特別な値を返すことを示します。この型は、nullの代わりに使用され、型チェックが改善されています。
例:
public Option<Integer> parseInt(String s) {
try {
return Option.some(Integer.parseInt(s));
}
catch (Exception e) {
return Option.none();
}
}
これを一貫して使用する場合は、IDEのnull警告を有効にするか、通常はnull
を使用するすべての場所でOption.none()
を使用する場合はコードにまったく表示されないMaybe
に対してgrepを使用できますリテラル。
Iterable
はScalaに標準装備されており、HaskellではOption<String>
と呼ばれます。上記のリンクは、 Functional Java と呼ばれるライブラリへのリンクです。そのバージョンは<=>インターフェースを実装し、モノをうまく合成できるモナドメソッドを持っています。たとえば、<=>:
int x = optionalInt.orSome(0);
これを置き換えることができます...
if (myString != null && !"".equals(myString))
...これがある場合、<=> ...
がある場合for (String s : myOptionString)
実際:フレームワークには「非null」ポインター型があり、メソッドが常に値を返すことを示すために返される場合があります。
3つのオプションが表示されます:
- 言語サポートがそれを表現するのを待つ(例: C#?!のこと)
- アスペクトオリエンテーションを使用して独自の言語拡張機能を構築し、それを表現する
- カスタムタイプを使用して表現する
- (ただし、開発者の協力の上に構築されます)命名スキームを使用してそれを示します
Javaの場合、メソッドのJavadoc記述を使用して、戻り値の意味(null可能かどうかなど)を文書化できます。既に述べたように、注釈もここで支援を提供します。
一方、nullを恐れるべきものとは見ていません。 <!> quot; nobody's home <!> quot;という状況があります。意味のある条件です(ただし、Null Objectテクニックにも実際の価値があります)。
確かに、null値でメソッド呼び出しを試みると例外が発生することは事実です。しかし、ゼロで除算しようとするとします。だからと言って、ゼロを排除するためにキャンペーンを続ける必要があるというわけではありません!メソッドのコントラクトを理解し、返される値で正しいことを行う必要があることを意味します。
仕様番号をご覧になりましたか?
独自の注釈(Java)または属性(C#)を記述して、戻り値がnullであることを示すことができます。自動的にチェックするものは何もありません(ただし、.NET 4.0にはコードコントラクトこの種のこと)が、少なくともドキュメントとして機能します。
IntelliJ IDEAの @Nullableおよび@NotNullアノテーションのサポートがいくつかあります。また、これらの注釈(または同様の機能)をJava 7に追加することについての話もあります。残念ながら、それがどこまで進んだか、それがまだ順調に進んでいるかどうかはわかりません。
<!> quot; NotNull <!> quot;という名前のジェネリッククラスを定義して、メソッドが次のようになる可能性があります:
public NotNull<Object> methodWhichCannotReturnNull(int i) throws Exception
{
// the following would lead to a run-time error thown by the
// NotNull constructor, if it's constructed with a null value
return new NotNull<Object>(null);
}
これはまだ実行時(コンパイル時ではない)のチェックですが、次のとおりです。
- メソッドの実装でスローされます(呼び出し元のコードの障害ではありません)
- 自己文書化(呼び出し側は、戻り値の型として
NotNull<T>
を取得していることを知っています)
どんな場合でも、JavaDocsに依存することは避けてください。人々は、署名が自明で自明でないように見える場合にのみそれらを読みます(最初は悪いです)、実際にそれらを読むことを気にする人は、現在より慎重になっているため、nullを間違える可能性が低くなります。
Java 5+を使用している場合、カスタムアノテーションを使用できます。 @MayReturnNull
更新
すべてのコーディング哲学(nullを返す、例外、アサーション、やだやだを使用)は別として、上記があなたの質問に答えることを願っています。デフォルト値を持つプリミティブとは別に、複合型はnullである場合とそうでない場合があり、コードはそれを処理する必要があります。
一般的に言えば、nullの戻り値はデフォルトでAPIの規約に反すると仮定します。ほとんどの場合、<!> quot; normal <!> quot;の間にAPIからnull値が返されないようにコードを設計することができます。実行の流れ。 (たとえば、foo.get(obj)を呼び出してnullに個別のブランチを持たせるのではなく、foo.contains(obj)をチェックします。または、ヌルオブジェクトパターン。
このような方法でAPIを設計できない場合は、Javadocで least にnullをスローできるタイミングと理由を明確に文書化し、場合によっては次のようなカスタム@annotationも使用します。他のいくつかの答えが示唆しているように。