目的と定義
本ドキュメントは、従来のプログラミング手法の限界を超えた、AI中心のプログラミング手法として、ラジカルAIプログラミングの概念を定義する。
2002年ごろにブームを起こしたeXtreme Programming (XP) は「昔からあるベストプラクティスを極端(eXtreme)なレベルで適用する」という思想で作られた。コードレビューが有効なら常にペアで開発を行う。テストが有効なら全てのコードでテスト書いてから実装する。ユーザーとの対話が必要ならいつでも会話できる場所にユーザーを座らせるといった具合である。それと同じようなチャレンジをAIを使った開発でもやってみようというのをモチベーションとして自分がAIを使った開発を半年ほど行って得た経験をもとに作成した。RadicalはeXtremeとは違う単語だが似たようなクレイジーさを表現できる単語として選んでいる。4つの価値と12のプラクティスなど、XPのオマージュとして作ったものではあるものの、eXtremeをそのまま拝借するのは陳腐なので避けた。
生成AIを活用するにあたり、オーガニックに行ってきた開発プロセスをAIに模倣させるというのはスタートとしてはやりやすいやり方だが、ツールなどが発展するにしたがってそこから離れていくと予想される。そこで既存のやり方を完全にアンラーニングしてリセットし、全く新規で開発プロセスを考えるとしたらどうかというのを思考実験しつつ、さまざまなエージェントで検証しつつ書いているのが本エントリーである。最終的には現在のオーガニックな開発とこのエントリーの中間点のどこかに落ち着くと思われるが、考えられうる極北を考えるのがこのエントリーの趣旨である。
ある程度モデルの性能は今後も伸びていき、ツールの機能が向上する前提で書いている。現時点で「こういう指示をしたらうまくいった」といったテクニック的な内容はモデルの変化で変わる可能性が高い。なるべくそういうのは排除している。また、マルチエージェントといった、具体的すぎるツールの形態には依存しないような、ジェネリックな内容となるようにしている。想定以上の発展があった場合にはここに書いてある内容も変化を受けるかもしれないが、その時が来たときに更新することを考えている。多くのエージェントがTODOリストを表示しつつ作業するなど、以前は指示が必要だったことも何も指示せずに行うように進化している。どのように手を動かせば良いかというHOWに対する指示は今後はどんどん不要になっていく想定で書いている。
これは個人として考えたパターンランゲージ集であるが、もちろんこれとは違う思想にたどり着いた人もいると思う。そういうのは是非フィードバックして欲しい。
4つの価値
1. 継続的学習
AIと人間がお互いの理解を更新し続ける「共進化」そのものを開発の中心価値とする。
AIモデルにとっては、人間から提供されたテキストやログなどを元に人間が期待するものを学習しアウトプットを出す活動がAIによる開発のAI側から見た視点である。いかに効率よく学習するかが鍵となる。人間側はAIがどのように理解しているのかを学び、それに対して軌道修正をさせることが主な活動になる。言い換えると、AIを使った開発はAIをいかに学習させるかというゲームである。
どんなに完璧な要件が頭にあったとしても、それを間違いや誤解を生まないテキストにしてAIに渡すというのは大変時間がかかるプロセスである。もちろん、完璧な要件があるというケースはまれである。その場合は多くのステークホルダーと調整などが発生する。巨大なシステムはそれだけでも年単位でかかる。アジャイル方法論やDDDに登場する、1人で要件を判断できるドメインエキスパートなどは存在せず、何人も手分けをしてヒアリングして話を統合し、一つの要件としてまとめる必要がある。
完璧な計画を作りそれを元に一発で自動で望むものができる、というのはそもそも完璧な計画を作るリードタイムが無駄となりボトルネックになる。その完璧な情報を用意する前に、断片的でもどんどんAIに情報を与えて学習をスタートし、その知見をsteeringドキュメントなどの形でプロジェクトの知見、あるいはspecとして活用可能な形に変換していくことが大切である。人間が情報を言語化する裏でAIがコードを書き、と人間とAIが並列かつインクリメンタルに作業を進めていくことが効率アップには不可欠である。
また、AIが大量の文章やプログラムを生成するのが得意といってもそれを人間が読んで理解して判断するのには時間がかかる。高速に生成されたプログラムを判断して判断を下すというのも時間がかかる。どんなに大量に並列度を上げても、その作られたプロダクトの検収を上げるところが最後のボトルネックになる。人間側の学習の効率も考慮が必要である。間違っても、AIが作成する文章やソースコードをユーザーに渡すのは間違いであるし、AIから出てくる部分のアウトプットをもって生産性を測るのは間違いである。
2. ビジョン駆動
AIを使って開発を行うと、従来よりもHowの比率が劇的に下がり、What、そしてWhyをいかに明文化して伝えるかが大切になる。プロジェクトのビジョンをより明確に持つほどに各エージェントをスムーズに利用できる。
ビジョンは今までも大切といわれてきたが、あくまでも企業理念のような少し浮ついた概念で、実際の普段の業務のKPIとの差などはあった。リーダー陣は別として、多くの作業者はHowを中心に考えてきたからである。しかし、生成AIにより文章やコードの生成は劇的に低コストで行えるようになったことで、重要度の比重が変わった。
以前は実装というのは時間がかかるし、手戻りがあるとさらに余計な工数がかかる作業とされた。そのため、フロントローディングでしっかり設計を作り込むことであと工程の手戻りや複数人の作業の結果の統合で時間を無駄にしないようにしてきた。アジャイル開発もバグによる手戻りなどを防ぐためにテスト駆動で開発するなどしてコードを書き、ボトムアップでパーツを組み上げてシステムを作っていた。
AIの開発になると、「何を実現したいか」「今後の発展の方向性はこうだ」というのを明確にすることで、HowはAIがカバーしてくれるようになる。その一方で、どの言語やフレームワークを使い、どのようなアーキテクチャにしていくかといったHowの比率は大きく下がる。フレームワーク切り替えの負担を減らすために、手間暇をかけてクリーンアーキテクチャを採用して切り替え時のコストを下げるといったことは考える必要性が減る。フレームワークを切り替える、データベースを別の製品にする、別の言語で再実装と言ったことが可能になる。これは今まで不可能であったプロトタイプを完全に捨てて、実装順を整理した上で再実装する、といったことも可能になる。
3. 品質と境界の再定義
AIと人間では成果物のスピードが異なるため、作業フローだけではなく品質などの基本的な考え方が大きく変化する。
1つ1つ、モジュールの完成度を上げて組み上げていくというのがウォーターフォールでもアジャイルでも行われてきたことである。だが、そもそもモジュールをどう分割して作るのかというのを人間が判断して指示をするとなると人間のスループットが落ちてしまう。なるべく細かい判断を人間が行わないことが効率の最大化には必要である。
そうなるとモジュール境界などは明確に白黒ついたものはなく、追加される要件によって多少の変動がありえる。それは品質が安定していない、低品質ということになるが、それを許容することでAIに任せられるレベルが1段アップする。モジュールの境界や責務がはっきりしていないということは品質があまり高くないということであるが、その分AIの物量でカバーできる。周りのモジュールも同時並行で設計・実装を行い、ある程度方向性が定まったところで完成度を上げる、というのが必要である。
実際に蓋を開けてみると、条件分岐がベタ書きの冗長なロジックの可能性がある。そういうのも動作しているのであれば許容し、時間的な余裕を動作可能なプログラムによって稼げ、より品質を高めるのが重要であると判断した段階でそれを改めて手実装するなり、リファクタリングを行うなどする。AIをフル活用し、ボトルネックが実装以外のところに移動したところで稼いだ時間で品質を確保するのである。
4. 流動的な構造
仕様・モジュール境界・フレームワークなど、構造を「固めない」こと自体をパフォーマンスの源泉となる。
AIにおける開発では仕様だけではなく、モジュールの境界、選択したフレームワークなどすべてが流動的である。うまく行かなければ、アドホックに部分的に仕様駆動開発を開始して、それまでの設計を再構成してプロトタイプを丸ごと作り変えることもある。
これまでのオーガニックな開発は人間が手を加えて行なってきた。人間が手を加えるまでシステムが変わることはないし、人間の手は早くないため、効率よく少ない工数システムを作るためにみんな知恵を絞ってきた。再利用性という言葉は長らくソフトウェア業界でマーケティング用語としてよく使われてきた。共通部分をモジュール化して使い回したり、既成の小さい硬い部品を組み合わせてシステムを作ろうとしてきた。その試みはうまく行ったり行かなかったりした。変更が少ないのが価値である。
AIは補間(Interpolation)は得意であり、外挿(Extrapolation)は比較的苦手といわれる。AIにおいては「事前に仕様や要件を固める」「ボトムアップで作り上げる」のは外挿にあたるため、精度があがらず、結果的にコストとなる。前後の枠を決めてその中で自由に要件に合わせてフレキシブルな開発の方が得意となる。中途半端に固く作ろうとすると、モジュール境界を人間が監修して設計を行う必要があり、人間の事前設計のリードタイムが長くかかり、AIのパフォーマンスは発揮できなくなる。
12のプラクティス
1. モデルオーケストレーション
AIエージェントには様々なモデルがある。計画が得意な高性能モデル、コーディングに特化した高速なモデルなどである。将来的にはテストに特化したモデル、クラッカーの思考を模倣して侵入的テストを行うモデルなどさまざまなカスタムのモデルが出る可能性もあるだろう。それぞれの得意領域を組み合わせることで低コスト(コンテキストやクレジットの面で)かつ高速にタスクが推進できる。
人間も1つのモデル/エージェントと考えるべきである。実装速度は遅いし、働き続けられないし、欠点ばかりである。ただ、対外ヒューマンインターフェースとしては他のAIには真似できない(生成AIは指示して初めて動く受動的な存在である)だろうし、AIが不得意な外挿的な発想でどのような方向性でシステムを作っていくかのグランドデザインは人間が行う。また、実装速度は遅いがどうしてもテキストでは表現しにくい微妙な高難易度のアルゴリズムの実装などのタスクを行なったりもある。
AI同士を組み合わせることでボトルネックを減らすということは今後も行われるが、人間もその一部であり、人間もボトルネックにならないようにしつつ、対外的な活動によってボトルネックを取り除くと言った活動を行う必要がある。
時にはAIではうまく実装できない案件を人間が肩代わりする、人間が怒っていた確認作業をAIが行うといったように、モデルの選択も流動的に変化する。
2. マクロマネジメント
人間とAIは1つの組織となる。組織のアウトプットを増やすにはマイクロマネジメントではなく、移譲がポイントである。マイクロマネジメントをすると、1+1が1.2とかにしかならず、なおかつ、マネージャロールの人が見られる人数をあまり増やせなくなる。マクロマネジメントでは、1人のマネージャが見られる担当者の数を増やし、並列度を上げ、全体のスループットを向上させる。
マクロマネジメントを行うには、なるべく指示を減らす必要がある。生成AIが持っている素のコーディングのスタイルをなるべく生かし、細かいところはすべて移譲する。コーディング標準やテスト駆動開発を行うかどうかなども、モデルに任せる。幸い、AnthropicのSonnet-4.5やHaiku-4.5、OpenAIのGPT-5-Codexなどはコーディングに特化したモデルとして、従来のモデルよりもコーディングの知識があり、細かい作法も指示する必要はない。また、TODOを作って開発させるなども、最近のモデルでは指示しなくても行ったりもする。
タスクレベルの細かい作業指示などは状況に応じてどのistructionを読み込ませるかなどのマイクロマネジメントを必要とする場合がある。また、その分、コンテキストを消費することになる。また、モデルごとの特徴を考慮して。モデルの使い分けなどを行う。外挿にあたるような、未知の領域の最初の実装などはどうしてもAIによる予測の正確性が上がらない場合があり、その場合も人間によるマイクロマネジメントが必要となる。
何をやるかの共通理解は必要であるため、外部設計レベルのドキュメントは必須とする。ユニットテストは生成AIエージェント自身が必要だと判断して作るのにまかせる。テストというものはそこの断面で品質のチェックを行うものであるが、そもそもテストを自動で作らせるのであれば、その仕様について人間の意志は入らないため、形としてユニットテストを行わせることは意味がない。静的型の定義なども全て任せる。また、人間にとって解読困難であることを許容する。あくまでも後述の受入テストで品質は確保する。
この信頼と移譲に必要なのは最低限2つのドキュメント群である
- instruction
- ADR(architecture decision record)とも呼ばれる。またKiroはSteeringと呼んでいる
- どのようなシステムか、どのような言語を使うか、どのような環境を想定するかなどの大雑把な指示
- spec
- 機能ごとの外部仕様書。お互いのspecは独立している。多くのAIエージェントは追加で必要な知識をリンクの形で表現できるが、漏れなくリンクを張り巡らせるよりかは共通知識をinstructionとして切り出す方が低コストだと思われる
ソフトウェアとしては以下のチェックツールを利用する
- 受入テスト
- Linterなどの静的解析ツール
利用する技術も、AIが良く知識を持っている言語やデータベースなどを選ぶようにする。こだわりがない限りは独自ツールなどを新規に作りこむ必要性は減っていくと思われる。多くの人が独自にAI向けにツールやinstructionを作りこむという状況はタコつぼ化をもたらすが、より効率の良いツールが登場すればそれが一般化するはずである。
ただし、高難易度のタスクで、生成AIに丸投げしてもうまくいかないというケースがある。その場合はマイクロマネジメントに切り替え、細かく内部仕様レベルのdesign documentを作成し、伴走しながら実装するものとする。
3. 受入テスト駆動開発
開発サイクルのチェックポイントは、静的なテストと、受入テストのみとする。受入テストはなるべく自動化をする。あるいは生成AIにシナリオに従って実施してもらう。受入テストはAIが得意な補完としてタスクを定義することにもなる。
受入テストは事前に作らせる必要はない。まずいったん一通り入力から出力までつながるようなコードが完成してから、その入力に対してアウトプットが何になるか、というペアをもとにテストを行う。ユニットテストとは異なり、人間が知覚できるレベルでの入力と出力のペアでテストを行う。例えば、ウェブ画面でのテストはバックエンドAPIでいったんテストを行うというのが主流であるが、画面と裏のDBのみを見て、途中のAPIなどは不要であれば見る必要はない。
受入テストはオーガニックプログラミングにおけるユニットテストに相当する品質ゲートになるため、バリエーションの網羅などはきちんとここで行う。またエラーケースの検証も行う。どのバリエーションに対応するか、最初に網羅して作り切ることが大切。
テストそのものは人間がすべて手で作る必要はなく、やり取りしながらAIに作成してもらう方法でもよい。テスト項目だけ決めて実際に作らせ、実際の出力を見て問題なさそうと判断してからそれを期待値としてコピーして保存するのもよい。ユニットテストの場合はテストケースは手で作成できるレベルのものが多いはずであるが、受入テストの場合は実行結果がファイルだったり大きくなることがある。そのような場合にはテストケースに従った出力をさせ、問題ないか目視確認したうえで、それをお手本とする。
一方で、ユニットテストはAI中心開発ではほとんど不要である。モジュールの単位では補完的なAIの特性を生かしたコーディングを進める方法を提供するが、そもそもどのようなモジュールがあればシステムが組みあがるのか?というボトムアップのモジュール分割設計は外挿的な思考を必要とする。モジュールの境界や役割がどんどん変化する中にあって、ユニットテストのカバレッジを計測してテストが通るように守らせるのは無駄にクレジットを消費してAIのフットワークを落とすことになる。AI自身が自発的に作る場合にわざわざ止める必要はないが、マクロマネジメントを行うためにもユニットテストにはこだわらないことが大切となる。
4. 光速イテレーション
アジャイルでは1週間から2週間単位でイテレーションを回し顧客のフィードバックを得てタスクを調整するが、AI開発ではそれを5分、10分の単位で行ってクオリティを上げていく。
そのためには生成AIには上から下までそろっていて、まずは動くシステムを作らせる。マイクロサービスなどプロセス単位で別れるもの、また分割個所が明確に分かれており、その単位で受入テストが可能なところで分割するが、それ以下のモジュールやパッケージ分割は生成AIに任せる。
オーガニックなコーディングほどの細かく分割してユニット単位でユニットテストを書きながら実装して積み上げていく必要があったが、生成AIではそのような手順での実装は不要である。おそらく最初の実装は仕様駆動開発である程度の方向性を持った実行可能なプログラムを作る必要がある。「とりあえずログイン画面」のような小さすぎるゴールを与えると必要なイテレーション回数が増えてしまうため、MVP相当の指示は必要となる。そのため、イテレーションゼロはやや大きくなる。
細かい単位で仕様駆動開発をすると、それぞれのモジュールの結合部分で時間がかかるため、細かすぎる分割指示をしてはならない。コアロジックの複雑さによっては複数に分割してコアロジックを固めてから実装したほうが良いこともあるが、最初から細かく分けて考えるのではなく一度プロトタイピングとして実装をして、ブラッシュアップではなかなかゴールにたどりつけないもぐらたたきになってきたと思ったタイミングでコア部分の再実装を仕様駆動開発で行ってモジュールを置き換えていく。
型情報を付けていくというのも過去の話である。生成AIが生成したコードを何度も動かして検証する。オーガニックではボトムアップで品質を積み上げるしか方法がなかったが、なども動かすことによって品質を確保する。
5. フィードバック・ファースト
イテレーションを高速に行う目的はお互いの理解している情報をぶつけ合い、学習スピードを向上させるのが目的である。出来上がったソフトウェアはAIが理解した結果である。それに対して実際に動かしてみせて何がおかしいかを伝えることは、ユースケースの具体例をAIに伝える行為である。
いかに早くフィードバックを返せる体制を作るか最適化するのが人間の役割である。
素早いフィードバックが大切だからといって、小さくモジュール分割を指示してそのレベルで開発を高速に回しても適切なフィードバックは得られない。その分割が正しいか、そのモジュールを組み合わせると期待するシステムになるかどうか、すべては仮説でしかないからである。人間も動くシステムを触れることにより、仮説が正しかったかどうかを人間も学習できる。
もちろん、全てを人の手で行うことはできないため、受け入れテストによるリグレッションの防止は大切となる。
6. プロトタイピング
生成AIのメリットは手が早いことである。生成されたコードは場合によって捨てて作り直すということが常に選択肢として入ってくる。イテレーションの途中で実装が詰まることがあり得る。その場合はその知見をもとに、不要な機能をそぎ落として新しく実装を開始する。生成AIでは実装が高速なため、プロトタイプを捨てることは躊躇する必要はない。
生成AIが生成するコードは冗長なことが多く、オーガニックな実装と比べて3倍程度のコード量になる。まずはプロトタイプを固めたうえで、ベンチマークを取り、そこの実装を手動実装(AIを使う場合も、エージェントではなく、コード補完)に切り替えて効率を稼ぐ方法が良い。
テンプレートは最終的な実装と同じアーキテクチャである必要はない。Pythonやシェルスクリプトである程度固めてから、GoやRustに清書させる方法もある。
生成AIの機能がどれだけ向上しても、「一発で欲しいシステム」ができあがることはない。世の中に既にあるソフトウェアの模倣(たとえばテトリスやぷよぷよ)であればできる可能性が高いが、そのようなソフトウェアを作る価値は基本的にない。ソフトウェア開発者は常に「現在存在しない」システムを作る必要があるからである。「一発で欲しいシステム」を生成AIに作らせるには、欲しいシステムの隅から隅まで事細かに定義されたドキュメントが必要であるが、過去の実績から、そのようなドキュメントは可能ではあっても、かなりの時間を要する。またドキュメントの整合性を隅々まで確保するのも人間が行うのはラジカルではない。そうなると、骨組みになるような機能から少しずつ指示をして作らせることになる。プロトタイプを作って指示をして方向修正を行って、というのが開発のメインのサイクルとなる。
なお、それなりの情報を与えて動くアプリケーションを作らせても、細かいユースケースには対応できないコードになっていることが多い。一通り動くようになってから、細かいブラッシュアップを行い、受け入れテストを網羅的に用意して行い、リリースできるようになるには、最初の動く状態から数倍の時間がかかる可能性がある。
7. テンプレート開発
生成AIは類似した機能を量産することが得意であるため、1つの機能をしっかり作りこみ、それをもとに水平展開できるような計画を行う。
アーキテクチャとしてはお手本のアーキテクチャがあればそれをもとに実装していく補完系のタスクとなるため、実装効率があがる。細かい実装方法などを逐次指示する必要もなくなる。ただし、定期的にそこから外れていないかは確認が必要となる。難易度が高いコア部分、量産できる部分をうまく分け、マイクロマネジメントか、マクロマネジメント、どちらが適しているかを決定し、実装する。なるべくマクロマネジメントできるような構成を検討する。
また、テンプレートから量産する場合は、1つの機能を増やすたびにどれぐらいの時間で行えるか、どれぐらいのプレミアムクレジットの消費で済むかなどの見積もりもしやすいメリットがある。
8. 知識の非永続化
生成AIを利用すると、ドキュメントの生成も高速に行えてしまうため、ドキュメントを作りすぎてしまうなど、中間生成物が大量になりがちである。不要なドキュメントを作らないように心掛けたり、一時的に作ったドキュメントは削除するなりする。
そもそも生成AIが高速に出力したドキュメントを「読む」前提にしてしまうと、人間の読解スピードがボトルネックになる。生成AIに読ませるにしてもクレジットを消費することになる。
中間生成物が多すぎると、方針転換を行うときに仕様を追従するために多くの作業が必要になったり、古い情報が残ったりするし、成果物を検索するときにノイズが増えて開発効率を落とす原因となる。また、Sonnet-4.5などのモデルが作成するドキュメントはソースコードが大量に入っており、半分はソースコードのようなドキュメントである。
実装中にマイクロマネジメントが必要になった場合などは細かいロジックを説明したドキュメントを生成させて確認などを行ったりするが、そのようなドキュメントは外部仕様にかかわる記述だけを残して削除する。
ドキュメント同士は矛盾などを検知しあう機能はないため、ソースコードという形が一番望ましい。もし今後セマンティックを表現し相互の矛盾検証などができるようなドキュメントフレームワークが登場した場合はこの前提は大きく変わる可能性はあるが、定理証明系は自然言語のような速度では読み書きできず、人間がボトルネックというところを解消しつつ問題を解決する解にはならないだろう。セマンティックウェブのような記述も同様である。
9. ブラックボックスなインスペクション
最終的にシステムが完成したあとは、ブラックボックスとして他のAIエージェントに解析させながら、実装をベースにドキュメントを作らせる。それにより、生成AIが誤解して理解していたこと、試行錯誤の過程で作られて残った機能などが洗い出せる。AIの学習をアンラーニングし、実際の作り上げたシステムを再学習するということである。
ベースとなった仕様書を読ませることなく、コードだけを見てインスペクション(検収)させることで、実際のコードがどうなっているかを明らかにする。また、内部の細かい挙動や過去の経緯でなくなった機能などが書き込まれたような密度の低いドキュメントが作られるのを防ぎ、人間が読んで価値のあるドキュメントが作れる。
生成AIはコーディングのリスクを下げるために、なるべく既存のコードを変更せずに後方互換性を残そうとするため、不要な関数パラメータ、不要な実行時フラグなどが高確率で残る可能性がある。不要な機能が検知されたら、その影響範囲の調査と削除を生成AIに行わせる。また、Linterの未使用の変数や関数などを検知する機能なども駆使して無駄なコードを取り除いていく。
知識はドキュメントとして保持しておくのではなく、その都度解析して出力させることで、当時あった願望(実装されていない)などを排除して今現在の情報が得る、という方法もあり、その手段でカバーできるか検討する。
10. ログによる対話
生成AIと一緒に作業を行うにあたっては、printデバッグが一番効率が良い。何か動作がいまいちな場合はログを追加することを指示し、そのログを渡してデバッグを行わせる。もともとデバッガ―があっても並列処理などはこの方法でやっていたし、ログの解読と問題個所の特定は生成AIが得意な領域である。並列動作があっても、素早くログの発行元を特定し、問題の解析につながる。そのため、ログを気軽に追加し、終わったら削除させる。または生成AIにどのようなフィルタでログを選別すればよいかを確認し、そのログを取得して出力する。ログこそはAIとシステムの「動きに」について共有するインターフェースである。
そのため、質の高い必要な情報を高密度でログを出力することが必要である。間違ってもJavaのスタックトレースのような情報を、本当の例外以外で出力してはならない。
11. データモデルファースト
生成AIにとっては、JSONなどから画面を生成するほうが得意である。また、アプリケーションの持つデータ構造の変更は簡単でも、運用中のデータの変更は簡単ではない。ソースコードは必要に応じて生成できるものだし、後方互換性さえ維持すれば入れ替えられるが、データ構造はそれよりも変更に弱い。そのため、データ設計は最初にしっかり行い、変更を少なくする必要がある。
また、プログラムの変更がしやすいといっても、マイクロサービスを作り替えや境界変更などは大事となってしまうだろう。生成AIは機能を減らすという指示に対しては後方互換性の維持をしようとしてなかなか思う通りの方向性で作業を進めてくれないことが多い。人間の意思を過去からの積み上げで理解するという現在の仕組みを考えれば、モデルがとてつもなく進化したとしてもこの傾向は大きく変わらないと思われる。
データモデルをきちんと作っておくことで、同一トランザクション内で同時に変更しなければならないデータ群が明確になり、プロセスの境界を置くべき箇所がはっきりする。そのため、マイクロサービスとして切り出すと、分散トランザクションといった、DBがやってくれることをユーザーランドで手作りするという無駄実装が大きく減らせる。またAPIでいくつか追加のデータが必要になったとしても、正しくプログラムで必要なデータが定義されていればDBクエリーの項目とAPIに項目を足すだけで済むはずである。サービス間で情報取得のためのAPI連携など大事にはならない。別テーブルだとしてもシステム上近い位置にあり、JOINやCTEで1クエリーで取得できるはずだ。
サーガパターンは設計レベルの失敗を実装で回避しようとする愚者のパターンである。月次締め後の訂正など、本当に修正が日単位で遅れて同一トランザクションで処理できずに必要なケースというのはありえるが、ウェブで議論されている構成では必要ないと思われるものがほとんである。
APIファーストという言葉もあるが、設計としてはモデルをきちんと考慮してサービス分割を事前に行った上で、コーディングの順序として先にAPIを作るのは問題ないが、設計としてAPIファーストというのはAIとは関係なくありえないだろう。
ドメイン知識はデータモデルの形でなるべく表現しておく。どの順番でデータを蓄積していくのか、ファイル単位のデータをどのように分割していくのか、どのように統合していくのかなど、データの変遷をきちんと設計する必要がある。
12. 品質、デリバリー、スコープ、コンテキスト、クレジット
アジャイルでは品質、デリバリー、スコープは相関関係にあり、それぞれのバランスを取ることを推奨していたが、実際には品質を犠牲にすることはありえないため、スコープとデリバリーの調整を行うという教義となっていた。
生成AIを大規模活用するにあたっては、品質も変数となる。最高のコードではなく、AIに任せて作った冗長なコードというのを許容する。これはプロトタイピングによってシステムの検証を早めるための「時間の前借り」である。
コンテキストはAIが活動するにあたって逃れられないものである。巨大なドキュメントを渡すことでパフォーマンスは落ちる。小さく処理しやすいブロックに分割して指示をする必要がある。また、作業中に中断、リセットなどしやすいように、永続化は必要ないが現在のタスクに必要なドキュメントだけを残すようにする。コンテキストが足りなくなってくると、指示した内容が守れなくなり、正しいコードが書けなくなって、ファイルを全削除しては微妙なファイルを作り直すという酔っ払ったような動きになる。現代の技術では限界はあるものの、適切な狭いタスクにフォーカスさせることで長く思考し続けられるようになる。ただし、デバッグをしつづけたりするとやはり途中でコンテキストが欠乏してきたりする。
生成AIの活動には大量の電力が必要である。今のところは月額で決まった量のクレジットが使えるサービスが主流であり、その中で活動を行う。将来的にクレジットが無限に使えるようになるかどうかは現時点では不明である。メモリ効率の良いローカルLLMと、CPUに内蔵のNPUで十分という時代が来る可能性はあるし、コーディングなど特定のタスクに限定してローカルで行うといったことはそのうちにできるようになるだろう。小さくコアを作り、そのテンプレートを増やしていくなど、どの段階でクレジットが切れても問題なく進められるようにすることが大切である。また、計画は高性能なモデルを、実装はクレジット消費が少なく高速なモデルを、といった具合に効率よく組み合わせることも必要となる。また、設計の良しあしも、「機能追加に必要なクレジット数が多いか低いか」で見積もれるようになる。
今までの見積もりはどうしても「ある程度の平均的な開発者が実装したとして」「ほぼ同一の構成のタスクに分解して」数値を出さざるを得なかった。またそのためにはある程度タスクを分解して平準化するといった事前の分析が必要であった。タスクを分解するというのはAIを使った開発でも並列で行うために必要であるが、やり方の平準化まではしなくてもおそらく精度が高い見積もりができるようになる。アジャイルでもベロシティといった、別組織では役に立ちにくい近似値、なおかつフィボナッチ数のような1桁の離散的数値などを使っていたが、クレジット数という(モデルごとに違いは出るが)、2-3桁の数値で計測できるようになるため、この分野でも相当な進歩があると思われる。
タスクごとの消費クレジット数は、指示の出し方やアーキテクチャによっても変化しうるため、いままでは定性的だった「よいアーキテクチャ」「よい設計」「よい指示」といった内容に対する議論が定量的に変化していくことが期待される。
まとめ
XPのようなパターンランゲージ集として、AI中心開発の方法論をまとめてみた。20万行ほどコードを作成してみて得た感覚や、他のAIエージェントを使った開発を行っている人との議論をもとに書いている。新しいモデル、パラメータ数が多いモデルが出たとしても変わらないだろうなというところを予想して書いている。
勢いで書いてみて2週間ほど寝かせて、おおよそ言いたいことは盛り込めたと思うので2025年の感覚のスナップショットとして公開しようと思う。なお、本記事の執筆にはAIは直接的には利用していない(推敲はちょっとしてもらった)。AIの作成する文書はまだ目が滑るような中身が薄い長文となりがちで、読者の時間を頂戴して読んでもらうのに失礼だという考えからである。