AI・信頼性・評価
AI生成コードのコードレビューは何を見る?目的・危険度・仕様
- コードレビュー
- ソフトウェア工学
- AI協働
- 仕様
- 要求工学
- 多層防御
- Design by Contract
- 自動化バイアス
- 受け入れテスト
- 受け入れ基準
- 不変条件
- 静的解析
- 性質ベーステスト
- Naur
- プログラムの死
- superpowers
- Claude Code
- コンプレイセンシー
- 抜き取り監査
- マイグレーション
- Eiffel
- TDD
- 双方向の扉
目次
AIにコードを書かせると、差分は速く大量に返ってくる。型は通り、テストも緑だ。だが、これをどうレビューすればいいのか。中身を全部読む気力も注意も無い。かといって素通しは怖い。
逆の失敗もある。「いい感じにログ基盤を整えて」とだけ頼むと、AIは立派な構成を返してくる。よくできている。ただ、本当に欲しかった要件は一つも入っていない。指示が曖昧だったぶんを、AIが「それらしく」埋めるからだ。埋めた内容が意図とずれても、AIは教えてくれない。
この二つは別の失敗に見えて、根は同じだ。速く大量に返るからこそ、渡す前にやるべきことが露わになる。
本稿は、Googleのコードレビュー研究と、同じ著者が加わった書物を例に取る。
速く大量に返るAIの出力を、限られた注意でどう検証し、生成の前に何を固めればよいのか。
レビューの第一の目的は欠陥を全部捕まえることではなく、コードベースの健全性を守り知識と規範を移すことにあり、この目的から、機械が判定できる性質は機械に、外すと痛い変更は人の深い精査に、判定できる意図は生成前の固定に回すことが決まる。 どれもAI以前からある規律で、AIの速い生成はもとからあった弱さを露わにしただけだ。ただしAI出力には、変更の理屈を持ってレビュアーの問いに答える著者がいない。
三百行の差分を、性質ごとに三つの関所へ分ける
※ この節の数値は説明のための仮定で、測定値ではありません。
AIが返した三百行の差分に、三種類の変更が混ざっているとする。返り値の形を変える二百行、列を一つ落とすマイグレーション二十行、ログの文言を直す八十行である。
返り値の形はスキーマとの照合で合否が出るので、機械の検査に任せる。列を落とすマイグレーションは戻せないので、別の人が深く読む。ログの文言は戻すのが安いので、数か所を抜き取って見る。
三百行を同じ深さで読むと、注意の大半は二百行と八十行に使われ、戻せない二十行に残る注意は小さい。
レビューの目的は、欠陥を全部捕まえることではない
まず、レビューは何のためにあるのか。ここを取り違えると、AIが来た瞬間に道具ごと壊れる。だから実行方法より先に、目的を据える。
Googleが自社のコードレビュー運用を調べた研究で、Sadowskiらはこう報告している。レビューへの期待の中心は、教育とコードの読みやすさ・分かりやすさにある。しかもそれは変化の結果ではなく、Googleがレビューを導入した当初からの動機に沿ったものだ、と。同論文は「欠陥発見から集団的な問題解決へ移った」という先行研究(Rigby と Bird)の見立てを挙げたうえで、Google の実態はそれとは一致しないと明言している。導入の動機そのものを、同論文はレビューを導入した初期従業員1名への回顧インタビューから取っている。バグが見つかるのは結構なことだが、導入の第一の理由はコードの分かりやすさと保守性を上げることだった。加えて同論文は、各コードを二人以上が知っている状態を作って知識が社内に残る確率を上げることを挙げている。規範を保つことのほうは導入時の動機ではなく、いまの開発者がレビューに期待する四テーマの一つとして挙がる1。
同じ著者(Caitlin Sadowski)が加わった、Googleが自社のエンジニアリング文化を明文化した書物の第9章も同じ向きを語る。正しさの検査はレビューの第一の便益ではない、とまで書く2。ただし独立した二つ目の証拠ではなく、同じ書き手による別媒体での記述として読むのが正しい。つまり、レビューの第一の目的はコードベースの健全性を守り、知識と規範を移すことにある(「健全性」は書物の語彙で、中身のほうは論文が持っている)。
欠陥発見が消えるわけではない。論文の Finding 1 自身が欠陥発見は歓迎されるが唯一の焦点ではないと結んでおり1、書物もそれを「左へ寄せる」戦略の一部であり多層防御の一枚だと位置づけている2。順位の話であって、有無の話ではない。
目的をこう据えると、実行方法はほぼ自動的に決まる。注意は有限だ。守るべきが健全性なら、レビューは網羅(量)ではなく、限りある注意を危険の濃いところへ配ることになる。不可逆な変更、影響範囲の広い変更、静かに失敗する変更には深く。可逆で低リスクな変更には浅く。均一な網羅は、むしろ注意の誤配分だ。決定的な差分に注ぐべき精査を、見ても得るもののない差分で使い切ってしまう。
そしてこの目的は、AIが来ても変わらない。AIは人間がすでに走らせてきた流れに乗るだけで、その流れには昔から関所があった。コードレビュー、多層防御、trust but verify、変更管理のゲート、出典の吟味。全部AI以前の規律だ。だから「AIが作ったからゲートが効かない」という嘆きは、AIだけの問題ではない。まずゲートの問題だ。AI出力を捕まえられないゲートは、最初から弱かった。速い生成が、その弱さを露わにしただけだ。
ただし、AI特有のほころびが一つある。レビューが知識と規範の移転なら、それは変更を書いた本人が変更の理屈を持ち、レビュアーの問いに答えられることを前提にしている。この前提を支えているのは、Naurが「理論」と呼んだものだ。Naurは、理論を持つチームが解散した状態を「プログラムの死」と呼ぶ。死んだプログラムも、実行されて有用な結果を出し続けることがある。その死が見えるのは、変更の要求に知的に答えられなくなったときだ。しかも Naur は、文書だけから理論を建て直すことは「厳密に不可能」だとする3。AI出力にはその著者がいない。だから関所は残る。抜けたのは、関所を通す側の理屈のほうだ。
危険の濃さで、精査の深さを変える
では、この目的からどう関所を張るか。これは新しい線ではない。古くからある仕分け、つまり機械判定できるか・可逆か・静かに壊れるかを、レビューの深さに当てはめるだけだ。配り方は、二つの問いに絞れる。その性質は機械が判定できるか。外したとき、被害はどれだけ大きく、取り返せるか(静かに壊れる失敗もここに含める)。 これで、どの差分をどの関所に流すかが決まる。
- 型・境界・不変条件のように機械が判定できる性質は、機械の検査で合否を出す。 見分ける問いは「意見を挟まず pass/fail を出せるか」。出せるなら、その判定に人間の注意は要らない。例:返り値がスキーマに合うか、「残高は負にならない」という不変条件を壊していないか、null 参照や未処理の例外がないか、マイグレーションに逆操作があるか。事前条件・事後条件・不変条件を機械可読な契約として書く契約による設計(Bertrand Meyer の Design by Contract)4や、性質ベーステストが機械化してきた領域で、機械が pass/fail を出す仕組みへ投げ、その性質の判定には人間の注意を割かない。ただし機械が確かめるのは書いた条件だけで、条件が足りているかは人間が判断する。ここで機構を取り違えないこと。契約を潰すのは静的解析ではない。実行時の監視が、破れたときにそれを検出する(しかも Meyer が題材とする Eiffel では、監視はクラスごとの選択式で、既定は事前条件のみ)。判定を返すには、契約と、それを走らせる仕組みが対で要る。この配り方には、Google の実運用にも対応物がある。Google はコミット前に開発者の明示的な override を要求するチェックを置いている。チーム固有の不変条件はそこで強制できる(コミットを止めない自動解析は、それとは別に併走している)1。
- 機械では判定できず、外すと痛い変更は、独立したレビュアーで深く精査する。 「この抽象は妥当か」「この説明は正しいか」「未知の攻撃に耐えるか」に pass/fail はない。見分ける問いは被害の重さである。不可逆か・影響範囲が広いか・失敗が静かかのどれかに当たるものが、その対象だ。例:列を落とすマイグレーション(不可逆)、認可やアクセス制御の変更(影響が広く、失敗が静か)、多数が依存する共有基盤の変更。希少な人間の判断はここへ集める。ただし人数を足すこと自体は解にならない5。「検証者を誰が検証するのか」という多層防御の問いも、ここに残る。
- 機械では判定できないが、可逆で害が小さく取り返せる変更は、抜き取り監査で通す。 見分ける問いは「外しても安く戻せるか」である。一方向でなく双方向の扉かを見る(Amazon の一方向/双方向の扉。前者は不可逆ゆえ慎重に、後者は戻せるゆえ軽い判断でよい)6。例:文言やログ文の調整、内部スクリプト、フラグで即オフにできる変更。全数を精査せず、標本を見て流す。ここで全数に網をかけると、Bezos が大組織の症状として挙げた遅さ、考えの伴わないリスク回避、実験不足、そして発明の減衰がそのまま出る6。
初期値はこうだが、深さは行数ではない。差分のすべての行に目を通したことは、精査したことではない。存在を確かめただけで、正しさを問うたことにはならない。
だから、人間の手をどこに使うかも同じ原則で決まる。機械がすでに保証できる場所は、機械に譲る。今後さらに自動化できるなら、なおのこと譲る。腕が鈍るのを恐れて、自動化できる仕事にわざわざ人が手を出すのは本末転倒だ。Google 自身の書物も、静的解析と自動テストが強くなるにつれ正しさの検査を人間のレビューに頼る必要は明確に減ったとし、そのうえでツールが人間による検査の価値を完全に無くすことはないかもしれないと断っている2。希少な人間の判断は、機械の保証がまだ届かない場所にこそ集める。
この「独立したレビュアー」を実装でどう作るかには、実例がある。superpowers という Claude Code 向けのスキル集は、タスクごとに新品のコンテキストを持つ別のエージェントを実装役に立てる。v5.1.0 では、完了ごとに二段のレビューを固定順で回していた。まず仕様に合っているかを見て、それが通ってから品質を見る。仕様の確認が通る前に品質レビューを始めることは、「順序違い」の赤旗に挙がっていた7。ただし上流は2026年6月の v6.0.0 で、二人のレビュアーを一人に統合した。一人が差分を一度だけ読み、仕様準拠と品質の二つの判定を返す。読む順は仕様が先のままだが、仕様が通るのを待ってから品質レビューを始める、という二段の待ち合わせはなくなった。上流は理由として、実プロジェクトでの費用と品質の実験を重ねた結果、一タスクに二人のレビュアーを走らせ、モデル選びと重大度をまとめ役の判断に任せる旧来の流れが、高くつき、ごまかされやすいと分かったと書いている7。そしてここでの「独立」は、人を替えることではなくコンテキストを替えることを指している。同じコンテキストを抱えたまま自分の出力を見直せば、隙間を埋めた前提もろとも引き継ぐ。
ただしこの集まり自体は、機構ではなく指示だ。実行時にコードを止めるフックは持たず、注入するのはコンテキストだけで、無視しても赤くはならない7。よくできた手順書があることと、それが守られることは別だ。
人間の査読の側にも、AI以前の規律では答えきれない弱さがある。正解のない生成物を、参照なしで「良し悪し」まで評価すること。多層防御が前提にしてきた「懐疑的な人間の査読者」を、AIの流暢さが静かに侵食すること。人間は自動化の出力を過信し、監視を緩めやすい。研究はこれを自動化への過信(コンプレイセンシーと自動化バイアス)として繰り返し観測してきた。コンプレイセンシーは、手元の作業が自動化の監視と注意を取り合う、複数作業の負荷の下で起きる。しかもどちらも素人・熟練者を問わず現れる。とくに自動化バイアスは単なる訓練や指示では防げず、個人だけでなくチームでも起きる(コンプレイセンシーのほうは、単なる練習では克服されない)5。だから「気をつけろと言う」も「人を足す」も、それ自体では解にならない。
曖昧な指示では、欠けた仕様をAIが埋めてずれる
もう一つの錯覚がある。「曖昧に頼んでも、AIが意図を汲む」というものだ。生成が安くなれば、ボトルネックは仕様の質へ移る、と本稿は見ている。仕様が欠けていると、AIはそこを「もっともらしく」埋める。埋めた内容が意図とずれても、AIは教えてくれない。静かにずれたまま、速く大量に返ってくる。
この「埋める」が何として現れるかは、レビュー項目として実装されている。さきの仕様レビューは、頼まれていない機能の追加を欠陥として数える。v5.1.0 のレビュー例には「Extra: Added —json flag (not requested)」がそのまま載っている7。仕様の隙間は、足りない形だけでなく余分な形でも現れる。しかも余分な実装は動いてしまうぶん、足りない実装より見つけにくい。
ここでも同じだ。判定できる意図を生成の前に固定し、AIの埋め合わせが静かにずれる余地を先に消す。同じ集まりは、設計の承認が下りるまで実装へ進むことを禁じる関門をスキル本文の中に置いている7。これは固定を「先に」やらせる仕掛けである。
これは新しい問題ではない。要求工学、受け入れ基準、TDD。意図を固定する仕事は、AIよりずっと前からソフトウェア工学の中心にあった。Meyer は1992年に、アサーション監視とは「ソフトウェアが実際にすることを、作者がすると思っていることと突き合わせて、その見栄を暴く」ことだと書いている4。
受け入れテストの形(Fit テーブル)で具体的な入出力の例を要求に添えると、要求の理解が実際に改善することも、学生を被験者にした二つの実験が示している。しかも理解にかかる時間は有意には増えなかった8。ただしこの実験で効いたのは具体性であって、実行可能性ではない。被験者は表を実行する手立てを与えられておらず、読んだだけである。
一方でNaurは1985年に、プログラムを書くとは文書に書き尽くせない「理論」を頭の中に築くことだと論じた。Naur が言うのは自然言語に限った話ではない。記法や形式化の選択は二次的な問題であり、Naur は仕様書もその一つとして名指ししたうえで、理論そのものが表現されえないとする。Naur はそこから「プログラミングの主たる活動に正しい方法は存在しない」まで進み、各段が文書化された成果物を生む行為の列として開発を捉える方法観そのものを否定する3。本稿の処方、つまり先に仕様を固定し、固定順の関門を置くことは、その型に当たる。
Naur 自身も方法を丸ごと捨ててはいない。方法を機械的に良い解へ導く規則の体系とみる考えは幻想だという Floyd らの結論を引き、方法に残るのはプログラマの教育への効果だとして、それを自説と両立するとする。記述と検証の技法への習熟が、築かれる理論の質を大きく左右するとも書く。そのうえで方法論者と分かれる点を「どの技法を、どの順で使うか」に置き、それは解くべき問題を見てプログラマが全面的に決めることだとする3。本稿の固定順の関門は、この順序の軸で Naur と分かれる。固定できる意図は固定で減らせるが、固定しきれない意図は必ず残る。そして残った分は、行為の列では取れない。
検証可能性と表現力は、引き換えになる
だから鍵は「どの形で固定するか」だ。ここに一つのトレードオフがある。仕様の形が機械で検証しやすくなるほど、掴める意図は「運用できるもの」に狭まる。逆に散文は何でも書けるが、機械では確かめられない。この引き換えが、形の選び方を決める。だから固定する形は、意図の性質で決まる。
- 判定できる・運用的な意図は、実行可能な受け入れ基準やテストで固定する。曖昧さは絞り込め、走らせればずれが出る。ただしテストに最適化して本質を外す危険は残る。
- 機械が読む入力は、構造化スキーマで固定する。「言い忘れ」を構造ごと消せるが、硬い。型に収まらない意図は「備考欄」へ逃げる。
- ニュアンスや美的判断、言語化できない意図は、散文で書き、人間のレビューに任せる。ここを無理に基準へ押し込めば、テストの外で静かにずれ続ける。
つまり、曖昧さが高くつく場所を、その意図を掴める最も検証可能な形で固定する。やることはそれだけだ。狙うのは「言った通り」ではなく「意図した通り」。一発で通そうとせず、対話で寄せていく。
残るのは、美的判断や暗黙知のように、完全には言語化しきれない意図だ。要求工学はここを掴みきれない。この残りは、差し戻す側の人間の査読も自動化への過信に侵食される、と分かったうえで、いまも人間の差し戻しに頼っている。
出典8件
-
C. Sadowski ほか「Modern Code Review: A Case Study at Google」ICSE-SEIP, 2018. https://doi.org/10.1145/3183519.3183525 — 期待の中心は教育と分かりやすさで、導入時の動機(初期従業員1名の回顧)に沿う。規範の維持は現在の期待。コミットを止めるチェックと止めない解析を分ける。 ↩ ↩2 ↩3
-
Winters ほか編「Software Engineering at Google」Ch.9, O’Reilly, 2020. https://abseil.io/resources/swe-book/html/ch09.html — Sadowski 共著の章。正しさの検査は第一の便益でなく、欠陥検査を多層防御の一枚に置く。ツールで人の検査の必要は減ったが、価値を無くしきれないかもしれないとする。「健全性」はこの書物の語。 ↩ ↩2 ↩3
-
P. Naur「Programming as Theory Building」Microprocessing and Microprogramming 15, 1985. https://doi.org/10.1016/0165-6074(85)90032-8 — 理論は仕様書を含む文書では表せず、主たる活動に正しい方法は無いとする。技法の選択と順序はプログラマが決める。 ↩ ↩2 ↩3
-
B. Meyer「Applying ‘Design by Contract’」Computer 25(10), 1992. https://doi.org/10.1109/2.161279 — 事前・事後条件と不変条件を契約として書き、実行時のアサーション監視で破れを検出する。Eiffel では監視の水準をクラスごとに選び、既定は事前条件のみ。性質ベーステストはこの出典の対象外。 ↩ ↩2
-
R. Parasuraman & D. H. Manzey「Complacency and Bias in Human Use of Automation」Human Factors 52(3), 2010. https://doi.org/10.1177/0018720810376055 — コンプレイセンシーは作業が注意を取り合うと起き熟練者にも現れ、自動化バイアスは訓練や指示で防げずチームでも起きる。 ↩ ↩2
-
J. Bezos「2015 Letter to Shareholders」Amazon.com, 2016. https://s2.q4cdn.com/299287126/files/doc_financials/annual/2015-Letter-to-Shareholders.PDF — 不可逆な一方向の扉と可逆な双方向の扉を分け、後者に重い手続きを課すと遅さや発明の減衰を招くとする。抜き取り監査は本稿の手立てで、原典に標本抽出の記述は無い。 ↩ ↩2
-
obra/superpowers v5.1.0「subagent-driven-development」. https://github.com/obra/superpowers/blob/v5.1.0/skills/subagent-driven-development/SKILL.md — 二段レビューを仕様→品質の固定順で回し、順序違いを赤旗とする。v6.0.0(2026-06-16)でレビュアーは一人に統合された。hooks は SessionStart の注入だけ。 https://github.com/obra/superpowers/blob/v6.4.1/RELEASE-NOTES.md https://github.com/obra/superpowers/blob/v6.4.1/skills/subagent-driven-development/task-reviewer-prompt.md ↩ ↩2 ↩3 ↩4 ↩5
-
F. Ricca ほか「Using acceptance tests as a support for clarifying requirements」IST 51(2), 2009. https://doi.org/10.1016/j.infsof.2008.01.007 — 学生30名の2実験で、Fit 表を添えると理解が有意に上がり、時間差は有意でない。表は読むだけで実行していない。 http://www.rcost.unisannio.it/mdipenta/papers/ist09.pdf ↩
この記事はAIを使用して執筆されました。内容には誤りが含まれる可能性があります。事実や数字の出典は脚注から確かめられます。