メインコンテンツへスキップ

🪆 ネスト地獄(Flat is better than nested)

🧭 はじめに

このページでは、Python の Zen Flat is better than nested に反する代表的アンチパターン 「ネスト地獄」 を扱います。

ネスト地獄は単なる「見た目の悪さ」ではありません。 処理の主筋が視覚的に失われ、理解・修正・検証のコストが指数関数的に増える という、構造的な欠陥です。


🎯 ねらい

  • ネストが深くなるほど、認知負荷が爆発する理由を説明する
  • 「平坦化」は好みではなく、設計上の安全策であることを示す

❓ 問題の定義

ネスト地獄とは、

  • if / for / try が入れ子になり
  • 処理の本質がインデントの奥に沈む
  • 全体像を把握するには最後まで読む必要がある

状態を指します。

ネストは分岐の数ではなく「組み合わせ」を増やします。 3段ネストは 3倍ではなく、理解コストが一気に跳ね上がります。


🤒 よくある症状

📐 インデントが右へ伸び続ける

  • 画面幅の半分以上が空白
  • ロジックが視界から消える

🧩 条件を最後まで読まないと意図が分からない

  • 「結局この関数は何をしたいのか」が見えない
  • 正常系と異常系の区別がつかない

🕳️ 重要な例外処理が深部に埋もれる

  • try/except がネストの底にある
  • エラー処理が後付けになっている

例外処理が深い位置にあるコードは、ほぼ確実に読まれません


❌ 悪い例:実務でよく見る地獄

def handle_request(req):
    if req:
        if req.user:
            try:
                if req.user.is_active:
                    result = do_something(req)
                    if result:
                        return result
                    else:
                        log_error('no result')
                else:
                    log_error('inactive user')
            except Exception:
                log_error('unexpected error')
        else:
            log_error('no user')
    else:
        log_error('no request')

問題点

  • 正常系が最も深い場所にある
  • エラー条件が主筋を覆い隠している
  • 「成功した場合」が一番読みにくい

✅ 良い例①:ガード節で早期リターン

def handle_request(req):
    if req is None:
        log_error('no request')
        return None

    if req.user is None:
        log_error('no user')
        return None

    if not req.user.is_active:
        log_error('inactive user')
        return None

    try:
        return do_something(req)
    except Exception as e:
        log_error(f'unexpected error: {e}')
        return None

改善点

  • 条件異常は最初に排除
  • 正常系が最短距離で読める
  • 処理の流れが上から自然に追える

ガード節は「条件分岐」ではなく「前提の明文化」です。


✅ 良い例②:分岐を関数に分解する

def validate_request(req):
    if req is None:
        raise ValueError('no request')
    if req.user is None:
        raise ValueError('no user')
    if not req.user.is_active:
        raise ValueError('inactive user')


def handle_request(req):
    try:
        validate_request(req)
        return do_something(req)
    except ValueError as e:
        log_error(str(e))
        return None

改善点

  • 分岐が意味単位でラベル化
  • ネストが構造的に消える
  • 検証ロジックの再利用が可能

🧩 設計の要点

平坦化の基本原則

  • 主筋(正常系)を一番上に置く
  • 例外・エラーは「脇役」として早期に処理
  • 深さではなく流れで読ませる

ネストを減らす代表手段

  • ガード節(early return)
  • 関数分割(意味で切る)
  • match による分岐の平坦化(必要な場合)

✅ チェックリスト

  • インデントが 3段を超えていないか
  • 正常系が 最短で読める構造
  • 例外処理が「深い場所」に沈んでいないか
  • 条件分岐が「理由」ではなく「状態」で書かれていないか

🧠 まとめ

ネスト地獄は、

  • 書いた瞬間は動く
  • 修正時に壊れ
  • 読み返した自分すら迷子になる

という時間差で効いてくるバグ生成器です。

Python の Zen が勧める Flat とは、

少ない行数ではなく、 思考の直線性を保つこと

次の記事では、 その「壊れているのに気づけない」代表例 🤐 例外の黙殺を扱います。