Articles
未来のコンテキスト
コードを書かせる側に立つ
AIにコードを書かせる開発は、かなり普通のものになりつつある。
奇しくも、国会答弁の原案を行政用生成AI基盤「源内」で作成したというニュースがあった。
政治とソフトウェア開発ではドメインが違うが、書く主体と責任を持つ主体が分かれるという点ではかなり近い。
コードを書かせ、テストを回し、動いたら次に進み、必要ならもう一度投げる。以前なら人を採用し、オンボーディングし、レビューしながら進めていた作業の一部が、今はトークンと待ち時間に置き換わっている。
これは便利だし実際に速く、局所的な実装であれば人間が手で書くより良いことも多い。
ただ開発者側の見方も変わっている。AIが出したコードを毎回きちんと読むとは限らず、差分を眺め、テストが通り、画面が動けばいったん受け入れて次に進む。
この感覚には既視感があり、大多数の受託開発において発注元はコードを読んでいない筈である。
読む能力がないとは言わないが、発注の目的はコードではなく、要件を満たしているかどうか、納期に間に合うかどうかであるはずだ。
今AIにコードを書かせる開発者も、同様なのではないか。外注先が人間からAIに変わっただけで、評価軸はアウトプットに寄っていく。
しかし人間の外注とAIの外注では決定的に違うところがあり、AIは「未来のコンテキスト」を持たない。
いったん「未来のコンテキスト」を今のコードが数ヶ月後に置かれる状況のことだと仮定義しておく。
今はまだコードの外側にあるが、後から必ずコードへ戻ってくる条件の集まりだ。
この先の状況を現在のコードに重ねて見る感覚を、ここでは「未来のコンテキスト」と呼ぶ。
違和感は「未来のコンテキスト」である
シニアエンジニアがコードを見たときに覚える違和感は、この「未来のコンテキスト」を先に感じ取った反応に近い。
もちろん命名や責務分割や依存関係の違和感として表面化することはあるが、本質は今のコードだけを見た評価ではない。
その設計を3ヶ月後に拡張するとどうなるか。仕様変更が入ったときにどこが壊れるか。障害が起きたときにどこから切り分けることになるか。納期が近い状態で手戻りが出たときに、チームや事業へどのくらいの影響が返ってくるか。
そういう未来の状態を、過去の失敗や運用上の痛みと照らし合わせている。
その入口として命名を見ることが多く、変数名、関数名、ファイル名、責務の名前を見ると、書いた人が何を見て何を同じものとして扱い、何を分けるべきものとして扱っていないかが出る。
命名そのものが悪いというより、その名前を付ける時点で見えている構造が違い、こちらが見ている意図とコードを書いた側が置いている意図が一致していない。
「この命名をするということは、たぶんここを勘違いしている」という感覚がある。
例えば状態として扱うべきものにイベントの名前が付いていたり、本来は複数の責務に分かれるものがひとつの Manager に集められていたりする。名前は小さいが、その時点で世界の切り方が見える。
その違和感を表現するときに「なんか臭う」という言い方をすることがある。
「匂い」は、違和感に身体性を与える表現だと思う。まだ言語化できていないが、近づくとまずいものがある。そういう反応を、頭ではなく身体の側から言っている。
シニアの違和感とは、「未来のコンテキスト」が現在のコードに落としている影のようなものだと思う。
まだ事故は起きておらず、負債にもなっておらず、誰も困っていない。けれどこのまま進むとどこかでまずくなる。その気配を先に察知している。
だから違和感は静的解析の結果でもベストプラクティスの暗記でもない。先の条件を、現在の実装に重ねて見ている状態に近い。
AIが持っていないもの
AIは失敗パターンを知っており、巨大なコードベース、設計論、レビューコメント、障害対応の文章を学習しているので「この構成は密結合になりやすい」「この抽象化は過剰かもしれない」といった説明はできる。
しかしそれを当事者の痛みとしては保持しない。
障害対応の重さも、納期前に設計ミスが発覚する重さも、過去の判断が半年後に返ってくる感覚もAI自身のものにはならない。
ここでいう身体性は物理的な体の有無だけではなく、責任が返ってくるという感覚のことだ。
AIには失敗しても次のプロンプトが来るが、修正コストはユーザー側に残る。信頼を失うのも、納期を詰めるのも、事業上の説明をするのも人間側である。
そのためAIは局所的には正しそうな判断をしやすい。確率的に良さそうな実装、一般に推奨される設計、テストが通る差分を出すことはできる。
一方で「この1件だけは起きたら困る」という不可逆な痛みは、制約として与えなければ軽く扱われやすい。
速さはコストを消さない
AIの強さは反復の速さにある。
書かせ、直させ、別案を出させ、テストを書かせるサイクルはかなり速い。失敗してもAI自身は痛みを持たず、手戻りを怖がらないため、反復横跳びの速度だけを見れば人間よりずっと強い。
この速さは大きな価値があり、探索できる案の数が増えるし、小さな実装の詰まりはかなり減る。
ただし反復は無料ではない。現実にはトークンとGPU、つまりコストによって有限である。
コンテキストが足りない状態で高速に回すと、間違った方向にも高速に進む。しかもAIの場合は出力がそれなりに整っているため、間違いが見えにくい。
その間違いのコストは、最終的には人間に返ってくる。AIが痛みを持たない代わりに、人間が遅れや追加費用を引き受ける。
速度が上がるほど、方向修正のタイミングはシビアになる。
シニアの仕事は何に変わるのか
シニアの価値はもともと細かいコードレビューだけではなく、本当に見ていたのはその人がどの方向へ進もうとしているかである。
この分割だと後で詰まり、この責務の置き方だと運用で困り、この依存関係を作ると次の変更で逃げ道がなくなる。
人間同士の開発では、こうした方向修正はコードレビューだけで起きていたわけではない。アーキテクチャ設計、仕様検討、設計レビュー、ミーティングのような合意形成の場を通じて、少しずつ修正されていた。
プロジェクトの流れが人間基準だったので、多少のズレはその過程で止まりやすかった。
AI開発では、その前提が崩れる。AIは疲れず、恐れず、大量に試せる。合意形成を経ないまま、ひとりで差分を積み上げられる。
その代わり、プロジェクトの未来を自分の問題としては持たない。
だからシニアの仕事はAIが書いたコードの細部を全部読むことではなくなっていく。もちろん重要な差分は読むが、より重要なのはAIが今どの方向へ進もうとしているかを早めに掴むことだ。
この抽象化はまだ早い。この境界は逆に置いた方がいい。このデータ形式を今固定すると後で逃げられず、この検証をしないまま進むと見た目だけ動くものになる。
その判断は巨大な設計図を読んで初めて分かるとは限らず、むしろ小さな命名に出ることが多い。意図がずれているなら早い段階で止めないと後で大きな設計差分になる。
そういう判断を、AIの出力が積み上がりすぎる前に差し込む必要がある。
ここでAIに対する指示は単なる命令ではなく、合意形成の代わりになる。
実装方針を先に固定するのか。失敗してほしくない条件を列挙するのか。既存コードの正本を読ませるのか。テストを先に書かせるのか。あるいは、あえて複数案を出させて比較するのか。
指示のメタスキルは以前から重要だった。ただAIの場合、ズレが一気に差分へ変わる。だから言語化されたレビューを待つ前に、違和感や匂いの段階で止め、未来のコンテキストを指示へ変換する必要がある。
「未来のコンテキスト」を誰が持つのか
AIはコードを書く速度ではすでに十分強く、局所的な品質でも人間より良い場面は増えている。
コードの整形、定型実装、テストの補助、既存パターンへの追従ではかなり実用的になった。
しかしプロジェクト全体の品質は局所的なコード品質だけでは決まらない。
納期や運用のような条件は、コードの外側にあるようで最終的にはコードに戻ってくる。
AIはその一部を説明できるが、自分が責任を持って抱えるわけではない。
ここに人間が持つべき役割が残り、これからの開発では人間が全部のコードを書く必要は減っていく一方で、「未来のコンテキスト」を誰が持つのかはより重要になる。
AIに任せる範囲が広がるほど、シニアは実装者というより方向を保つ人になる。
今の差分を見るだけではなく、先に挙げた未来の条件まで含めてどの選択が後で痛くなるかを見る。
その痛みの予感を、まだ言語化しきれない段階で拾う。
最初に、発注者はコードを読まないと書いた。
AIにコードを書かせるとき、自分は発注者の側に立っている。差分を眺め、テストが通り、画面が動けば次に進む。
書く主体がAIでも、遅れや追加費用を払うのは人間である。
便利な外注先を手に入れたつもりでいたら、いつの間にか自分が未来を読まない発注者になっている。
「未来のコンテキスト」は、コードの数ヶ月後だけにあるのではない。
AIを使う自分たちの数ヶ月後にもある。