web-dev-qa-db-ja.com

戻り値を生成できない場合、検索メソッドは 'null'を返すべきですか、それとも例外をスローするべきですか?

オブジェクトが見つかった場合にそれを返すことになっているメソッドがあります。

見つからない場合は、次のようにします。

  1. nullを返す
  2. 例外を投げる
  3. その他の
471
Robert

常に値を見つけることを期待しているのであれば、もしそれが欠けていれば例外を投げます。例外は問題があることを意味します。

値が欠落しているか存在する可能性があり、両方がアプリケーションロジックに対して有効である場合は、nullを返します。

もっと重要:あなたはコードの他の場所で何をしますか?一貫性が重要です。

455
Ken

本当にエラーである場合にのみ例外をスローします。オブジェクトが存在しないことが予想される動作である場合は、nullを返します。

そうでなければそれは好みの問題です。

95
Carlton Jenke

一般的な規則として、メソッドが常にオブジェクトを返すべきであるならば、例外を持って行きなさい。時折のnullを予想してそれをある方法で処理したい場合は、nullで進めてください。

あなたが何をするにしても、私は第三の選択肢に対して強く忠告します: "WTF"を言う文字列を返すこと。

64
Matias Nino

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
50
Kevin Gale

前述のオプションを要約して、新しいオプションをいくつか追加したいと思います。

  1. nullを返す
  2. 例外を投げる
  3. nullオブジェクトパターンを使用
  4. あなたのメソッドにブール値のパラメータを提供するので、呼び出し側は、例外をスローしたいかどうかを選択できます。
  5. 追加のパラメータを提供するので、呼び出し側は値が見つからない場合に元に戻す値を設定できます。

あるいは、これらのオプションを組み合わせることもできます。

ゲッターのオーバーロードされたバージョンをいくつか提供するので、呼び出し側はどちらの方法を選ぶか決めることができます。ほとんどの場合、最初のものだけが検索アルゴリズムの実装を持ち、他のものだけが最初のものをラップアラウンドします。

Object findObjectOrNull(String key);
Object findObjectOrThrow(String key) throws SomeException;
Object findObjectOrCreate(String key, SomeClass dataNeededToCreateNewObject);
Object findObjectOrDefault(String key, Object defaultReturnValue);

1つの実装のみを提供することを選択した場合でも、契約を明確にするためにそのような命名規則を使用することをお勧めします。他の実装を追加することを決断した場合に役立ちます。

あなたはそれを使いすぎてはいけませんが、特にエラー処理規約が異なる何百もの異なるアプリケーションで使用するヘルパークラスを書くときには役に立つかもしれません。

25
Lena Schimmel

Nullオブジェクトパターンを使用するか、例外をスローしてください。

18
pmlarocque

使用しているAPIと一致していること。

13
dmckee

「オブジェクトが見つからないのは例外的なケースなのか」と自問してみてください。それがあなたのプログラムの通常の過程で起こると予想されるなら、あなたはおそらく例外を発生させるべきではありません(それは例外的な振る舞いではないので)。

ショートバージョン:プログラムの通常の制御の流れを処理するのではなく、例外的な動作を処理するために例外を使用します。

- アラン。

11
AlanR

それはあなたの言語とコードが促進するかどうかによって異なります:LBYL(あなたが跳躍する前に見て)またはEAFP(許可より許しを求めることが容易)

LBYLは値をチェックすべきだと言っています(だからnullを返してください)
EAFPは単に操作を試して失敗したかどうかを確認するように言います(例外をスローします)

私は上記に同意しますが、例外は例外/エラー条件に使用されるべきであり、チェックを使用するときはnullを返すことが最善です。


PythonでのEAFPとLBYLの比較:
http://mail.python.org/pipermail/python-list/2003-May/205182.htmlWeb Archive

11
Corey Goldberg

例外をスローする利点

  1. 呼び出し元コードの制御フローがよりきれいになりました。nullをチェックすると、try/catchによってネイティブに処理される条件付きブランチが挿入されます。 nullをチェックしても、それが何をチェックしているのかを示すものではありません。予期しているエラーを探しているのでnullをチェックしているか、それともダウンチェーンに渡さないようにnullをチェックしていますか?
  2. "null"の意味のあいまいさを取り除きます。nullはエラーを表しているのか、それとも実際に値に格納されているのはnullなのか?その決断の根拠となるものが1つしかない場合は、言い難いです。
  3. アプリケーション内のメソッド動作間の一貫性が向上しました。例外は通常メソッドシグネチャで公開されるので、Edgeでどのメソッドがメソッドを実行するかを理解することができます。アプリケーションアカウント、およびアプリケーションが予測可能な方法で対応できる情報。

例を使用した詳細な説明については、 http://metatations.com/2011/11/17/returning-null-vs-throwing-an-exception/ を参照してください。

8
Clifford Oravec

例外は契約によるデザインに関連しています。

オブジェクトのインターフェースは実際には2つのオブジェクト間の契約です。呼び出し側はその契約を満たさなければなりません。そうでなければ受信側は例外で失敗するかもしれません。 2つの可能な契約があります

