# 循環的複雑度が高いコードはリファクタリングの優先候補だ

URL: https://whatshouldibuildnext.com/ja/journal/junkan-teki-fukuzatsu-do-refactoring-guide
Type: blog
Locale: ja
Published: 2026-08-01
Updated: 2026-08-27

---

> 循環的複雑度（CC）が10を超えた関数は技術負債の核心だ。計測ツール比較、変更頻度との優先度マトリクス、CIへの組み込み方をdev向けに解説する。

## 循環的複雑度が高いコードはリファクタリングの優先候補だ

循環的複雑度（Cyclomatic Complexity）は、次に何をリファクタリングすべきかを教えてくれる数値だ。感覚ではなく、計測で判断できる。

## 循環的複雑度とは何か、なぜdevが今すぐ計測すべきか

循環的複雑度は、1976年にThomas McCabeが定義したメトリクスだ。ひとつの関数内に存在する線形独立なパスの数を測る。`if`、`for`、`while`、`case`などの分岐が増えるほどスコアが上がる。

スコアが1なら分岐なし。スコアが15なら、その関数をテストするには最低15個のテストケースが必要という意味だ。計算式はシンプルだ。`CC = 判断ノード数 + 1`。

この数値を知っておく実用的な理由が3つある。まず、テストに必要なケース数が事前にわかる。次に、バグが潜みやすい関数を客観的に特定できる。そして、コードレビューの議論を感覚論から数値論に変えられる。

## CC 1〜10は緑、11以上はアラート、25以上は負債確定

業界のコンセンサスは明快だ。

- 
**1〜10**：シンプル。テストしやすい。リファクタリング不要。

- 
**11〜25**：複雑。リファクタリング候補。テストコストが跳ね上がる。

- 
**25以上**：テスト不可能に近い。技術負債として即座に記録すべき。

McCabe自身は10を上限として推奨した。GoogleのEngineering Practices、MicrosoftのCode Analysis、NASAのコーディング標準もこの数字を参照している。

CC25の関数を考えてみる。分岐が25本あるということは、完全なテストカバレッジには最低25個のテストケースが必要だ。そのうちの1本でも漏れれば、バグは本番環境で出る。

## どこから手をつける？変更頻度との掛け合わせが答えだ

高複雑度 × 高変更頻度の関数が最優先だ。変更されないコードが複雑でも、バグのリスクは低い。書き直すコストに見合わない。

次のgitコマンドで変更頻度の高いファイルを特定できる：

`git log --format=format: --name-only | grep -v "^$" | sort | uniq -c | sort -rn | head -20`この出力とCCスコアを組み合わせると、優先度マトリクスが作れる。CCが20でコミット頻度が月1回のファイルより、CCが12で週3回触るファイルのほうが先に直すべきだ。

CodeSceneはこの「ホットスポット分析」を自動化している。循環的複雑度 × コミット頻度でヒートマップを生成し、次に何を直すかを一目で示す。

