オブジェクトが見つかった場合にそれを返すことになっているメソッドがあります。
見つからない場合は、次のようにします。
常に値を見つけることを期待しているのであれば、もしそれが欠けていれば例外を投げます。例外は問題があることを意味します。
値が欠落しているか存在する可能性があり、両方がアプリケーションロジックに対して有効である場合は、nullを返します。
もっと重要:あなたはコードの他の場所で何をしますか?一貫性が重要です。
本当にエラーである場合にのみ例外をスローします。オブジェクトが存在しないことが予想される動作である場合は、nullを返します。
そうでなければそれは好みの問題です。
一般的な規則として、メソッドが常にオブジェクトを返すべきであるならば、例外を持って行きなさい。時折のnullを予想してそれをある方法で処理したい場合は、nullで進めてください。
あなたが何をするにしても、私は第三の選択肢に対して強く忠告します: "WTF"を言う文字列を返すこと。
Nullがエラーを示さない場合は、単にnullを返します。
Nullが常にエラーの場合は、例外をスローします。
Nullがときどき例外となる場合は、2つのルーチンをコーディングしてください。一方のルーチンは例外をスローし、もう一方のルーチンは出力パラメータでオブジェクトを返すブール値テストルーチンで、オブジェクトが見つからなかった場合は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オブジェクトパターンを使用するか、例外をスローしてください。
使用しているAPIと一致していること。
「オブジェクトが見つからないのは例外的なケースなのか」と自問してみてください。それがあなたのプログラムの通常の過程で起こると予想されるなら、あなたはおそらく例外を発生させるべきではありません(それは例外的な振る舞いではないので)。
ショートバージョン:プログラムの通常の制御の流れを処理するのではなく、例外的な動作を処理するために例外を使用します。
- アラン。
それはあなたの言語とコードが促進するかどうかによって異なります:LBYL(あなたが跳躍する前に見て)またはEAFP(許可より許しを求めることが容易)
LBYLは値をチェックすべきだと言っています(だからnullを返してください)
EAFPは単に操作を試して失敗したかどうかを確認するように言います(例外をスローします)
私は上記に同意しますが、例外は例外/エラー条件に使用されるべきであり、チェックを使用するときはnullを返すことが最善です。
PythonでのEAFPとLBYLの比較:
http://mail.python.org/pipermail/python-list/2003-May/205182.html ( Web Archive )
例外をスローする利点
例を使用した詳細な説明については、 http://metatations.com/2011/11/17/returning-null-vs-throwing-an-exception/ を参照してください。
例外は契約によるデザインに関連しています。
オブジェクトのインターフェースは実際には2つのオブジェクト間の契約です。呼び出し側はその契約を満たさなければなりません。そうでなければ受信側は例外で失敗するかもしれません。 2つの可能な契約があります
1)すべての入力メソッドが有効である場合、オブジェクトが見つからないときはnullを返さなければなりません。
2)いくつかの入力のみが有効であり、すなわちそれは発見されたオブジェクトをもたらすものである。その場合、呼び出し側が入力が正しいかどうかを判断できるようにする2番目の方法を提供する必要があります。例えば
is_present(key)
find(key) throws Exception
もしあなたが2番目の契約の両方の方法を提供するならば、あなたは例外を投げることを許されます何も見つからないということです!
ここにもう少し提案があります。
コレクションを返す場合、nullを返さないようにするには、最初にnullチェックを行わずに列挙を処理しやすくする空のコレクションを返します。
いくつかの.NET APIはthrownOnErrorパラメータのパターンを使用します。これは、オブジェクトが見つからない場合に、それが本当に例外的な状況であるかどうかの選択を呼び出し側に与えます。 Type.GetTypeはその一例です。 BCLのもう1つの一般的なパターンは、ブール値が返され、値が出力パラメータを介して渡されるTryGetパターンです。
また、デフォルトまたは動作のないバージョンのいずれかになる可能性がある状況で、Null Objectパターンを検討することもできます。重要なのは、コードベース全体でnullチェックを回避することです。詳細についてはこちらを参照してください http://geekswithblogs.net/dsellers/archive/2006/09/08/90656.aspx
私はただnullを返すことを好み、それを適切に処理するために呼び出し側に頼ります。 (より良いWordがないための)例外は、このメソッドがオブジェクトを返すことが絶対に '確実'な場合です。その場合、失敗は例外的なはずであり、投げるべきです。
オブジェクトが見つからないという意味によって異なります。
通常の状況であれば、nullを返します。これは時々起こるかもしれないちょうど何かであり、呼び出し側はそれをチェックする必要があります。
それがエラーであるならば、それから例外を投げます、呼び出し側は行方不明のオブジェクトのエラー条件で何をするべきか決めるべきです。
究極的にはどちらでもうまくいくでしょうが、ほとんどの人は一般的に、何か例外的なことが起こった場合にのみ例外を使用することをお勧めします。
nullが例外的な振る舞いと見なされていない場合のみを参照してください。これは明らかにtryメソッドのためのもので、明確になっています。
だから基本的に:
bool TryFindObject(RequestParam request, out ResponseParam response)
これは、ユーザーのコードも明らかになることを意味します
...
if(TryFindObject(request, out response)
{
handleSuccess(response)
}
else
{
handleFailure()
}
...
いくつかの関数で私はパラメータを追加します。
..., bool verify = true)
Trueはスローを、falseは何らかのエラー戻り値を返すことを意味します。このように、この関数を使う人は両方とも選択肢があります。エラー処理を忘れる人のために、デフォルトはtrueであるべきです。
例外をスローせずにnullを返し、nullの戻り値の可能性をAPIドキュメントに明確に記載してください。呼び出し元のコードがAPIを尊重してnullケースをチェックしない場合は、何らかの理由で "nullポインタ例外"が発生する可能性があります。
C++では、オブジェクトを見つけるメソッドを設定する3つの異なるフレーバーを考えることができます。
オプションA
Object *findObject(Key &key);
オブジェクトが見つからない場合はnullを返します。素敵でシンプルです。私はこれと一緒に行きます。以下の代替的なアプローチは、アウトパラムを嫌いではない人々のためのものです。
オプションB
void findObject(Key &key, Object &found);
オブジェクトを受け取る変数への参照を渡します。オブジェクトが見つからない場合、メソッドは例外をスローしました。オブジェクトが見つからないことが本当に予想されない場合は、この規約がおそらくより適しています。したがって、予期しないケースであることを示すために例外をスローします。
オプションC
bool findObject(Key &key, Object &found);
オブジェクトが見つからない場合、このメソッドはfalseを返します。これがオプションAよりも優れている点は、1つの明確なステップでエラーのケースを確認できることです。
if (!findObject(myKey, myObj)) { ...
またはOptionを返す
オプションは基本的にクライアントにブースケースを処理させるコンテナクラスです。 Scalaにはこの概念があります。それをAPIで調べてください。
それから、このオブジェクトに対してT getOrElse(T valueIfNull)のようなメソッドを見つけると、見つかったオブジェクト、あるいはすべてのクライアント指定を返します。
クライアントコードが見つかったものと見つからなかったものの違いを知ることが重要であり、これが日常的な動作であると想定される場合、nullを返すことが最善です。その後、クライアントコードは何をすべきかを決定できます。
通常はnullを返します。メソッドを呼び出すコードは、例外をスローするか他のことを試みるかを決定する必要があります。
残念ながらJDKは矛盾しています。リソースバンドル内の存在しないキーにアクセスしようとすると例外が見つからず、mapから値を要求したときに存在しない場合はnullになります。それで、私は勝者の答えを次のように変更します。見つかった値がnullになる可能性がある場合は、見つからない場合は例外を発生させ、それ以外の場合はnullを返します。だから、値が見つからない理由を知る必要があるなら、例外を1つ例外として出してください。
私はここでのコンセンサスと思われるものに同意します(「見つからない」が通常起こり得る結果である場合はnullを返し、状況の意味論でオブジェクトが常に見つかることを要求する場合は例外をスローします)。
しかし、あなたの特定の状況によっては意味があるかもしれない3番目の可能性があります。あなたのメソッドはある種のデフォルトオブジェクトを "見つからない"状態で返すことができ、呼び出し元のコードがnullチェックや例外キャッチの必要なしに常に有効なオブジェクトを受け取ることを保証することができます。
Nullを返す -
呼び出し側が確認せずにそれを使用すると、とにかくそこで例外が発生します。
呼び出し側が実際にそれを使用していない場合は、try
/catch
ブロックに課税しないでください。
例外は例外にする必要があります。 nullを返すnullを返すことが有効な場合.
メソッドがコレクションを返す場合は、空のコレクションを返します(上記のように)。 Collections.EMPTY_LISTなどはしないでください。 (Javaの場合)
メソッドが単一のオブジェクトを取得する場合は、いくつかの選択肢があります。
Nullを返すことにした場合は注意してください。あなたがプロジェクトの唯一のプログラマーでないなら、あなたは実行時にNullPointerExceptions(Javaあるいは他の言語の何でも)を受け取るでしょう!そのため、コンパイル時にチェックされないnullを返さないでください。
Nullを返す、例外はまさにそれです:あなたのコードがすることは期待されていません。
あなたがライブラリや例外を投げる別のクラスを使っているなら、あなたはrethrowそれをすべきです。これが一例です。 Example2.Javaはライブラリに似ており、Example.Javaはそのオブジェクトを使用します。 Main.Javaは、この例外を処理するための例です。意味のあるメッセージと(必要であれば)スタックトレースを呼び出し側のユーザに見せるべきです。
Main.Java
public class Main {
public static void main(String[] args) {
Example example = new Example();
try {
Example2 obj = example.doExample();
if(obj == null){
System.out.println("Hey object is null!");
}
} catch (Exception e) {
System.out.println("Congratulations, you caught the exception!");
System.out.println("Here is stack trace:");
e.printStackTrace();
}
}
}
Example.Java
/**
* Example.Java
* @author Seval
* @date 10/22/2014
*/
public class Example {
/**
* Returns Example2 object
* If there is no Example2 object, throws exception
*
* @return obj Example2
* @throws Exception
*/
public Example2 doExample() throws Exception {
try {
// Get the object
Example2 obj = new Example2();
return obj;
} catch (Exception e) {
// Log the exception and rethrow
// Log.logException(e);
throw e;
}
}
}
Example2.Java
/**
* Example2.Java
* @author Seval
*
*/
public class Example2 {
/**
* Constructor of Example2
* @throws Exception
*/
public Example2() throws Exception{
throw new Exception("Please set the \"obj\"");
}
}
オブジェクトにreferenceを返すことになっている限り、NULLを返すのが良いでしょう。
しかし、C++のように、「return&blah;」ではなく「return blah;」(または「blah」がポインタ)のように、血まみれのものを返すのであれば、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を返します。オブジェクトが常に見つかるのが通常の動作である場合は、例外をスローします。
経験則として、何か例外的なが発生した場合にのみ例外を使用してください。例外のスローとキャッチが通常の操作の一部になるような方法でコードを書かないでください。
それが見つからないことが例外的な出来事であるならば(すなわち、それは通常の状況下でそこにあるべきである)、そして投げる。そうでない場合は、「見つからなかった」値(nullでもかまいません)を返すか、またはfind/notfoundに対してブール値を返し、実際のオブジェクトに対してoutパラメータを返すようにすることさえできます。
それはあなたの方法によります。あなたのメソッドが常に有効なオブジェクトを返すことになっていて、何も見つからない場合は、例外をスローするのがいいでしょう。メソッドが単に存在してもしなくてもよいオブジェクトを返すことを目的としている場合(おそらく連絡先の画像など)、エラーを発生させないでください。
このメソッドが実際にオブジェクトを返す場合は、ブール値のtrue/falseを返すメソッドを公開することもできます。したがって、a)nullをチェックしたり、b)例外をキャッチする必要はありません。
"other"オプションは、findメソッドが、検索対象のオブジェクトが見つからない場合に返されることになるデフォルトオブジェクトを持つ追加のパラメータを受け取るようにすることができます。
そうでなければ、オブジェクトが見つからないときに例外的なケースでない限り、単にnullを返します。