1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

if条件を並列に足すだけ──その積み重ねが“バグを呼ぶ構造”だった

Posted at

──見落とされた「構造的従属」から設計を学べた話

よくあるコードから始まった

はじまりは、よくあるコードだった。

if (user && user.isAdmin) {
  showAdminPanel();
}

これは、ユーザーが存在しており、かつ管理者であれば管理者UIを表示する処理。
短くて、読みやすく、問題も起きていなかった。

条件追加でバグが発生

仕様追加は「ただ1つの条件追加」のはずだった
ある日、新たな仕様が加わった。

「ダークテーマを使っている管理者だけに表示してほしい」

それを反映するには、こうすればいいと思った。

if (user && user.isAdmin && user.settings.theme === 'dark') {
  showAdminPanel();
}

見た目上、何の問題もない。
条件が1つ増えただけで、既存の形を壊していないように見えた。

しかし、自分のミスで、本番で障害が発生した
特定のユーザーで画面が真っ白に。
原因は user.settings が undefined だったこと。

TypeError: Cannot read properties of undefined (reading 'theme')

そこで、よくある短絡的な修正すると、

if (user && user.isAdmin && user.settings && user.settings.theme === 'dark') {
  showAdminPanel();
}

見た目は正しい。評価順も安全。

しかし、意味の関係性がまた“対等に並列”に見えてしまう

このように条件を“並列に”積み重ねていくと、
次の仕様追加でもまた && で繋いでしまいがちになります。

たとえば「組織に所属している人だけ」や「2段階認証を有効にしている人だけ」など、
次々と要件が追加されるたびに、if 文がどんどん長く、複雑になっていきます。

やがて──

if文の“条件地獄”が生まれるのです

読みづらく、変更しづらく、ミスが生まれやすい構造。

その結果、また誰かが「ここに条件足せばいい」と勘違いしやすくなる。
そして、“なんとなく足される条件”が積み重なり、
本来分けるべき責任が分けられないまま、技術負債が静かに膨らんでいきます。

実は、某有名なプログラミングの本でも、ファイルの有無とファイル保護状態のチェックを“並列の条件”として書いている例があり、どうしても違和感を覚えることがあります。

本来は、その条件同士に“構造的な従属関係”があることを、
コード上でも読み手に伝えるべきなのでは──そう感じたことがある人もいるのではないでしょうか。

従属関係を構造で見せる

「構造で見せる」とは、単に if 文を安全に書くという話ではありません。
条件同士に“意味的な上下関係”があるときは、それをコード構造(ネスト)で表現することで、意図の誤解や将来的な事故を防ぐという考え方です。

たとえば、次のように

「user が存在して初めて isAdmin を確認できる」「さらに settings の存在があって初めて theme を見られる」

という従属関係を、if 文の入れ子構造で視覚的に示します。

if (user) {
  if (user.isAdmin) {
    const settings = user.settings;
    if (settings && settings.theme === 'dark') {
      showAdminPanel();
    }
  }
}

このように

「user → isAdmin → settings.theme」

という意味的な依存関係を、コードの階層でそのまま見せることで、
「この条件は、上の条件を前提にしているんだな」という設計意図が誰にでも伝わるようになります。

ネストが深いときの代替手法(early return)

ネストが深くなりすぎると、たしかに読みづらさや保守性の低下につながることがあります。

ただし、意味的な従属関係が明確にある場合は、あえてネストによって構造化することで、
その関係性を読み手に正しく伝えることができます。

ネストが浅く収まるなら、構造を見せる有効な手段になります。
もし、ネストが深くなりすぎて読みづらくなる場合には、early return で“責任の順序”を保ったままフラットに表現するのも選択肢のひとつです。

function shouldShowAdminPanel(user) {
  if (!user) return false;
  if (!user.isAdmin) return false;
  
  const settings = user.settings;
  if (!settings) return false;
  
  if (settings.theme !== 'dark') return false;
  
  showAdminPanel();
}

STSで責任を分ける

STSとは、

「Source(入力)」「Transfer(判断・変換)」「Sink(出力)」

という責任の流れで 設計やコードを構造化する考え方です。

では、先ほどのコードを「責任の流れ」という視点で見直してみましょう。

先ほどのコードで言えば:

・user の存在チェック → Source

・isAdmin や theme の条件判断 → Transfer

・showAdminPanel の実行 → Sink

すべてが1つの関数に詰め込まれていたため、責任が混ざり、変更や拡張・レビューが難しくなっていました。

ここで Transfer(判断)部分を関数として切り出してみると、

function shouldShowAdminPanel(user) {
  // --- Source: 入力チェック ---
  if (!user) return false;
  const settings = user.settings;
  if (!settings) return false;

  // --- Transfer: 条件の判断 ---
  const isAdmin = user.isAdmin;
  const isDarkTheme = settings.theme === 'dark';
  const isEligible = isAdmin && isDarkTheme;
  if (!isEligible) return false;

  // --- Sink: 表示許可を出力 ---
  return true;
}

if (shouldShowAdminPanel(user)) {
  showAdminPanel();
}

設計とは、責任の流れを“構造で見せる”こと

「コードが動くかどうか」ではなく、その処理がどんな前提や流れで実行されるかを意識する

条件を横並びに書くのではなく、どの条件がどれに依存しているか(従属関係)を明確にする

ネストが深くなりすぎなければ、従属関係を読み手に正しく伝えるための“構造的なヒント”として、ネストは有効に機能します。

まとめ:構造は、設計意図の“言語”である

設計とは、動くこと以上に、“意図が伝わること”。
構造で意味を語れるコードは、バグを防ぎ、未来を守ります。

if文の条件は、ただの構文ではなく、その設計意図を伝える“構造”でもある。
条件を横に並べるだけでは、すべてが同じ重み・前提で評価されるように見えてしまう。
だからこそ、依存や従属の関係があるなら、それを“構造として見える形”で表現すべきなのだ。

このコード、あなたのプロダクトでも見たことありませんか?

もし、複雑な条件や仕様追加でバグが入りやすいと感じていたら──
今回紹介したような「構造で責任を見せる」設計、ぜひ試してみてください。

あわせて学びたいコンテンツ

また、今回紹介した内容をより実践的に学びたい方には、以下のUdemy講座もおすすめです。

🎓 Udemyコース(8,800円 → クーポンで割引中)

▶️ AIとC#で極める!クリーンコードの技法(限定クーポン付き)

  • C#でクリーンコードと設計力を身につける実践講座
  • ChatGPTの活用方法や、伝わるコードの考え方を解説

📘 出版書籍『あきらめない者たち』

▶️ Amazonで見る

  • 技術の基礎からやり直すために、なぜ一歩勇気を振り絞れたのか
  • 自身の成長と再出発を描いたノンフィクション作品
1
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?