AI生成コードのレビュー方法を“やさしく深く”理解する:動くだけでは危険な理由と確認すべきポイント【初心者向け+実務の基礎】

AI-Assisted Engineering

🤖【初心者向け】AI生成コードのレビュー方法をやさしく解説:動くだけでは正しくない理由

ChatGPTやGitHub Copilotなどの生成AIを利用すると、プログラムを短時間で作成できるようになりました。

以前なら数十分かけて調べながら書いていた処理も、AIに依頼すれば数秒から数分でコードが提案されることがあります。

しかし、ここで気を付けたいことがあります。

「AIが生成したコードは、実際に動いたのだから問題ない」

この考え方には落とし穴があります。

プログラムは、動くことと、正しいことが必ずしも同じではないからです。

この記事では、まず初心者向けにAI生成コードをレビューする基本的な考え方を解説します。

後半の深掘り編では、境界値、例外処理、セキュリティ、テスト設計、AI特有のリスクまで踏み込み、実務でどのように品質を確認すべきかを整理します。


結論:AI生成コードは「完成品」ではなく「検証対象」

最初に結論です。

AIが生成したコードは、そのまま信用するのではなく、仕様に照らして検証する必要があります。

AIが生成したか、人間が書いたかに関係なく、コードにはレビューとテストが必要です。

ただしAI生成コードでは、特に「見た目が自然で、正しそうに見える」という特徴に注意が必要です。

AIがコードを生成
       ↓
仕様と比較
       ↓
処理内容を確認
       ↓
例外・境界値を確認
       ↓
セキュリティを確認
       ↓
テストを実行
       ↓
採用を判断

重要なのは、AIの回答を正解として扱わず、仕様を正解の基準にすることです。


なぜAI生成コードは間違えるのか?

生成AIは、入力された指示や周辺の情報をもとにコードを生成します。

しかし、AIがコードを生成したという事実だけでは、実際の業務仕様やシステム全体との整合性は保証されません。

たとえば、次のような問題が起こり得ます。

  • 仕様に書かれていない動作を勝手に補っている
  • 存在しないメソッドやAPIを使用している
  • 古いライブラリの書き方を使っている
  • 正常系しか考慮していない
  • セキュリティ上の問題を含んでいる
  • 既存システムの設計方針と合っていない

しかも、こうした問題があっても、コードの見た目は自然な場合があります。

つまり、読みやすいコードだから正しいとは限らないのです。


「動くけれど間違っている」コードの例

簡単なJavaの例を考えてみます。

仕様は次のとおりです。

商品の合計金額が5,000円以上の場合、送料を無料にする。それ未満の場合は送料500円を加算する。

AIが次のコードを生成したとします。

public int calculateTotal(int price) {
    if (price > 5000) {
        return price;
    }

    return price + 500;
}

一見すると問題なさそうです。

5,500円なら送料は無料です。

3,000円なら送料500円が加算されます。

しかし、5,000円の場合はどうでしょうか。

price = 5000

5000 > 5000
    ↓
false
    ↓
送料500円が加算される
    ↓
合計5500円

仕様では5,000円以上なので、5,000円ちょうどでも送料無料になるべきです。

正しくは次の条件です。

if (price >= 5000) {
    return price;
}

このように、コンパイルが通り、実行できても、仕様を満たしていないコードは存在します。

なお、実際の業務では負の金額や金額の型、税込・税抜の判定基準なども別途定義する必要があります。


コードレビューで最初に見るべきものは「仕様」

コードレビューというと、ソースコードを上から順番に読むことを想像しがちです。

しかし、最初に確認すべきなのはコードそのものではありません。

そのコードが何を実現するべきなのかという仕様です。

仕様
 │
 ├─ 入力は何か?
 ├─ 出力は何か?
 ├─ 正常な条件は?
 ├─ 異常な条件は?
 └─ 守るべき制約は?
       ↓
   コードと比較

仕様を理解しないままコードだけを読んでも、「書かれている処理が動きそうか」は判断できても、「必要な処理がすべて存在するか」は判断しにくくなります。


初心者が確認したい5つのポイント

① 仕様どおりの処理になっているか

まず、入力と出力が仕様どおりになっているか確認します。

先ほどの送料計算なら、5,000円以上と5,000円未満の区別が重要です。

② 境界値が正しいか

境界値とは、条件が切り替わる境目の値です。

今回なら次の3つが重要になります。

商品金額期待する合計
4,999円5,499円
5,000円5,000円
5,001円5,001円

この3つを確認するだけでも、条件式の間違いを発見しやすくなります。

