早期リターンを実践する
TL;DR
- 出口は一か所にすべきは古い。
- 条件がそろっていればなるべく早く
return
を実施する。
具体的な例
極端な例を次に示します。
こんな実装はしないと感じるかもしれませんが、実際に現場では散見されます。
public String returnStuff(SomeObject argument1, SomeObject argument2) {
if (argument1.isValid()) {
if (argument2.isValid()) {
SomeObject otherVal1 = doSomeStuff(argument1, argument2)
if (otherVal1.isValid()) {
SomeObject otherVal2 = doAnotherStuff(otherVal1)
if (otherVal2.isValid()) {
return "Stuff";
} else {
return "None";
}
} else {
return "None";
}
} else {
return "None";
}
} else {
return "None";
}
}
-
argument1
が有効な場合は処理を継続 -
argument2
が有効な場合は処理を継続 - 引数を関数に渡し、
otherVal1
を作成 -
otherVal1
が有効な場合は処理を継続 -
otherVal1
を関数に渡し、otherVal2
を作成 -
otherVal2
が有効な場合は"Stuff"
を返却 - 各条件に適合しない場合は
"None"
を返却
早期リターンの実践
処理を整理して早期リターンを実装してみましょう。
public String returnStuff(SomeObject argument1, SomeObject argument2){
if (!argument1.isValid()) {
return "None";
}
if (!argument2.isValid()) {
return "None";
}
SomeObject otherVal1 = doSomeStuf(argument1, argument2);
if (!otherVal1.isValid()) {
return "None";
}
SomeObject otherVal2 = doAnotherStuff(otherVal1);
if (!otherVal2.isValid()) {
return "None";
}
return "Stuff";
}
-
argument1
が無効な場合は"None"
を返却 -
argument2
が無効な場合は"None"
を返却 - 引数を関数に渡し、
otherVal1
を作成 -
otherVal1
が無効な場合は"None"
を返却 -
otherVal1
を関数に渡し、otherVal2
を作成 -
otherVal2
が無効な場合は"None"
を返却 - すべての処理を通過した場合は
"Stuff"
を返却
処理を整理することで何が行われているか、わかりやすくなりました。
関数の出口は一か所であるべき?
早期リターンの話をすると必ずこの議論になります。
Cやアセンブリのような明示的なリソース管理を行う言語の場合、出口を実装するたびにリソースの解放が必要でした。
そのため、出口を一か所にする必要がありました。
モダンな言語ではこのような問題は起こりません。
リソースの管理(ファイルを開いて、処理して、閉じるなど)がある場合は、Javaであればfinally
、Pythonであればwith
などを活用できます。
また、デバッグがしにくい等の指摘も正しくありません。
コードの理解しやすさを重視し、適切にreturn
を実施しましょう。
どのような時に適用すべきか
とはいえ、闇雲にreturn
を実装するというのは誤りです。
いくつかの考え方を示します。
Fail Fast
早期リターンの基礎となっている考え方で終了する条件をみつけることにフォーカスします。
ガード節
前述の例のように後続の処理が失敗する条件の判定を先に実施し、早期リターンを行います。
やりすぎに思えてきたら設計を見直す
たとえば、200行の関数に10個のreturn
があることを想像してみましょう。
とても理解しやすいコードとは思えません。
これは早期リターンを実施し無くても10個のreturn
の代わりに10個のエラー処理が紛れ込んでいるので、同じことです。
このような場合は適切に関数の役割が分割されていなかったりすることが原因です。
引数のチェックは別の関数に切り出すなど設計を見直すことを検討してください。
まとめ
- 「関数の出口は一か所であるべき」はモダンな言語では適用されない
- 条件を整理し、ガード節を実装する
- 出口が増えすぎるなら関数の設計が適切か、分割できなかなど検討する
株式会社ソルクシーズの事業戦略室のアカウントです。 ジュニアエンジニア向けのお役立ち記事を中心に投稿しています。 採用サイト:solxyz.co.jp/recruit/ 未経験採用も実施中です!
Discussion