AI駆動開発で敵対的レビューが必要な理由|AI生成コードの品質を高める方法
AI駆動開発によって、コードを書く速度は大きく変わりました。
以前なら数時間かかっていた実装でも、要件を整理してAIエージェントに渡せば、実装・テスト・修正まで短時間で進められることがあります。
実際、AIを活用することで開発速度はかなり上がります。
一方で、AI駆動開発を続けていると、別の問題も見えてきます。
それが、
「作る速度に、レビューする速度が追いつかない」
という問題です。
しかもAIが生成するコードは、明らかに壊れているとは限りません。
コンパイルできる。
テストも通る。
コードも一見きれい。
それでも、特定条件でだけ壊れたり、要件を微妙に取り違えていたり、既存機能に副作用を出していたりすることがあります。
そこで弊社では、AIに実装させるだけでなく、あえてその実装を疑い、壊しにいく**「敵対的レビュー」**という考え方を重視しています。
敵対的レビューとは何か
ここでいう敵対的レビューとは、セキュリティ上の攻撃をするという意味ではありません。
簡単に言えば、
「この実装は正しい」という前提を捨てて、「間違っているとしたらどこか」を探すレビュー
です。
通常のレビューでは、
「このコードに問題はないか」
と確認します。
一方、敵対的レビューでは、
「この実装を壊せる入力はないか」
「要件を満たしていない箇所はないか」
「既存機能を壊していないか」
「権限のない人でも操作できないか」
「同時実行されたらどうなるか」
「テストされていない条件はないか」
といった方向から確認します。
つまり、実装者の味方になるのではなく、反例を探す役割を明確に作るという考え方です。
なぜAI生成コードほど必要なのか
AI生成コードの難しいところは、もっともらしい間違いを作れることです。
構文エラーが出るわけでもなく、コード品質も一見高い。
しかし、前提条件を一つ誤解しているだけで、全体としては間違った実装になっていることがあります。
さらに問題なのが、実装したAI自身にそのまま、
「このコードをレビューして」
と依頼するケースです。
もちろん、それでも問題を見つけられることはあります。
ただし、同じ会話、同じ前提、同じ要件解釈を引き継いでいると、最初の誤解まで共有してしまう可能性があります。
そのため重要なのが、
実装する役割と、疑う役割を分けること
です。
人間の開発チームでも、実装者とレビュアーを分けることがあります。
AI駆動開発でも、この役割分離は同じように有効です。
「テストが通った」だけでは完成ではない
AI駆動開発では、テストコードまでAIに書かせることが増えています。
これは非常に便利です。
しかし、ここにも落とし穴があります。
AIが要件を誤解していた場合、
誤解した実装と、その誤解した実装を正しいと証明するテスト
がセットで完成する可能性があります。
つまり、
「テストが緑だから正しい」とは限らない
ということです。
テストが確認しているのは、あくまで「書かれたテストの範囲」です。
そのテスト自体が不足していれば、当然見逃しも発生します。
だからこそ、テストとは別に、
「要件そのものに合っているか」
「テストされていない条件はないか」
を確認する役割が必要になります。
弊社では「作るAI」と「疑うAI」を分ける
弊社でも、AI駆動開発ではできるだけ役割を分離しています。
例えば、
プランナー
↓
実装者
↓
テスター
↓
レビュアー
という形です。
実装担当AIの「完了しました」という自己申告だけで終わらせません。
レビュー担当には、
「良いところを探してください」
ではなく、
「この実装をRejectするとしたら、理由を探してください」
という方向で確認させます。
特に見るのは、
- 要件漏れ
- 境界値
- エラー処理
- 権限
- データ不整合
- 既存機能への副作用
- セキュリティ
- 不要な複雑化
- 保守性
といった項目です。
AIに「問題ありますか」と聞くだけではなく、
「どこから壊せるか」
という問いに変えることで、レビューの性質がかなり変わります。
実装前にImplementation Planを作る
もう一つ重要なのが、実装前に正解の範囲をある程度固定することです。
弊社では、いきなりAIに、
「この機能を作って」
とは依頼せず、先にImplementation Planを作るようにしています。
例えば、
- 何を変更するのか
- 変更対象はどこか
- 影響範囲はどこか
- リスクは何か
- どんなテストが必要か
を整理します。
これにより、AIが勝手に仕様を広げたり、不要な箇所まで触ったりするリスクを減らせます。
さらにレビュー時には、
「Implementation Planと実装結果が一致しているか」
という明確な比較軸を持てます。
AIに任せないチェックも重要
すべてをAIに判断させる必要はありません。
むしろ、機械的に確認できるものは、機械に任せたほうが安定します。
例えば、
- lint
- 型チェック
- 静的解析
- Unit Test
- Integration Test
- E2E Test
- CI
- セキュリティチェック
などです。
こうしたチェックは、曖昧な判断よりも決定論的な仕組みのほうが向いています。
AIにはその上で、
「そもそも要件を満たしているか」
「設計に不自然さはないか」
「ユーザー目線で正しいか」
といった、意味の理解が必要な領域を担当させます。
UIはコードではなく実際の画面で確認する
Webシステムでは、コード上正しくても画面が正しいとは限りません。
例えば、
- ボタンが押せない
- モーダルが隠れる
- レイアウトが崩れる
- 特定操作でエラーが出る
- 旧画面と挙動が違う
といった問題です。
そのため弊社では、Playwrightなどを使って、実際にブラウザを操作するところまで確認しています。
画面リプレースなどでは、
- 見た目のParity Check
- 機能のParity Check
- 操作シナリオ
- ATDD
なども組み合わせています。
つまり、
「コードとして正しい」から「ユーザーが操作して正しい」まで確認範囲を広げる
という考え方です。
敵対的レビューにも弱点がある
ただし、厳しくレビューすればするほど良いわけではありません。
AIは、
「将来的に問題になる可能性があります」
「改善できる余地があります」
と、いくらでも指摘できます。
すべて対応していたら、今度はレビューが開発速度を落とします。
そこで重要なのが、
指摘にも証拠を求めること
です。
例えば、
- 該当ファイル
- 該当箇所
- 再現条件
- 期待する挙動
- 実際の挙動
- 影響範囲
- 重要度
まで示させます。
「なんとなく危険」と「実際に壊れる」を分けるためです。
「AI VS AI」にすれば品質が上がるわけではない
実装AI、レビューAI、さらにレビューをレビューするAI、と増やせば品質が無限に上がるわけではありません。
場合によっては、
A「問題ありません」
B「問題があります」
C「Bの指摘は誤りです」
という堂々巡りになります。
重要なのはAIの数ではなく、
役割と合格条件が明確になっているか
です。
そして、人間、AI、テスト、CI、静的解析、それぞれに役割を持たせることです。
AI時代の品質は「コード」ではなく「仕組み」で担保する
AI駆動開発が進むほど、人間の仕事も変わっていきます。
これまでは、
「どうコードを書くか」
が中心でした。
これからは、
「AIが間違えることを前提に、どう品質を担保するか」
がより重要になります。
AIは、実装もできます。
テストもできます。
レビューもできます。
そして、壊す役割もできます。
だからこそ、
作るAIだけではなく、壊すAIも用意する。
さらに、AIの判断だけに依存せず、テスト、静的解析、実ブラウザ確認、人間の判断を組み合わせる。
AIによってコード生成速度が上がれば上がるほど、
「どう作らせるか」以上に「どう疑うか」が重要になる。
これが、AI駆動開発で高い品質を維持するための大きなポイントだと考えています。