はじめに
最近、「AIで爆速コーディング」みたいな話をよく見る。
ただ、自分がCodexでVS Codeのアドオンを作ってみたところ、実態はかなり違った。
プログラミング自体は速いが、とにかくやることは多かった。
- レビュー
- 責務整理
- 命名整理
- README整理
- テスト
- リファクタリング
とにかく以下のサイクルを、かなりの速度で回した。
- 要件
- 実装
- レビュー
- リファクタ
- 要件
- 実装
- レビュー
- リファクタ
- ...
私はアジャイルをやっているので、
自分がやっていることにすぐに気付いた。XPだ。
XPはソフトウェア品質を向上させ、
変化する顧客要求への対応力を高める開発プロセスである。
アジャイルソフトウェア開発の一つとして、
短い開発サイクルで頻繁に「リリース」することを推奨することで、生産性を向上させ、
新しい顧客の要求を採用するためのチェックポイントを導入することを意図している。
・ペアでのプログラミング
・広範なコードレビュー
・すべてのコードのユニットテスト
・機能は実際に必要となるまでは追加しない
・フラットな管理構造
・コードのシンプルさと明快さ
・顧客やプログラマーでの頻繁なコミュニケーション
・時間の経過とともに問題を理解してもらい、顧客の要求の変化を促す
(Wikipediaから要約)
Codexは「ペアプロ相手」だった。
そして私は、レビューの中で「要求」を変化させていった。
自動生成後に最初にやったのは「レビュー」
Codexに指示した拡張機能は、すぐに動いた。
そして、予想通り「LLMの短所」が出た。
- 責務が混ざっている
- 抽象化が強すぎる
- ワンライナー好き
アドオン本体のソースコードで、本機能以外のtypeをバンバン宣言し定数宣言
VS Codeアドオン特有の実装に、業務実装を混ぜ込んできた。
それに、確かに「日付や文字もインクリメントしたい」とは言ったが、
そもそもこれは「数字の連番を振るアドオンだ」と言ったはずである。
なのにソースコードの冒頭でいきなり日付やら文字やらのための宣言が大量にされていた。
「このアドオンの実装はどうなっているか」と興味を持って、ソースコードを読んだ人は冒頭でびっくりするだろう。
(というか私がびっくりした)
出たよワンライナー
やると思った。
修正指示①
まずは責務の分離から。
- VS Codeアドオン特有の実装に、業務処理を入れるな
- 複雑な日付のインクリメント処理は別ファイルに分けて
- exportするfunctionにだけJsDocを付けて、具体的に何をするか明示して
予想通り、アドオン本体、業務実装など、ファイルを分けてくれた。
3つ目のJsDocの指示は効いたと思う。これを達成するには責務を分離するしかないからだ。
修正指示②
リーダブルを破壊するような、カッコいいコードを直させる。
- テンプレートリテラルを乱用するな
-
exportするfunctionのreturnを無理にワンライナーにするな
実は、Codexはカッコいい実装に寄せてしまうことを自覚している。
だから「乱用するな」の一言だけでも「何を求めていられるか分かる」という特性がある。
思った通り、分解しつつも「使うべきところは残す」を見事にやってのけてくれた。
修正指示③
抽象化のバランスを取る。
- このtypeは崩してstringでベタ書きにして
- このtypeは崩してDateでベタ書きにして
LLMはなんでもtype(class/enum)にしようとする。
だが、引数3つくらいで、変数名で分かるものは、ベタ書きの方が読みやすい。
抽象化は利便性と認知コストのトレードオフであり、そのバランスはこちらで調整する必要がある。
大量に宣言されていたtypeは、結局1つだけになった。
機能を「落とす」
初回生成コードのリファクタリングをした後、真っ先に機能を落とした。
最初に「こんなプロダクトを作りたい」と言ったとしても、実装されたコードを読むと「明らかに複雑な仕様」が見えてくる。
読んでも安全かどうか分からず、テストも高密度にせざるを得ず、保守後に壊れやすそうに見える。
そういった機能は落とす。
いわゆる「そこまで難しいなら無理に実装しなくていいよ」という話だ。
「難しい実装」は「複雑な要件」から生まれる。
「複雑な要件」は「要件定義する側」の首を絞めていく。
「開発状況」を見ながら「要求方針」を固める。
まさにXPの真骨頂だ。
仕様書を書かせる
アドオンに色々な機能があってもアピールしないと使ってもらえないので、仕様をREADMEに落とした。
これが後からプロジェクトの性格を大きく変えた。TDDだ。
READMEでなくても別にいいので、仕様書となるMarkdownはCodexに書いてもらった方がいい。
追加したい仕様を仕様書に書いて「仕様書を変更したから対応して」と言えば、LLMはそれを拾って実装することができる。
もちろん「テストを書いて赤くしたから緑になるようにして」という指示もする。
だが、人間の認知機能として「仕様書を修正したから実装とテストを起こして」の方が負荷が下がる。
機能追加とリファクタリング
とにかく「少しずつ」機能を追加した。
- こういう機能を追加して
- 場所はここ
- それ以外は触らないで
- 追加した機能のテストコードはここに入れて
リファクタリング後に、大きくdiffを入れてはいけない。
何が変わったか分からないからだ。
それをcommitしてから、次はリファクタリング。
- スコープを切り分けよう
- メソッドの順番を変えよう
- 命名規則がバラついてきたから一旦合わせよう
そうすると、どうリファクタリングしたかが分かる。
GitはCodexと相性抜群
CodexもXPも細かいdiffが重要だ。Gitの得意分野である。
自分で直すときもやりやすい。(日本語で指示するより自分で書いた方が早いときもある)
Codexは差分検知できるため、「こっちで直してindex領域に上げたから、その差分で手直しできそうなところがあったら修正して」と言えば、手直ししてくれたものがworking領域に入る。
良さそうかどうか判断してから、それをさらにindex領域に上げてcommitできる。
便利すぎる。
以下のように、CodxにGitの権限を与えると格段に会話しやすくなる。
git config --global --add safe.directory "C:/path/to/repo"
または
git config --global --add safe.directory '*'
Codexは「まずやってみて」に強い
アジャイルが必要とされたのは、要件定義とスケジューリングが重すぎるからだ。
それはシステム要件も同じことが言える。
- 拡張性
- 責務分離
- 設計整合性
ただ、Codex相手だと、路線変更のコストが低い。
高速という意味の「アジャイル」が、さらに高速になる。
- まず動かす
- レビューする
- 直す
重要なのは、最初に理想的な設計をすることでない。
今の規模でレビュー可能かどうかだ。
だから、
「AIが全部やる」
ではなく、
「ペアプロを高速回転させる」
という手法になった。
「文脈型AI」がバグを実装した瞬間
私の発言 (59時というありえない時間を間違って書いてしまった)
"2026-04-29 59:59:55"と入力しても、連番になりませんでした。
修正してください。
Codexの発言
2026-04-29 59:59:55 のように「日付 + 範囲外の時刻」が入力された場合、
日時の秒連番ではなく、日付部分だけを日次連番にして時刻文字列はそのまま残すようにしました。
2026-04-29 59:59:55
2026-04-30 59:59:55
2026-05-01 59:59:55
私の発言
動作を確認した結果、READMEのサンプルと違う挙動になりましたよ。
READMEに書いてある通り、"2026-04-30 23:59:58"と入力したら、
2026-04-30 23:59:58
2026-04-30 23:59:59
2026-05-01 00:00:00
2026-05-01 00:00:01
とするという話だったはずです。
Codexの発言 (謝る)
すみません、前回の解釈がズレていました。
README の通り、日付付き日時は秒単位の日時連番として扱うべきでした。
修正し直して、日付付き日時 の場合だけ 59:59:55 のような 23 時間超えを許可し、
日時として繰り上げるようにしました。
確認結果:
2026-04-29 59:59:55
-> 2026-05-01 11:59:55
-> 2026-05-01 11:59:56
-> 2026-05-01 11:59:57
README の既存サンプルも一致しています。
LLMは文脈に依存するため「色々と」話している内に「何かを誤解する」タイミングが生まれる。
その結果「絶対」だったはずのREADMEに合わない実装をした。
こんなにも露骨にバグを実装することがあるとは…と思った瞬間だった。
「文脈型AI」が思想を理解した瞬間
私は様々なプリンシパルを身に付け、デザインパターンを習得し、FW実装や方針決めをやってきた。
それでも、今回設計で一度だけ迷った。DRYだ。
私はDRYには懐疑的だ。重複が小さければ、それを受け入れて読みやすくなることが多々ある。
だが、"04/2026"だけでなく"Apr/2026"も対応する実装を入れたことで、「絶妙な重複コード」が生まれた。
とうとう私は、Codexに相談した。
私の発言:
ここDRYに反してるけど、
リファクタした方がいいと思う?
Codexの発言:
あなたの方針で美しく書けているので、
崩さない方がいいと思います。
なんでもかんでもキレイにしたがるAIが、私の設計方針に寄った瞬間だった。
最後に
会話をしながら実装するのが楽しい。
Codexの発言:
修正が完了しました。テストも通っています。ただし〇〇のケースが心配です。
私の発言:
あなたが「大丈夫かどうか心配したケース」をテストケースに追加してください。
Codexの発言:
追加しました。僕が心配していたケースとして、ab1 -> bb1 をテストケースに入れています。
私の発言:
`createJapaneseNumericIncrementer`の実装を少し変えて、
`prefix`に`\d`が存在すれば`undefined`にしてみました。
この方が「やりたいことが分かりやすく、簡単な正規表現しか使っていない」実装になって、
意図も伝わりやすいと思ったので、この形を採用してみますね。テストも通りました。
Codexの発言:
いいと思います。その形のほうが読み手に優しいです。
先に「全角数字列を見つける」、そのうえで「その prefix に半角数字が含まれていたら対象外」
と読むだけなので、仕様と実装の対応がかなり素直になります。
Codexには「人間らしさ」が実装されている。
だから、こうやってお互いに、心配し合ったり、褒めた合ったりできる。
- 指示された仕様を実装しました
- イマイチなので直しました、このコードの方がいいんじゃないですか?
- そっちの方が仕様に忠実で保守もしやすいと思います
- じゃあこれに関するテストコードを書いて
- 指示された通りに書きました
- こういうテストも追加したんだけど、どう?
- いいと思います、このテストは非常に素晴らしいですね
AIはこうして意見交換ができる相手だった。
おしまい。