![循環的複雑度と変更頻度で優先度を可視化するヒートマップ](https://fdzlnqpwsaniezitwiuw.supabase.co/storage/v1/object/public/cms-media/whatshouldibuildnext/2026-08/aec123-inline1.webp)

## SonarQube、CodeScene、Code Climate：3ツールの実力差

ツールによって計算の粒度と提供する洞察が違う。知っておくべき差異がある。

**SonarQube**は関数ごと、クラスごと、プロジェクト全体のCCを出す。オープンソースのCommunity Editionで十分計測できる。CIに組み込むならSonarQube Scannerを使う。既存のGitHub Actions / GitLab CI連携も揃っている。

**CodeScene**はCCをコミット履歴と組み合わせる。「技術負債の利子」を可視化するのが強みだ。前述のホットスポット分析が自動化されており、SaaS版の料金は2026年時点で月$39から始まる。

**Code Climate Quality**はGitHub PRに自動でCC差分を表示する。CIパイプライン前提で設計されており、設定が最も簡単だ。PRを出すたびにCCの増減が数値で見える。

## リファクタリング前にテストを書く：順序を間違えるとリグレッションになる

複雑な関数にテストがなければ、リファクタリングはリグレッションを招く。順序がある。先にテストを書き、次にリファクタリングする。

ルールは単純だ。**循環的複雑度 = 最低限必要なテストケース数**。CCが12の関数には、少なくとも12個のテストが必要だ。それが揃っていない状態でコードを触るのは、セーフティネットなしの綱渡りだ。

テストを先に書くことで、もうひとつの利点が生まれる。テストを書く段階で「この関数は何をするのか」が明確になり、分割のヒントが出てくることが多い。

![テストカバレッジとリファクタリングの関係：CCが指示する最小テスト数](https://fdzlnqpwsaniezitwiuw.supabase.co/storage/v1/object/public/cms-media/whatshouldibuildnext/2026-08/cf7628-inline2.webp)

## 循環的複雑度を下げる4つの実践的な手法

**1. Guard Clause（早期リターン）で条件ネストを潰す**

ネストされた`if`の代わりに、条件が満たされない場合に即座にreturnする。

`# Before（CC: 5）
def process(data):
    if data is not None:
        if data.is_valid():
            if data.size > 0:
                return data.transform()
    return None

# After（CC: 2）
def process(data):
    if data is None or not data.is_valid() or data.size == 0:
        return None
    return data.transform()`**2. ポリモーフィズムでswitch/caseを置き換える**

`switch`文は各caseがパスを追加する。Strategy PatternやFactoryでCCを分散させる。型ごとのロジックをクラスに移すだけでスコアが3〜5下がることが多い。

**3. 関数を分割して単一責任に戻す**

1000行の関数は存在してはいけない。「この関数は何をするか」を一文で言えない場合、分割のサインだ。目安として、関数が20行を超えたら分割の必要性を検討する。

**4. Fail Fastで入力バリデーションを先頭に集める**

入力バリデーションを関数の先頭に集約し、主要ロジックのネスト深さを下げる。エラー処理が先頭に来ると、残りのコードはハッピーパスだけになる。可読性も上がる。

## CI/CDに組み込んで計測ループを自動化する

SonarQubeをGitHub ActionsやGitLab CIに入れれば、PRごとにCC差分が出る。

`# .github/workflows/sonar.yml
- name: SonarQube Scan
  uses: SonarSource/sonarqube-scan-action@master
  env:
    SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
    SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}`Quality Gateを設定する。CCが10を超える新関数はマージをブロックする。レガシーコードには猶予を与え、新コードには厳しくする。この2層運用が現実的だ。

計測が自動化されると、「複雑に見える」という感覚論がコードレビューから消える。「このコードのCCは22で、変更頻度ランク3位だ」という言い方ができる。

## 次に何をbuildするかの判断材料として使う

新機能を追加するか、既存コードをリファクタリングするか。この判断はデータで下せる。

コードベースの複雑度スコアの中央値が15を超えているなら、新機能追加は技術負債の上に技術負債を積む行為だ。スコアを8〜10以下に戻してからbuildする。

逆に中央値が5〜7なら、コードベースは健全だ。自信を持って次のフィーチャーに進める。

ツールが出す数字は感情論を消す。「このコードは複雑に見える」ではなく「このコードのCCは22で、変更頻度ランク3位だ」。そう言えるのが強みだ。次に何をbuildするかは、計測結果が答えを持っている。

## FAQ

### 循環的複雑度の許容範囲はどのくらいですか？

McCabeのオリジナル推奨は1〜10です。NASA、Microsoftも同じ数字を基準にしています。実用上は関数の目的次第で15まで許容するチームもありますが、20を超えたら問題と考えてください。

### どのツールで循環的複雑度を計測できますか？

SonarQube（OSS版あり）、CodeScene、Code Climate Qualityが主要3択です。小規模プロジェクトならlizard（Python製CLIツール）で十分です：`pip install lizard && lizard ./src`で即座に計測できます。

### 複雑度が高いコードは必ずリファクタリングすべきですか？

変更頻度が低く、十分なテストがあるなら後回しで構いません。優先度は「複雑度 × 変更頻度」で決めてください。触らないコードを無理に直すリスクを避けることも大切です。

### テストカバレッジと循環的複雑度の関係は？

CCはテストに必要な最低パス数を示します。CC12の関数に5テストしかなければ、カバレッジ不足が確定しています。テストを書く前に循環的複雑度を確認すると、必要なテスト数の目標が立てやすくなります。

### レガシーコードへの適用方法を教えてください。

まず計測だけ実行し、現状のベースラインを記録してください。次のスプリントから「このファイルに触ったらCCを下げる」ルールを適用するボーイスカウト方式が現実的です。一度に全部直そうとしないことが重要です。

### チームで循環的複雑度をどう共有しますか？

SonarQubeのダッシュボードをチームの週次レビューに組み込む方法が効果的です。Code Climate QualityやCodeClimateをPRに連携させ、コードレビュー時にCC差分が自動で表示される設定も有効です。

### 数値を下げるだけで品質は上がりますか？

CCは必要条件であって十分条件ではありません。スコアを下げるためだけに「変数を増やして分岐を隠す」リファクタリングは逆効果です。可読性と合わせて判断してください。目標はCCが低くて読みやすいコードです。