多くのレビューが「表面チェック」と「設計判断」を混ぜている

コードレビューで起こること。

  • メモリリークがないか調べる
  • 例外が飲み込まれていないか確認する
  • SQL インジェクションの脆弱性はないか見る
  • 設計の責務分離が妥当か検討する
  • このアルゴリズムは本当に必要か疑問を呈する
  • チームの慣例に合っているか確認する

前半 3 つは「検査」。後半 3 つは「判断」。

検査はツールが得意。判断は人間が得意。

/code-review/security-review が見つけるもの

これらのコマンドは 一定のルール違反を機械的に見つけることに特化 している。

/code-review が検出しやすいもの

  • 型安全性の違反(型が宣言と合わない)
  • 変数の初期化漏れ
  • 使われていない変数やインポート
  • エラーハンドリング漏れ(エラーを受け取ったが処理していない)
  • 標準的な脆弱性パターン(ハードコードされた認証情報など)
  • テストカバレッジの低い領域の変更

/security-review が検出しやすいもの

  • SQL インジェクション可能な文字列結合
  • 認証・認可の不備(保護すべき操作が保護されていない)
  • 暗号化なしで機密データを送信
  • 既知の脆弱なライブラリを使用
  • CSRFトークン検証の漏れ
  • ファイルシステムアクセスの境界検証なし

共通点: すべて「パターンマッチング」

これらは、既知の「悪いパターン」を探している。「if で認可チェックしているか」「SQL を構築する際に parameterized query を使っているか」「メモリ割り当て後に解放しているか」。

ツールは 同じ問題が何度も起きているパターンを記憶して検出する

これらのツールが見落とすもの

1. 責務の曖昧さ

def process_user_data(user_id, config):
    user = fetch_user(user_id)
    data = transform_data(user)
    store_data(data)
    send_notification(user)
    log_event(user_id)
    update_cache(data)
    return data

この関数は何をしているのか。ユーザーデータを取得し、変換し、保存し、通知し、ログし、キャッシュを更新する。この関数の責務は 1 つか 6 つか?

/code-review は「エラーハンドリング漏れ」は見つけるかもしれない。だが「この責務分離は妥当か」という判断は、ツールの範囲外。なぜなら「正解」がルール化できないから。

チームによって異なる。API 層では一度に複数の操作をしてもいい。ドメイン層では単一責務が必須。ツールはそのコンテキストを知らない。

2. 設計の過不足

class UserRepository {
  getById(id) { ... }
  getByEmail(email) { ... }
  getByName(name) { ... }
  getActive() { ... }
  getInactive() { ... }
  getCreatedAfter(date) { ... }
  // あと 10 個のクエリバリエーション
}

各メソッドは正しく動く。型安全。例外処理も。だが 「この repository はクエリ方法を持ちすぎているのでは」 という設計判断は?

ツール: 「すべて型安全で、エラーハンドリングもある。OK」

人間のレビュアー: 「getByName と getByEmail の違いは何か。この粒度が必要か。フィルタビルダーで統一できないか」

3. コンテキストに基づく判断

if random.random() > 0.5:
    # 50% の確率で実行
    run_migration()

脆弱性か。型エラーか。いいえ、テストの不安定さ という判断。ツールは「これは危ない」と判定できない。なぜなら「テストが確実性を求める」というビジネスルールを知らないから。

実務パターン: ツールと人間の役割分担

パターン 1: まずツールで「必須チェック」を済ませる

リビジョン提出時に自動的に実行。

/code-review      # ルール違反を検出
/security-review  # 脆弱性パターンを検出

ツールの役割: 「このコード、明らかに壊れているところある?」に答える

結果: メモリリーク、初期化漏れ、認可漏れが引っかかる

パターン 2: 人間は「それ以外」に集中

ツールが通ったコードに対して、人間のレビュアーは:

  • 「この責務分離、妥当か」を聞く
  • 「このアルゴリズムの効率性、実務的か」を検討する
  • 「チームの方針に合っているか」を判断する
  • 「将来の保守がしやすいか」を見る
  • 「テストで本当に必要なケースをカバーしているか」を確認する

パターン 3: ツールで見落とされるものを補強する

/security-review が「暗号化の脆弱性」を見つけるのは得意。

だが「なぜこのデータを暗号化する必要があるのか」という設計判断は見落とす。

レビュアーが「このデータ、本当に暗号化が必要か。保存期間は最小限か。アクセス制限では不十分か」という高次の質問をする。

よくある誤解

「ツール見直しは軽い」 ← 誤り

ツール見直しも「本当に必要な修正か」を人間が判断する必要がある。

例: /code-review が「この変数は使われていない」と指摘。

  • 実際に不要なら、削除。
  • デバッグ用に残してある意図的な変数なら、コメント追加。
  • チームの慣例で「意図を示す」ために使われるなら、スキップ。

ツールは「使われていない」と言うだけ。「削除すべきか」は人間の判断。

「ツールで OK なら、レビューは最小限」 ← 誤り

ツールが見落とすものを見つけるのがレビューの本質。

ツールの出力を「チェックリスト」だと思うと、人間のレビュアーは「チェックリストの監査役」になり、本当の設計判断から目が離れる。

逆に、ツールの出力を「表面チェックの自動化」だと考えれば、人間は「設計と意図」に集中できる。

最後に: 時間を削るのは「ツール」ではなく「分業」

/code-review/security-review が価値を発揮するのは、 これらを「人間のレビューの代替」ではなく「前工程」として使った時 だけ。

ツールで「明らかな問題」を先に見つけて消す → 人間は「判断を要する部分」だけに注力する。

この分業ができると、レビュー時間は 30% 短縮される。だが理由は「ツールが強い」からではなく、「人間の時間が『本来のレビュー仕事』に戻った」から。

逆に「ツールが通ったから、レビュー浅くていいや」と考えると、設計の問題や長期保守性の落とし穴を後から何度も踏むことになる。

ツールと人間の役割の境界線を明確にすること。それがコードレビューの効率化の本質。