質問
大規模なコードレビューを行ってきましたが、あちこちで気づいたパターンの1つは次のとおりです。
public bool MethodName()
{
bool returnValue = false;
if (expression)
{
// do something
returnValue = MethodCall();
}
else
{
// do something else
returnValue = Expression;
}
return returnValue;
}
これは私がこれをどのように行うかではなく、それが何であるかを知ったときに値を返すだけでした。これら2つのパターンのどちらがより正確ですか?
ロジックは常に、戻り値が1つの区画にのみ割り当てられ、割り当て後にコードが実行されないように構成されているように見えることを強調します。
解決
このトピックに関する長い議論がありますこちら 。
他のヒント
多くの人々は、メソッドからの出口を1つだけにすることを推奨しています。上記のパターンはその推奨事項に従います。
この推奨事項の主な要点は、メソッドから戻る前にメモリまたは状態をクリーンアップする必要がある場合は、そのコードを1か所に配置することをお勧めします。複数の出口点があると、1つ以上の出口点でクリーンアップコードが重複したり、クリーンアップコードが見つからないために問題が発生したりする可能性があります。
もちろん、メソッドが数行の長さである場合、またはクリーンアップが必要ない場合は、複数のリターンを取得できます。
制御構造を削減するために、三値を使用していました...
return expression ? MethodCall() : Expression;
少数派になると思いますが、この例で示したスタイルは気に入っています。ログステートメントを追加し、ブレークポイントIMOを設定するのは簡単です。さらに、一貫した方法で使用すると、<!> quot;パターンマッチ<!> quot;複数のリターンを持つよりも。
<!> quot; correct <!> quot;があるかどうかわかりません。ただし、これについては答えてください。
一部の学習機関や書籍では、シングルリターンプラクティスを提唱しています。
それが良いかどうかは主観的です。
それは、悪いOOPデザインの一部のように見えます。おそらく、単一のメソッドの内部よりも高いレベルでリファクタリングする必要があります。
それ以外の場合、次のような三項演算子を使用することを好みます:
return expression ? MethodCall() : Expression;
より短く、読みやすくなっています。
これらの状況のいずれかですぐにメソッドから戻る:
- 境界条件が見つかったため、一意の値またはセンチネル値を返す必要があります:
if (node.next = null) return NO_VALUE_FOUND;
- 必要な値/状態がfalseであるため、メソッドの残りの部分は適用されません(別名ガード句)。例:
if (listeners == null) return null;
- メソッドの目的は、特定の値を見つけて返すことです。例:
if (nodes[i].value == searchValue) return i;
- メソッドの他の場所で使用されていないメソッドから一意の値を返す句にいます:
if (userNameFromDb.equals(SUPER_USER)) return getSuperUserAccount();
それ以外の場合、returnステートメントを1つだけにしておくと、デバッグロギング、リソースクリーンアップの追加、ロジックの実行が簡単になります。上記の4つのケースすべてを最初に処理し、該当する場合は、result(s)
という名前の変数をできるだけ遅く宣言し、必要に応じて値を割り当てます。
両方とも同じタスクを実行します。メソッドには、1つのエントリと1つの出口ポイントのみが必要であると言う人もいます。
これも使用します。アイデアは、プログラムの通常のフローでリソースを解放できるということです。 20の異なる場所でメソッドから飛び出し、前にcleanUp()を呼び出す必要がある場合は、さらに別のクリーンアップメソッドを20回追加する(またはすべてをリファクタリングする)必要があります
コーダーは、メソッドの先頭でオブジェクトtoReturnを定義する設計を取っていると思います(たとえば、List <!> lt; Foo <!> gt; toReturn = new ArrayList <!> lt; Foo <! > gt;();)そして、メソッド呼び出し中にそれを移植し、どういうわけかブール値の戻り値型に適用することにしました。これは奇妙です。
また、メソッド本体の中央に戻ることはできず、最後にのみ戻ることができるというコーディング標準の副作用になる可能性があります。
現在、戻り値が割り当てられた後にコードが実行されない場合でも、一部のコードを後で追加する必要がないという意味ではありません。
使用できる最小のコードではありませんが、リファクタリングに非常に適しています。
Delphiは、<!> quot; Result <!> quotという変数を自動的に作成することにより、このパターンを強制します。関数の戻り値型になります。何でも<!> quot; Result <!> quot;関数が終了するとき、戻り値です。したがって、<!> quot; return <!> quot;はありません。キーワード。
function MethodName : boolean;
begin
Result := False;
if Expression then begin
//do something
Result := MethodCall;
end
else begin
//do something else
Result := Expression;
end;
//possibly more code
end;
使用されるパターンは冗長ですが、[Registers]ウィンドウを開いてEAXをチェックせずに戻り値を知りたい場合はデバッグも簡単です。