Skip to content

ADR-008: サイクロマティック複雑度制限

ステータス

承認済み

コンテキスト

コードの複雑性を管理し、テスタビリティと保守性を向上させるため、サイクロマティック複雑度の上限を設定する必要がある。

サイクロマティック複雑度は、プログラムの複雑性を測定する指標で、以下の要素をカウントする: - 条件分岐(if, else if, else) - ループ(for, while, do-while) - case文 - 論理演算子(&&, ||)

決定

サイクロマティック複雑度の上限を7に設定する。

ESLintのcomplexityルールを使用して、この制限を自動的に検証する。

rules: {
  'complexity': ['error', { max: 7 }]
}

根拠

複雑度7を選択した理由

  1. テスタビリティの確保
  2. 複雑度7以下の関数は、すべてのパスを網羅するテストケースが現実的に作成可能
  3. 複雑度が高いほど、必要なテストケース数が指数関数的に増加

  4. 認知的負荷の軽減

  5. 人間が一度に理解できる複雑性には限界がある
  6. 複雑度7は、多くの研究で推奨される上限値(5-10の範囲内)

  7. リファクタリングの促進

  8. 複雑度が高い関数は、単一責任の原則に違反している可能性が高い
  9. 制限により、開発者は自然と関数を小さく分割するようになる

複雑度と品質の関係

複雑度 コードの品質 リスクレベル
1-3 シンプル
4-7 普通
8-10 複雑
11+ 非常に複雑 非常に高

結果

ポジティブな結果

  • コードの可読性向上: 複雑な関数が小さな単位に分割される
  • テストカバレッジの向上: すべてのパスをテストしやすくなる
  • バグの削減: 複雑度が低いコードはバグが少ない傾向がある
  • 保守性の向上: 将来の変更が容易になる

ネガティブな結果

  • 初期の開発速度: リファクタリングに時間がかかる可能性
  • 関数数の増加: より多くの小さな関数が必要になる

実装例

Before(複雑度が高い)

function processGame(state: GameState, action: Action): GameState {
  if (action.type === 'MOVE') {
    if (state.currentPuyo) {
      if (action.direction === 'left') {
        if (canMoveLeft(state)) {
          // 移動処理
        }
      } else if (action.direction === 'right') {
        if (canMoveRight(state)) {
          // 移動処理
        }
      } else if (action.direction === 'down') {
        if (canMoveDown(state)) {
          // 移動処理
        }
      }
    }
  } else if (action.type === 'ROTATE') {
    // 回転処理
  }
  // さらに続く...
}

After(複雑度を下げた)

function processGame(state: GameState, action: Action): GameState {
  switch (action.type) {
    case 'MOVE':
      return handleMove(state, action)
    case 'ROTATE':
      return handleRotate(state, action)
    default:
      return state
  }
}

function handleMove(state: GameState, action: MoveAction): GameState {
  if (!state.currentPuyo) return state

  const moveHandlers = {
    left: moveLeft,
    right: moveRight,
    down: moveDown,
  }

  const handler = moveHandlers[action.direction]
  return handler ? handler(state) : state
}

参照