③ 異常な入力を考慮しているか

たとえば次のような入力です。

  • null
  • 空文字
  • 負の数
  • 想定外に大きい数
  • 存在しないID

ただし、すべてのメソッドがこれらを個別に処理する必要があるわけではありません。

重要なのは、どこで入力を検証し、どのように異常を扱う設計なのかを確認することです。

④ 既存コードとの整合性があるか

AIが提案した実装だけを見れば問題がなくても、既存システムのルールと合わない場合があります。

たとえば、既存システムでは共通の例外クラスを利用しているのに、AIが独自の例外処理を追加してしまうケースです。

動作することだけでなく、保守しやすい構造になっているかも重要です。

⑤ テストで確認できているか

コードを読んで問題がなさそうでも、テストは必要です。

特に、正常系だけでなく境界値や異常系まで確認できているかを見ます。


AIにレビューさせれば十分なのか?

生成AIにコードレビューを依頼すること自体は有効です。

たとえば、次のような観点を洗い出す補助として利用できます。

  • 見落としている境界値
  • 例外処理の不足
  • 潜在的なセキュリティ問題
  • 可読性や保守性の改善点

ただし、AIが生成したコードを別のAIにレビューさせたとしても、それだけで正しさが保証されるわけではありません。

AIレビューは問題を発見するための補助であり、仕様確認、テスト、必要な人間のレビューを置き換えるものではありません。


ここまでのまとめ(初心者向け)

AI生成コードをレビューするときは、次の考え方を押さえておきましょう。

  • AIが生成したコードも間違える可能性がある
  • コンパイル成功や実行成功だけでは正しさを判断できない
  • 最初に仕様を確認する
  • 正常系だけでなく境界値や異常系を確認する
  • 既存システムとの整合性も見る
  • AIによるレビュー結果も検証する
AI生成コード
     ↓
仕様と比較
     ↓
境界値・異常系
     ↓
既存設計との整合性
     ↓
テスト
     ↓
採用判断

初心者向けとしては、まずここまで理解できれば十分です。

ここから先は、実務で特に重要になる「なぜテストが通っても安心できないのか」「AI生成コードに潜むセキュリティリスクをどう確認するのか」という部分を深掘りします。


▼▼ 深掘り編ここから ▼▼


AI生成コードのレビューは「差分」から始める

AIが複数ファイルを編集した場合、変更したメソッドだけを見るのでは不十分です。

最初に確認したいのは、変更全体の差分です。

AIへの依頼
  ↓
「送料計算を修正して」
  ↓
実際の変更
  ├─ ShippingService.java
  ├─ ShippingTest.java
  ├─ application.yml
  └─ build.gradle

送料計算の修正なのに、設定ファイルや依存ライブラリまで変更されていたら、その理由を確認する必要があります。

意図しない変更が混ざっている可能性があるためです。

特にAIエージェントがファイルを直接編集する場合、依頼した範囲と実際に変更された範囲が一致しているかは重要なレビュー観点です。


AIが生成したテストも間違える

ここは特に注意したいポイントです。

AIに実装とテストをまとめて生成させると、実装の間違いに合わせてテストまで作られる可能性があります。

先ほどの送料計算を考えてみます。

間違った実装は次のとおりでした。

if (price > 5000) {
    return price;
}

もしAIが次のようなテストを生成したらどうでしょうか。

@Test
void testShipping() {
    assertEquals(
        5500,
        calculateTotal(5000)
    );
}

このテストは、間違った実装に対して成功してしまいます。

間違った実装
      ↓
間違った期待値
      ↓
テスト成功
      ↓
でも仕様違反

つまり、テストが成功したことと、テストの期待値が正しいことは別問題なのです。

テストの期待値は、生成された実装ではなく、仕様から独立して導く必要があります。


テスト設計では「同値分割」と「境界値分析」が役立つ

AI生成コードのテストを考えるときにも、従来のテスト設計技法が役立ちます。

同値分割

同じような振る舞いを期待する入力をグループに分ける考え方です。

送料計算なら、次のように分けられます。

0 ~ 4999
  ↓
送料500円

5000以上
  ↓
送料無料

それぞれのグループから代表値を選び、テストします。

境界値分析

条件が切り替わる境目を重点的に確認します。

4999 | 5000
     ↑
   境界

条件式の「>」と「>=」の間違いなどを検出するのに有効です。

ただし、同値分割や境界値分析だけですべての不具合を発見できるわけではありません。

状態遷移、組み合わせ、並行処理など、対象に応じた別のテスト観点も必要になります。


