そのif文、本当に必要ですか?

こんにちは~ Webエンジニアのマッシュルーム🍄です! 

プログラムを書いていると、自然と増えていくものがありますよね!

そう、if文です。

if (条件) {
    // 何らかの処理
}

条件によって処理を分けます。
プログラムには欠かせない、とても基本的な構文です。

もちろん、if文そのものが悪いわけではありません。

ですが、コードレビューをしていると、ときどき思うことがあります。

そのif文、本当に必要ですか?

今回は、そんなif文について考えてみます。

📋 目次

  1. trueかどうかを確認するif文

  2. trueかfalseを返すだけのif文

  3. if文の中にif文、その中にもif文

  4. 「念のため」追加されたif文

  5. if文を減らせば、良いコードになる?

  6. if文は、仕様を表している

  7. 最後に

 

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;
}

最初のコードでは、

  1. 条件を判定する
  2. trueならtrueを返す
  3. 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文

なのかもしれません。

それでは、また次回の記事でお会いしましょう~🍄