web-dev-qa-db-ja.com

「ランダム」なことをするのではなく、何かが失敗した場合に何を返すか?

文字列内の文字列の位置を見つけるためのメソッドを再実装するとします。つまり、整数の位置か、-1のような「マジックナンバー」を取得します。このパターンは非常に多くのプログラミング言語で見られ、nullのような値を返すものもあれば、-`のようなランダムな「範囲外」の値を返すものもあれば、完全にエラーをスローするものもあります。

これに関する「ベストプラクティス」、または少なくとも私が知らない他のプログラミング言語でより明確なものはありますか?

10
anemaria20

どんな言語でコーディングする場合でも 最小の驚きの原則 に従ってください。あるレベルで、人々はあなたの関数があなたの言語のパラダイムと標準に従うことを期待します。したがって、言語が通常、検索関数(C、C++など)で-1などのエラーコードを使用している場合は、それを実行します。オプションタイプが一般的である関数型言語を使用している場合は、そうしてください。言語がそのようなことのためにnullを通常使用する場合、それを行います。等使用する人が使いやすい機能にする。彼らが慣れている他の物と同じように機能するとき、彼らはそれを正しく得る可能性がはるかに高いです。

20
Becuzz

少なくとも関数型言語の中で一般的な方法は、Maybe型(または一部の関数型言語ではOption)を使用することです。

Maybe<int> FindPosition(string stringToSearch, char charToFind)
    // Return Some(int) if found or none if not.

関数は、見つかった場合はその位置のint値を生成し、何も見つからなかった場合はnoneを生成します。

これにより、structまたはタプルを使用して成功を示すフラグと、そのフラグの状態によっては未定義のint値を返すことに固有の問題が回避されます。例外を投げる;マジックナンバーなどを使う.

15
David Arno

TryGetパターンは、説明したシナリオで役立つ場合があります。

例:

public bool TryGetValue(string input, string toFind, out int value)

注:これは、例外をサポートする言語についても、このメソッドから例外が発生してはならないことも示しています。

3
Jon Raynor

これには多くのアプローチがあり、私はBecuzzにある程度同意しますが、通常は言語/チームの規則に従う必要がありますが、必ずしも完全に完全なものではありません。 Javaでは、この種のものにアプローチする最良の方法について競合するアイデアがあり、正しい答えが何であるかは、メソッドのコンテキストによって異なります。

私が最初にあなたを混乱させようとすることの1つは、-1を返すことは「ランダムな」値またはマジックナンバーであることです。実際に特定の値にコーディングするべきではありません。その場合は、0未満の値が見つからないかどうかを確認する必要があります。そのような仮定がバグにつながるのを見てきました。たとえば、Java Integer.compareは減算を使用して実装されています。つまり、ほとんどすべてのint(正または負)が返される可能性がありますが、比較呼び出しが-1、0、または1を返します。ポイントのもう1つのケースはArrays.binarySearchです。これは、要素が見つからない場合に、配列内の要素の順序を示す負の数を返します。

これらの種類のアプローチは、単に「見つからない」というより多くの情報を返すため、有用です。異なるアプローチが一般的ですが、他のケースもあります。たとえば、特定の条件を満たすアイテムのコレクションを取得するためのメソッドは、nullを返す可能性があります。別のオプションは、空のコレクションを返すことです。ほとんどの場合、nullポインターチェックを心配する必要がないため、後者をお勧めします。通常、結果を反復するだけの場合、チェックは必要ありません。 nullを返すことは一般的であり、Javaで期待されますが、これも問題があります。別のオプションは例外をスローすることですが、スタックトレースを作成するオーバーヘッドのため、一般的には推奨されません。通常、誇張されていますが、本物です。

重要なのは、優れた結果を得ることができるのであれば、慣習に従って盲目的に従う必要はないということです。しかし、その代わりに、人々が期待することをしてください。

2
JimmyJames

1つの方法は、値によって2フィールドの構造体を返すことです。C++では、これは通常、次のようになります。

struct find_result
{
    bool found;
    size_t index;
};

次に、呼び出し先はfoundtrueまたはfalseに設定できます。indexfoundの場合はtrueのみを設定し、indexfoundtrueの場合にのみ使用できます。

C++標準ライブラリはこれをstd::pair<>で使用します。ここで、firstboolであり、secondはコンテキストを保持します(上記のindexと同様)。

1
Johann Gerell

この特定のケースでは、有効な戻り値(一致が見つかったことを示す)はゼロから始まり、-1は何も見つからなかったことを示します。問題があったことを示す他のすべての負の値が残ります。したがって、ここでは具体的には、エラーがあったことを示すために-2を返します。

Johannが前述したように、複雑な構造を使用して「ステータス」タイプの値を返すことができますが、複雑な戻り値が必要であり、返される実際の結果が「実際」であるかどうかを示す必要があるAPIにのみ使用します。したがって、特定のケースでは、有効な負の値を返すことが可能である場合、負の数を使用して状態を示すオプションがないため、値のペアを返すと便利です。

1
John Fergus