こんにちは~ Webエンジニアのマッシュルーム🍄です!
プログラムを書いていると、自然と増えていくものがありますよね!
そう、if文です。
if (条件) {
// 何らかの処理
}
条件によって処理を分けます。
プログラムには欠かせない、とても基本的な構文です。
もちろん、if文そのものが悪いわけではありません。
ですが、コードレビューをしていると、ときどき思うことがあります。
そのif文、本当に必要ですか?
今回は、そんなif文について考えてみます。
📋 目次
- trueかどうかを確認するif文
- trueかfalseを返すだけのif文
- if文の中にif文、その中にもif文
- 「念のため」追加されたif文
- if文を減らせば、良いコードになる?
- if文は、仕様を表している
- 最後に
1.trueかどうかを確認するif文
まずは、よく見かけるこちらのコードです。
if (isActive === true) {
start();
}
isActiveが必ずboolean型であるなら、次のように書けます。
if (isActive) {
start();
}
どちらも動作は同じです。
後者の方が短く、条件もすぐに読み取れます。
逆に、falseの場合を判定したいのであれば、次のように書けます。
if (!isActive) {
stop();
}
もちろん、値がboolean型とは限らず、trueだけを厳密に判定したい場合は、=== trueに意味があります。
大切なのは、省略することではありません。
なぜ、trueと比較しているのか
を説明できるかどうかです。
2.trueかfalseを返すだけのif文
次のようなコードもあります。
function isAdult(age) {
if (age >= 18) {
return true;
} else {
return false;
}
}
間違いではありません。
しかし、age >= 18の判定結果は、最初からtrueかfalseです。
そのため、次のように書けます。
function isAdult(age) {
return age >= 18;
}
最初のコードでは、
- 条件を判定する
- trueならtrueを返す
- falseならfalseを返す
という処理になっています。
ですが実際には、条件の判定結果をそのまま返せば十分です。
コードが短くなるだけでなく、
この関数は、18歳以上かどうかを返している
という意図も伝わりやすくなります。
3.if文の中にif文、その中にもif文
if文が増えると、ネストが深くなることがあります。
function updateUser(user) {
if (user) {
if (user.isLoggedIn) {
if (!user.isSuspended) {
update(user);
}
}
}
}
処理を追うためには、外側から順番に条件を確認しなければなりません。
このような場合は、処理できない条件を先に終了させる方法があります。
function updateUser(user) {
if (!user) {
return;
}
if (!user.isLoggedIn) {
return;
}
if (user.isSuspended) {
return;
}
update(user);
}
これは「早期リターン」や「ガード節」と呼ばれる書き方です。
if文の数自体は減っていません。
しかし、ネストがなくなったことで、
- ユーザーが存在しないなら終了
- ログインしていないなら終了
- 利用停止中なら終了
- それ以外なら更新
という流れが上から順番に読めるようになりました。
重要なのは、if文を消すことではありません。
コードを読む人が、条件を理解しやすくなることです。
4.「念のため」追加されたif文
開発をしていると、こんな理由でif文を追加することがあります。
念のため、nullチェックしておこう。
もちろん、外部から受け取った値を検証することは大切です。
しかし、すでに別の場所で必ずチェックされている値に対して、あらゆる場所で「念のため」のチェックを追加すると、少しずつ問題が見えにくくなります。
if (user) {
if (user.profile) {
if (user.profile.name) {
displayName(user.profile.name);
}
}
}
このコードだけを見ると、安全そうに見えます。
ですが、別の疑問も生まれます。
- userが存在しないことは正常なのか
- profileが存在しなくてもよいのか
- nameが空の場合は何もしなくてよいのか
- データがおかしい場合、本当はエラーにすべきではないのか
すべてをif文で囲むと、異常なデータが来ても、何も起こらず処理が終わってしまいます。
安全にしたつもりのif文が、不具合を隠してしまうこともあるのです。
5.if文を減らせば、良いコードになる?
ここまで読むと、if文は少ない方が良いように感じるかもしれません。
ですが、そうとは限りません。
例えば、if文を使わずに三項演算子を重ねると、次のようなコードになります。
const message = isError
? isTimeout
? "タイムアウトしました"
: "エラーが発生しました"
: isCompleted
? "完了しました"
: "処理中です";
if文はありません。
しかし、読みやすいかと言われると、少し考えてしまいます。
無理にif文をなくすより、素直に条件分岐を書いた方が分かりやすい場合もあります。
let message = "処理中です";
if (isError) {
message = isTimeout
? "タイムアウトしました"
: "エラーが発生しました";
} else if (isCompleted) {
message = "完了しました";
}
コードの品質は、if文の数だけでは決まりません。
少ないことよりも、意図が伝わることの方が大切です。
6.if文は、仕様を表している
if文は、ただのプログラム構文ではありません。
多くの場合、そこには仕様や業務ルールが表れています。
if (totalPrice >= 5000) {
shippingFee = 0;
}
このif文には、
合計金額が5,000円以上なら、送料を無料にする
というルールがあります。
このような条件分岐は、無理に消す必要はありません。
むしろ、何を判定しているのかが伝わるように、名前を付けてもよいかもしれません。
const isFreeShipping = totalPrice >= 5000;
if (isFreeShipping) {
shippingFee = 0;
}
コードが少し長くなったとしても、意図は分かりやすくなります。
短いコードが、必ずしも読みやすいコードとは限らないのです。
7.最後に
if文は、プログラムに欠かせないものです。
だからこそ、何となく追加していると、いつの間にか増えていきます。
if文を書いたときは、一度だけ立ち止まって考えてみてもよいかもしれません。
-
この条件は、何を表しているのか。
-
本当にここで判定する必要があるのか。
-
条件の結果を、そのまま返せないか。
-
ネストを浅くできないか。
-
「念のため」という不安だけで追加していないか。
if文が多いこと自体が、悪いわけではありません。
本当に怖いのは、
なぜ存在しているのか、誰にも分からないif文
なのかもしれません。
それでは、また次回の記事でお会いしましょう~🍄

