私はJava言語を使用しています。オブジェクトが見つかった場合にオブジェクトを返すメソッドがあります。
見つからない場合は、次のことを行う必要があります。
- null を返す
- 例外をスローする
- 他の
ベストプラクティスまたはイディオムはどれですか?
私はJava言語を使用しています。オブジェクトが見つかった場合にオブジェクトを返すメソッドがあります。
見つからない場合は、次のことを行う必要があります。
ベストプラクティスまたはイディオムはどれですか?
常に値が見つかることを期待している場合は、値が見つからない場合に例外をスローします。例外は、問題があったことを意味します。
値が欠落しているか存在している可能性があり、両方がアプリケーション ロジックに対して有効な場合は、null を返します。
さらに重要: コードの他の場所で何をしますか? 一貫性が重要です。
本当にエラーである場合にのみ、例外をスローします。オブジェクトが存在しないことが予期される動作である場合は、null を返します。
それ以外は好みの問題です。
時折のヌルを予測し、特定の方法でそれを処理したい場合は、ヌルを使用してください。
何をするにせよ、3 番目のオプションである「WTF」という文字列を返すことは強くお勧めしません。
null がエラーを示さない場合は、単に null を返します。
null が常にエラーの場合は、例外をスローします。
null が例外になる場合がある場合は、2 つのルーチンをコーディングします。1 つのルーチンは例外をスローし、もう 1 つは出力パラメーターでオブジェクトを返すブール テスト ルーチンであり、オブジェクトが見つからない場合、ルーチンは false を返します。
Try ルーチンを誤用することは困難です。null のチェックを忘れがちです。
したがって、 null がエラーの場合は、次のように記述します
object o = FindObject();
null がエラーでない場合は、次のようにコーディングできます。
if (TryFindObject(out object o)
// Do something with o
else
// o was not found
前に述べたオプションを要約し、いくつかの新しいオプションを追加したかっただけです。
または、これらのオプションを組み合わせることができます。
ゲッターのオーバーロードされたバージョンをいくつか提供して、呼び出し元がどちらに進むかを決定できるようにします。ほとんどの場合、最初のものだけが検索アルゴリズムを実装しており、他のものは最初のものをラップするだけです:
Object findObjectOrNull(String key);
Object findObjectOrThrow(String key) throws SomeException;
Object findObjectOrCreate(String key, SomeClass dataNeededToCreateNewObject);
Object findObjectOrDefault(String key, Object defaultReturnValue);
実装を 1 つだけ提供することを選択した場合でも、そのような命名規則を使用してコントラクトを明確にすることをお勧めします。これは、他の実装も追加することにした場合に役立ちます。
過度に使用するべきではありませんが、多くの異なるエラー処理規則を持つ何百もの異なるアプリケーションで使用するヘルパー クラスを作成する場合に特に役立ちます。
null オブジェクト パターンを使用するか、例外をスローします。
例外をスローする利点:
例を含む詳細な説明については、http: //metatations.com/2011/11/17/returning-null-vs-throwing-an-exception/を参照してください。
言語とコードが促進するかどうかによって異なります。
LBYL は、値を確認する必要があることを示しています (したがって、null を返します)
。EAFP は、操作を試行して失敗するかどうかを確認するように指示します (例外をスローします)。
上記には同意しますが、例外/エラー条件には例外を使用する必要があり、チェックを使用する場合は null を返すのが最適です。
Python での EAFP と LBYL の比較:
http://mail.python.org/pipermail/python-list/2003-May/205182.html
( Web アーカイブ)
使用している API と一貫性を保ちます。
「オブジェクトが見つからないのは例外的なケースですか?」と自問してみてください。プログラムの通常の過程で発生することが予想される場合は、おそらく例外を発生させないでください (例外的な動作ではないため)。
短いバージョン: 例外を使用して、プログラム内の通常の制御フローを処理するのではなく、例外的な動作を処理します。
-アラン。
例外は、契約による設計に関連しています。
オブジェクトのインターフェースは、実際には2つのオブジェクト間のコントラクトであり、呼び出し元はコントラクトを満たす必要があります。そうでない場合、受信者は例外を除いて失敗する可能性があります。2つの可能な契約があります
1)メソッドのすべての入力が有効です。この場合、オブジェクトが見つからない場合はnullを返す必要があります。
2)一部の入力のみが有効です。つまり、オブジェクトが見つかりました。その場合、呼び出し元が入力が正しいかどうかを判断できる2番目のメソッドを提供する必要があります。例えば
is_present(key)
find(key) throws Exception
2番目のコントラクトの両方のメソッドを提供する場合にのみ、例外をスローすることが許可されます。何も見つかりません。
さらにいくつかの提案があります。
コレクションを返す場合は、null を返さないようにし、最初に null チェックを行わずに列挙を処理しやすくする空のコレクションを返します。
いくつかの .NET API は、オブジェクトが見つからない場合に本当に例外的な状況であるかどうかを呼び出し元に選択させる throwOnError パラメーターのパターンを使用します。Type.GetType はこの例です。BCL のもう 1 つの一般的なパターンは、ブール値が返され、値が出力パラメーターを介して渡される TryGet パターンです。
状況によっては、デフォルトまたは動作のないバージョンのいずれかである Null Object パターンを検討することもできます。重要なのは、コード ベース全体で null チェックを避けることです。詳細については、こちらを参照してください http://geekswithblogs.net/dsellers/archive/2006/09/08/90656.aspx
オブジェクトが見つからないことの意味によって異なります。
通常の状態である場合は、null を返します。これは、たまに発生する可能性があるものであり、発信者はそれを確認する必要があります。
エラーの場合、例外をスローする場合、発信者は、オブジェクトの欠落のエラー条件で何をすべきかを決定する必要があります。
最終的にはどちらでも機能しますが、ほとんどの人は一般的に、例外が発生した場合にのみ例外を使用することをお勧めします。
例外をスローする代わりに null を返し、API ドキュメントで null の戻り値の可能性を明確に文書化します。呼び出し元のコードが API を尊重せず、null のケースをチェックしない場合、何らかの「null ポインター例外」が発生する可能性が最も高いでしょう :)
C++ では、オブジェクトを検索するメソッドを設定する 3 つの異なるフレーバーを考えることができます。
オプション A
Object *findObject(Key &key);
オブジェクトが見つからない場合は null を返します。素敵でシンプル。私はこれで行きます。以下の代替アプローチは、out-params を嫌わない人向けです。
オプション B
void findObject(Key &key, Object &found);
オブジェクトを受け取る変数への参照を渡します。オブジェクトが見つからない場合、メソッドは例外をスローしました。この規則は、オブジェクトが見つからないことが実際には予想されない場合に適している可能性があります。そのため、予期しないケースであることを示すために例外をスローします。
オプション C
bool findObject(Key &key, Object &found);
オブジェクトが見つからない場合、メソッドは false を返します。オプション A に対するこの利点は、1 つの明確な手順でエラー ケースを確認できることです。
if (!findObject(myKey, myObj)) { ...
null が例外的な動作と見なされない場合のみを参照してください。私は間違いなく try メソッドに賛成です。ここで述べたように、「本を読む」または「ジャンプする前に見る」必要がないことは明らかです
だから基本的に:
bool TryFindObject(RequestParam request, out ResponseParam response)
これは、ユーザーのコードも明確になることを意味します
...
if(TryFindObject(request, out response)
{
handleSuccess(response)
}
else
{
handleFailure()
}
...
私は単に null を返すことを好み、呼び出し元がそれを適切に処理することに依存しています。(より良い言葉がないため)例外は、このメソッドがオブジェクトを返すことが絶対に「確実」である場合です。その場合、失敗は例外的なはずであり、スローする必要があります。
一部の関数では、パラメーターを追加します。
..., bool verify = true)
true はスローを意味し、false は何らかのエラー戻り値を返すことを意味します。このように、この関数を使用する人は誰でも両方のオプションを利用できます。エラー処理を忘れている人のために、デフォルトは true にする必要があります。
またはオプションを返す
オプションは基本的に、クライアントにブース ケースの処理を強制するコンテナ クラスです。Scala にはこの概念があります。その API を調べてください。
次に、このオブジェクトに T getOrElse(T valueIfNull) のようなメソッドがあり、見つかったオブジェクトを返すか、クライアント指定の代替案を返します。
If it's important for client code to know the difference between found and not found and this is supposed to be a routine behavior, then it's best to return null. Client code can then decide what to do.
nullを返すことを好む -
呼び出し元がチェックせずにそれを使用すると、いずれにしても例外がすぐに発生します。
呼び出し元が実際に使用しない場合は、try
/catch
ブロックに課税しないでください。
通常、null を返す必要があります。メソッドを呼び出すコードは、例外をスローするか、別のことを試みるかを決定する必要があります。
残念ながら、JDK には一貫性がありません。リソース バンドルに存在しないキーにアクセスしようとすると、見つからないという例外が発生し、マップから値を要求すると、存在しない場合は null が返されます。したがって、勝者の回答を次のように変更します。見つかった値がnullになる可能性がある場合は、見つからない場合は例外を発生させ、そうでない場合はnullを返します。したがって、値が見つからない理由を知る必要がある場合は、常に例外を発生させるか、1 つの例外を除いてルールに従います。
メソッドがコレクションを返す場合は、空のコレクションを返します(上記のように)。ただし、Collections.EMPTY_LISTなどは使用しないでください。(Javaの場合)
メソッドが単一のオブジェクトを取得する場合、いくつかのオプションがあります。
nullを返すことにした場合は、注意してください。プロジェクトのプログラマーがあなただけではない場合、実行時にNullPointerExceptions(Javaまたは他の言語の何か)が発生します。したがって、コンパイル時にチェックされないnullを返さないでください。
例外処理のオーバーヘッドについて誰も言及していないと思います-例外をロードして処理するために追加のリソースが必要になるため、真のアプリの強制終了またはプロセス停止イベント(今後は良いよりも害をもたらす)でない限り、私はパスバックすることを選択します呼び出し環境が適切と考える値を解釈できます。
ここでのコンセンサスと思われるものに同意します(「見つからない」が通常の可能な結果である場合はnullを返すか、状況のセマンティクスでオブジェクトが常に見つかる必要がある場合は例外をスローします)。
ただし、特定の状況に応じて意味をなす可能性のある3番目の可能性があります。メソッドは、「見つからない」状態である種のデフォルトオブジェクトを返すことができます。これにより、呼び出し元のコードは、nullチェックや例外キャッチを必要とせずに常に有効なオブジェクトを受け取ることが保証されます。
null を返します。例外はまさにそれです。コードが予期しないことを行うことです。
オブジェクトへの参照を返すことになっている限り、NULL を返すことは良いことです。
ただし、血まみれのもの全体を返す場合 (C++ のように、「return &blah;」ではなく「return blah;」(または「blah」がポインター) の場合、NULL を返すことはできません。その場合、例外をスローするか、成功フラグが設定されていない空のオブジェクトを返すことが、問題に対処する方法です。
例外は例外的であるべきです。nullを返すことが有効な場合は null を返します。
データレイヤーコードでは、次のコードを使用することがあります。これにより、呼び出し元は、「オブジェクトが見つかりません」がエラーが発生したことを意味するかどうかを判断できます。
DataType GetObject(DBConnection conn, string id, bool throwOnNotFound) {
DataType retval = ... // find object in database
if (retval != null || ! throwOnNotFound) {
return retval;
} else {
throw new NoRowsFoundException("DataType object with id {id} not found in database");
}
}
DataType GetObject(DBConnection conn, string id) {
return GetObject(conn, id, true);
}
オブジェクトが含まれていないことは、通常の操作中に発生する可能性があり、呼び出し元が NULL を返すことで処理する必要があります。
オブジェクトが含まれていないことが、呼び出し元のコードまたは内部状態によるバグを示している場合は、アサートを実行します。
オブジェクトが含まれていない場合は、まれなイベントを示します。(アイテムを同時にチェックアウトしているときに、誰かがストアからアイテムを削除したようなものです。) 次に、例外をスローします。
それは、オブジェクトが見つかるかどうかに大きく依存します。何かを示すために例外を使用する必要があるという考え方に従う場合、例外が発生したことになります。
それ以外の場合は、null を返します。
これは、メソッドの性質と使用方法によって異なります。オブジェクトが見つからないことが通常の動作である場合は、null を返します。オブジェクトが常に見つかることが通常の動作である場合は、例外をスローします。
経験則として、例外は何か例外が発生した場合にのみ使用してください。例外のスローとキャッチが通常の操作の一部になるようにコードを記述しないでください。
それが例外的なイベントであると判断されない場合 (つまり、通常の状況では存在するはずです)、スローします。それ以外の場合は、"not found" 値 (null の場合もありますが、null にする必要はありません) を返すか、メソッドが found/notfound のブール値と実際のオブジェクトの out パラメーターを返すようにします。
それはあなたの方法に依存します。メソッドが常に有効なオブジェクトを返すことになっていて、何も見つからない場合は、例外をスローする方法があります。メソッドが、存在するかどうかわからないオブジェクト (連絡担当者の画像など) を返すだけの場合は、エラーを発生させるべきではありません。
このメソッドが実際にオブジェクトを返す場合は、ブール値の true/false を返すメソッドを公開して、a) null をチェックするか、b) 例外をキャッチする必要がない場合もあります。
「その他」のオプションは、検索されたオブジェクトが見つからない場合に返されるデフォルト オブジェクトを含む追加のパラメータを find メソッドに持たせることです。
それ以外の場合は、オブジェクトが見つからないという例外的なケースでない限り、null を返します。