1)すべての入力メソッドが有効である場合、オブジェクトが見つからないときはnullを返さなければなりません。

2)いくつかの入力のみが有効であり、すなわちそれは発見されたオブジェクトをもたらすものである。その場合、呼び出し側が入力が正しいかどうかを判断できるようにする2番目の方法を提供する必要があります。例えば

is_present(key)
find(key) throws Exception

もしあなたが2番目の契約の両方の方法を提供するならば、あなたは例外を投げることを許されます何も見つからないということです!

5
akuhn

ここにもう少し提案があります。

コレクションを返す場合、nullを返さないようにするには、最初にnullチェックを行わずに列挙を処理しやすくする空のコレクションを返します。

いくつかの.NET APIはthrownOnErrorパラメータのパターンを使用します。これは、オブジェクトが見つからない場合に、それが本当に例外的な状況であるかどうかの選択を呼び出し側に与えます。 Type.GetTypeはその一例です。 BCLのもう1つの一般的なパターンは、ブール値が返され、値が出力パラメータを介して渡されるTryGetパターンです。

また、デフォルトまたは動作のないバージョンのいずれかになる可能性がある状況で、Null Objectパターンを検討することもできます。重要なのは、コードベース全体でnullチェックを回避することです。詳細についてはこちらを参照してください http://geekswithblogs.net/dsellers/archive/2006/09/08/90656.aspx

4
Duncan

私はただnullを返すことを好み、それを適切に処理するために呼び出し側に頼ります。 (より良いWordがないための)例外は、このメソッドがオブジェクトを返すことが絶対に '確実'な場合です。その場合、失敗は例外的なはずであり、投げるべきです。

4
swilliams

オブジェクトが見つからないという意味によって異なります。

通常の状況であれば、nullを返します。これは時々起こるかもしれないちょうど何かであり、呼び出し側はそれをチェックする必要があります。

それがエラーであるならば、それから例外を投げます、呼び出し側は行方不明のオブジェクトのエラー条件で何をするべきか決めるべきです。

究極的にはどちらでもうまくいくでしょうが、ほとんどの人は一般的に、何か例外的なことが起こった場合にのみ例外を使用することをお勧めします。

4
Steve B.

nullが例外的な振る舞いと見なされていない場合のみを参照してください。これは明らかにtryメソッドのためのもので、明確になっています。

だから基本的に:

bool TryFindObject(RequestParam request, out ResponseParam response)

これは、ユーザーのコードも明らかになることを意味します

...
if(TryFindObject(request, out response)
{
  handleSuccess(response)
}
else
{
  handleFailure()
}
...
3
DorD

いくつかの関数で私はパラメータを追加します。

..., bool verify = true)

Trueはスローを、falseは何らかのエラー戻り値を返すことを意味します。このように、この関数を使う人は両方とも選択肢があります。エラー処理を忘れる人のために、デフォルトはtrueであるべきです。

3
Lev

例外をスローせずに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)) { ...
3
Ateş Göral

またはOptionを返す

オプションは基本的にクライアントにブースケースを処理させるコンテナクラスです。 Scalaにはこの概念があります。それをAPIで調べてください。

それから、このオブジェクトに対してT getOrElse(T valueIfNull)のようなメソッドを見つけると、見つかったオブジェクト、あるいはすべてのクライアント指定を返します。

2
John Nilsson

クライアントコードが見つかったものと見つからなかったものの違いを知ることが重要であり、これが日常的な動作であると想定される場合、nullを返すことが最善です。その後、クライアントコードは何をすべきかを決定できます。

2
plinth

通常はnullを返します。メソッドを呼び出すコードは、例外をスローするか他のことを試みるかを決定する必要があります。

2
Eran Galperin

残念ながらJDKは矛盾しています。リソースバンドル内の存在しないキーにアクセスしようとすると例外が見つからず、mapから値を要求したときに存在しない場合はnullになります。それで、私は勝者の答えを次のように変更します。見つかった値がnullになる可能性がある場合は、見つからない場合は例外を発生させ、それ以外の場合はnullを返します。だから、値が見つからない理由を知る必要があるなら、例外を1つ例外として出してください。

2
Dmitriy R

私はここでのコンセンサスと思われるものに同意します(「見つからない」が通常起こり得る結果である場合はnullを返し、状況の意味論でオブジェクトが常に見つかることを要求する場合は例外をスローします)。

しかし、あなたの特定の状況によっては意味があるかもしれない3番目の可能性があります。あなたのメソッドはある種のデフォルトオブジェクトを "見つからない"状態で返すことができ、呼び出し元のコードがnullチェックや例外キャッチの必要なしに常に有効なオブジェクトを受け取ることを保証することができます。

1
GBegen

Nullを返す -

呼び出し側が確認せずにそれを使用すると、とにかくそこで例外が発生します。

呼び出し側が実際にそれを使用していない場合は、try/catchブロックに課税しないでください。

1
kizzx2

例外は例外にする必要があります。 nullを返すnullを返すことが有効な場合.

1
Andrew Lewis

メソッドがコレクションを返す場合は、空のコレクションを返します(上記のように)。 Collections.EMPTY_LISTなどはしないでください。 (Javaの場合)

メソッドが単一のオブジェクトを取得する場合は、いくつかの選択肢があります。

  1. メソッドが常に結果を見つけなければならず、それがオブジェクトを見つけないのが本当の例外の場合であるなら、あなたは例外を投げるべきです(Javaでは:未チェックの例外をお願いします)。
  2. (Javaのみ)メソッドがチェック済み例外をスローすることを許容できる場合は、プロジェクト固有のObjectNotFoundExceptionなどをスローします。この場合、例外を処理するのを忘れると、コンパイラーはあなたに言います。 (これはJavaで見つからないものの私の好みの取り扱いです。)
  3. オブジェクトが見つからず、メソッド名がfindBookForAuthorOrReturnNull(..)のようになっていれば、本当に問題ないと言ってもnullを返すことができます。この場合、ある種の静的チェックやコンパイラチェックを使用することを強く強く推奨します。これはnullチェックなしで結果の間接参照を防ぐためです。 Javaの場合、それは例えばすることができます。 FindBugs( http://findbugs.sourceforge.net/manual/annotations.html のDefaultAnnotationを参照)またはIntelliJ-Checking。

Nullを返すことにした場合は注意してください。あなたがプロジェクトの唯一のプログラマーでないなら、あなたは実行時にNullPointerExceptions(Javaあるいは他の言語の何でも)を受け取るでしょう!そのため、コンパイル時にチェックされないnullを返さないでください。

1
iuzuz

Nullを返す、例外はまさにそれです:あなたのコードがすることは期待されていません。

1
Anders

あなたがライブラリや例外を投げる別のクラスを使っているなら、あなたは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\"");
    }

}
1
svlzx