セキュリティ:SQLインジェクションの例

AI生成コードでは、機能が動作していてもセキュリティ上の問題が残っている場合があります。

たとえば、次のJavaコードです。

String sql =
    "SELECT * FROM users WHERE id = '"
    + userId + "'";

このコードでは、外部から渡された値をSQL文字列へ直接連結しています。

入力内容によってSQLの意味が変わってしまう可能性があり、SQLインジェクションの危険があります。

JDBCであれば、たとえば次のようにパラメータ化したSQLを使用できます。

String sql =
    "SELECT * FROM users WHERE id = ?";

PreparedStatement ps =
    connection.prepareStatement(sql);

ps.setString(1, userId);

ResultSet rs = ps.executeQuery();

値をSQLの構造から分離して扱うことが重要です。

ただし、テーブル名や列名などを動的に組み立てる場合は別途安全な設計が必要です。

「検索結果が正しい」だけでは、セキュリティが正しいとは判断できません。


認証と認可を取り違えていないか?

Webアプリケーションでは、認証と認可を区別する必要があります。

認証は「誰なのか」を確認することです。

認可は「その人が何をしてよいか」を判断することです。

ログイン済み?
    ↓
   認証

このデータを見てよい?
    ↓
   認可

たとえばログイン済みのユーザーが、URL中のIDを書き換えることで他人の注文情報を閲覧できてしまうなら、認可の問題が疑われます。

AIが生成したコードにログインチェックが存在していても、対象データへのアクセス権まで確認しているとは限りません。

レビューでは、「ログインしているか」だけでなく「対象リソースへの操作が許されているか」を確認します。


例外処理は「エラーを握りつぶしていないか」を見る

AI生成コードでは、エラーが発生したときに処理を継続させるため、安易に例外を捕捉する実装が提案される場合があります。

try {
    updateData();
} catch (Exception e) {
    // 何もしない
}

このコードはコンパイルできます。

しかし、更新に失敗しても呼び出し元が失敗を認識できない可能性があります。

レビューでは、次の点を確認します。

  • 例外を捕捉する必要があるか
  • 捕捉する例外の種類は適切か
  • ログや監視で失敗を把握できるか
  • 呼び出し元へ失敗を伝える必要があるか
  • トランザクションの整合性は保たれるか

例外処理は、単にプログラムを停止させないための仕組みではありません。

失敗したという事実を、システム内で正しく扱うための設計です。


存在しないライブラリや古いAPIにも注意する

生成AIは、存在しないライブラリ名やメソッドを提案することがあります。

また、存在するライブラリであっても、現在利用しているバージョンでは使えないAPIを提案する可能性があります。

そのため、外部ライブラリが追加された場合は、次の点を確認します。

  • 実在するライブラリか
  • 公式ドキュメントと一致するか
  • 現在のバージョンで利用できるか
  • 既知の脆弱性がないか
  • その依存関係を追加する必要があるか

AIが提案したパッケージを無条件にインストールすることは避けます。

存在しないパッケージ名を攻撃者が登録し、不正なコードを配布するようなリスクにも注意が必要です。


AIエージェントでは「コード以外の変更」も危険になる

コードを提案するだけのAIと、ファイル編集やコマンド実行まで行うAIエージェントでは、確認すべき範囲が異なります。

AIエージェントは、許可された環境によっては次のような操作も実行できます。

  • ファイルの追加・削除
  • 依存パッケージのインストール
  • テストコマンドの実行
  • CI/CD設定の変更
  • 外部サービスへのアクセス

そのため、コードレビューに加えて、どのファイルが変更され、どのコマンドが実行されたかも確認する必要があります。

特にCI/CD設定、認証情報、Dockerfile、依存関係の設定ファイルなどは、アプリケーションコードとは別のリスクを持っています。


プロンプトインジェクションにも注意する

AIエージェントが外部の情報を読み取る場合、その情報に含まれた不正な指示によって、意図しない操作へ誘導される可能性があります。

たとえば、AIがIssueやREADME、外部Webページを参照するとき、その内容を無条件に信頼してしまうと危険です。

開発者の依頼
    ↓
AIエージェント
    ↓
外部のREADMEを読む
    ↓
不正な指示が含まれる
    ↓
意図しない操作の危険

これはプロンプトインジェクションと呼ばれる問題の一例です。

AIに読み込ませる情報と、AIへ実行を許可する操作を分けて考えることが重要です。

特に、外部情報を読んだだけで本番環境の操作や秘密情報へのアクセスができる構成は避ける必要があります。