オブジェクトにreferenceを返すことになっている限り、NULLを返すのが良いでしょう。

しかし、C++のように、「return&blah;」ではなく「return blah;」(または「blah」がポインタ)のように、血まみれのものを返すのであれば、NULLを返すことはできません。その場合は、例外をスローするか、成功フラグが設定されていない空のオブジェクトを返すことで問題に対処できます。

1
warren

誰かが例外処理のオーバーヘッドを言ったとは思わないでください - 例外をロードして処理するための追加のリソースを必要とします。呼び出し元の環境が適切と判断したときに解釈できる値。

1
ScottCher

データ層のコードでは、次のコードを使うことがあります。これにより、呼び出し側は「オブジェクトが見つかりません」というエラーが発生したことを意味するかどうかを判断できます。


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);
} 
0
codeape

オブジェクトが含まれていない場合は通常の操作で発生する可能性があり、呼び出し側がNULLを返すことで対処する必要があります。

オブジェクトが含まれていない場合は、呼び出し元のコードまたは内部状態によるバグを示している場合は、アサートを実行します。

オブジェクトが含まれていない場合は、頻度の低いイベントを示します。 (あなたが同時にアイテムをチェックアウトしている間に誰かがストアからアイテムを削除したように。)そして例外を投げます。

0
Jeroen Dirks

それは本当にあなたがオブジェクトを見つけることを期待しているかどうかにかかっています。何かを示すために例外を使うべきだと考える考え方に従うと、間違いなく、例外が発生しています。

  • オブジェクトが見つかりました。オブジェクトを返す
  • オブジェクトが見つかりません。例外を投げる

そうでなければ、nullを返します。

0
Rob

それはメソッドの性質とそれがどのように使われるかに依存します。オブジェクトが見つからない可能性があるのが通常の動作である場合は、nullを返します。オブジェクトが常に見つかるのが通常の動作である場合は、例外をスローします。

経験則として、何か例外的なが発生した場合にのみ例外を使用してください。例外のスローとキャッチが通常の操作の一部になるような方法でコードを書かないでください。

0
Simon Howard

それが見つからないことが例外的な出来事であるならば(すなわち、それは通常の状況下でそこにあるべきである)、そして投げる。そうでない場合は、「見つからなかった」値(nullでもかまいません)を返すか、またはfind/notfoundに対してブール値を返し、実際のオブジェクトに対してoutパラメータを返すようにすることさえできます。

0

それはあなたの方法によります。あなたのメソッドが常に有効なオブジェクトを返すことになっていて、何も見つからない場合は、例外をスローするのがいいでしょう。メソッドが単に存在してもしなくてもよいオブジェクトを返すことを目的としている場合(おそらく連絡先の画像など)、エラーを発生させないでください。

このメソッドが実際にオブジェクトを返す場合は、ブール値のtrue/falseを返すメソッドを公開することもできます。したがって、a)nullをチェックしたり、b)例外をキャッチする必要はありません。

"other"オプションは、findメソッドが、検索対象のオブジェクトが見つからない場合に返されることになるデフォルトオブジェクトを持つ追加のパラメータを受け取るようにすることができます。

そうでなければ、オブジェクトが見つからないときに例外的なケースでない限り、単にnullを返します。

0
Chris Vest