AI生成コードのレビューを効率化する順番

すべてのコードを同じ順番で細かく確認すると、時間がかかりすぎる場合があります。

そこで、まず大きな問題から確認する方法が役立ちます。

① 変更範囲
    ↓
② 仕様との一致
    ↓
③ セキュリティ・データ整合性
    ↓
④ 境界値・異常系
    ↓
⑤ テストの妥当性
    ↓
⑥ 可読性・保守性

これはあくまでレビューの一例です。

認証処理や決済処理など、リスクが高い変更では、より厳格な確認が必要になります。

逆に、単純な表示文言の変更であれば、確認する観点は少なくて済む場合があります。

変更の影響度に応じてレビューの深さを調整することも、実務では重要です。


AIを使ってAI生成コードをレビューする方法

AIによるレビューを補助的に利用する場合、単に「このコードをレビューして」と依頼するより、確認観点を指定したほうが有用な結果を得やすくなります。

たとえば次のような依頼です。

以下のJavaコードをレビューしてください。

【仕様】
商品金額が5000円以上なら送料無料。
5000円未満なら送料500円を加算する。

【確認観点】
1. 仕様との不一致
2. 境界値の問題
3. 異常な入力
4. 例外処理
5. セキュリティ
6. 必要なテストケース

問題がある場合は、
該当箇所・理由・修正案を示してください。

判断できない点は推測で補わず、
不明点として明示してください。

このように、仕様と確認観点をセットで渡します。

ただし、AIが指摘しなかった問題が存在しないとは限りません。

また、社外のAIサービスへコードを送る場合は、組織の利用ルールや機密情報の取り扱いを確認する必要があります。


実務で使えるAI生成コードのレビューチェックリスト

最後に、レビュー時の確認項目をまとめます。

観点 確認すること
仕様 要求された処理を満たしているか
変更範囲 不要なファイルまで変更していないか
境界値 条件の切り替わりを確認したか
異常系 不正な入力や失敗時の動作は適切か
セキュリティ 認可・入力検証・秘密情報などに問題はないか
依存関係 ライブラリやAPIは実在し、利用可能か
テスト 期待値が仕様に基づいているか
保守性 既存設計と整合し、理解しやすいか
運用 障害時に検知・調査できるか

すべての変更に同じ重さのレビューを行う必要はありませんが、重要な観点を見落とさないための土台になります。


AI生成コードの品質は誰が保証するのか?

AIはコードを生成できます。

しかし、生成したコードが対象システムの仕様を満たし、安全に運用できるかについては、適切な検証が必要です。

組織開発では、レビュー担当者、開発責任者、品質管理担当者などの役割が定められている場合があります。

そのため、すべての責任を一人の開発者へ単純に帰属させるという話ではありません。

重要なのは、AIを使ったからといって、既存の品質保証や承認の仕組みを省略しないことです。

AI生成コードも、通常のコードと同じように、変更の追跡、レビュー、テスト、承認を経て利用する必要があります。


この記事のまとめ

AI生成コードをレビューする際に重要なのは、コードの見た目やAIの説明を正解として扱わないことです。

仕様を基準に、変更範囲、境界値、異常系、セキュリティ、テストの妥当性を確認します。

AI生成
   ↓
仕様確認
   ↓
差分レビュー
   ↓
テスト設計
   ↓
実行・検証
   ↓
人間による判断
   ↓
採用・リリース

生成AIは開発速度を高める手段になりますが、品質確認まで自動的に完了するわけではありません。

生成の速さと、検証の確かさを組み合わせることが重要です。


Deep Friendly Tech の一言(後書き)

AI生成コードを扱うとき、最も危険なのは「AIが間違えること」そのものではありません。

人間が書いたコードにも間違いはあります。

むしろ注意したいのは、コードが自然で完成度高く見えるため、確認を省略してしまうことです。

AIが書いた
    ↓
動いた
    ↓
正しいはず

ではなく、

AIが書いた
    ↓
仕様と比較した
    ↓
テストした
    ↓
採用できると判断した

AIによってコードを書く時間が短くなったとしても、仕様を理解する力や、不具合を見抜く力の価値がなくなるわけではありません。

むしろ、コードを生成する速度が上がるほど、何を確認すべきか判断する力が重要になります。

AIはコードを書く速度を変えます。

そしてレビューは、その速度で生まれたコードを、信頼できるソフトウェアへ近づけるための工程です。

書く力だけでなく、確かめる力も育てていきたいところです。🌱


参考資料

タイトルとURLをコピーしました