はじめに
ここ1年ほど、Copilot や Cursor のようなツールを使って開発する時間が急速に増えました。
最近いくつかのプロジェクトでは、コードの約95%(ビジネスロジック、ボイラープレート、テストを含む)が AI によって生成される状況も珍しくなくなっています。
この「AI がコードを生成し、人間がレビューする」という高速なイテレーションを続ける中で、ある違和感を覚えるようになりました。
それは、従来の Web フレームワーク設計と、この新しい開発スタイルの間に摩擦があるのではないかという点です。
現在主流の Web フレームワーク(MVC など)の設計思想は、基本的に「人間がコードを書く」ことを前提としています。
しかし、もしコードの主な生産者が
「人間」から「AI と人間の協働」へ変わるとしたらどうでしょうか。
従来のアーキテクチャ原則はそのまま有効なのでしょうか。
それとも、AI を前提としたアーキテクチャ設計が必要になるのでしょうか。
従来の開発と AI 開発の違い
従来の Web 設計の前提
これまでのソフトウェア設計には、暗黙の前提がありました。
コードは貴重な資源である
そのため、次のような設計が重視されてきました。
- 再利用性を最大化する
- 抽象化を徹底する
- 重複コードを避ける
また、コードの主な読者は開発者です。
そのため
- 可読性
- デザインパターン
- 人間の認知習慣
といった要素が重要視されてきました。
さらに、コード変更は比較的コストが高い作業でした。
そのため将来の変更を想定し、複雑な抽象化を導入することも一般的でした。
AI 時代に起きている変化
AI を開発に組み込むと、この前提が大きく変わります。
コード生成コストがほぼゼロになる
AI は大量のコードを瞬時に生成できます。
そのため、再利用による「人手削減」の価値は相対的に小さくなります。
コンテキストウィンドウが制約になる
LLM は無限のコードを理解できるわけではありません。
理解できる範囲は コンテキスト長に制限されます。
依存関係が複雑なコードベースでは、
- 重要な文脈が欠落する
- 誤った仮定でコードを生成する
といった問題が起きやすくなります。
イテレーション速度が大幅に上がる
AI によって
- コード生成
- 修正
- リファクタリング
の速度が大幅に向上します。
その結果、「保守性」の意味も変わります。
従来
人間が読みやすいコード
AI時代
AIが理解しやすいコード
考察1:モジュール設計を見直す
従来のモジュール分割
これまでのソフトウェア開発では、モジュール分割は主に
- ドメイン(DDD)
- チーム構造
に基づいて行われてきました。
これはコード整理には有効ですが、次のような問題も生みます。
- 深い依存チェーン
- 共有状態
- 暗黙の依存関係
多くのモジュールは単独では理解できず、
システム全体の文脈を前提に設計されています。
熟練した開発者であれば、経験を通じてこの複雑さを把握できます。
しかし AI にとっては事情が異なります。
AI にとっての問題
AI がコード生成の中心になると、次の問題が顕在化します。
依存関係の複雑さ
大規模システムでは依存グラフが非常に複雑になります。
依存チェーンが深くなると、
AI は必要な文脈をすべて把握できなくなります。
その結果、生成コードの品質が大きく下がる可能性があります。
暗黙の状態
共有状態や暗黙の依存は AI にとっての盲点です。
AI はそれらを正確に推論できないため、
- 誤った前提でコードを書く
- バグを生みやすい
といった問題が起きます。
モジュール単体で理解できない
AI は人間のような自由に文脈を切り替えることができません。
そのため
モジュール単体で理解できる設計
が重要になります。
改善の方向性
インターフェース契約を明示する
依存関係は
- グローバル状態
- 暗黙的 DI
ではなく、
明確なインターフェース契約
として定義するべきです。
深い継承を避ける
複雑な継承構造よりも
コンポジション中心の設計
のほうが AI にとって理解しやすくなります。
明示的な依存関係
依存関係は
- 明確なパラメータ
- 明確なインターフェース
として表現するほうが望ましいでしょう。
考察2:テストを「生成ゲート」にする
従来の開発では、テストは後工程として扱われることが多くありました。
開発者は経験に頼り、
テストカバレッジが十分でないことも珍しくありませんでした。
しかし AI 開発では、この方法では品質を維持できません。
テストはコンテキストのアンカー
テストは単なる品質保証ではありません。
AI にとってテストは
要件を理解するための最も正確なコンテキスト
になります。
テストを生成ゲートにする
AI 時代では、
テストをパスしないコードは有効なコードではない
という考え方が重要になります。
CI/CD においても、
テスト成功をマージの必須条件
にするべきでしょう。
テストのないコードは未定義動作
テストされていないコードは、
初期化されていない変数のようなものです。
その挙動は予測できません。
AI 開発では
テストのないコードは dev 環境から出さない
というルールが必要になります。
考察3:抽象化戦略の見直し
なぜ抽象化してきたのか
DRY 原則のもと、私たちは
- 共通ロジックの集中管理
- 重複コードの削減
を重視してきました。
これは人間主導の開発では合理的でした。
AI 時代の課題
しかし AI 開発では別の問題が生まれます。
過度な抽象化
複雑な抽象化は
- 継承チェーン
- 共通インターフェース
を増やします。
これはコードの重複を減らしますが、
理解コストは大きく増えます。
AI にとっては、
理解しにくいコード = 誤生成しやすいコード
になります。
抽象化変更の連鎖
共通抽象を変更すると、
システム全体に影響が広がります。
AI が全体影響を正確に把握するのは簡単ではありません。
コスト構造の変化
従来
- コードを書くコスト → 高い
AI 時代
- コード生成コスト → ほぼゼロ
つまり
抽象化のメリットは小さくなり、理解コストだけが残る
可能性があります。
改善の方向
プリミティブベース設計
複雑な抽象クラスよりも、
小さな機能プリミティブ
を提供するほうが柔軟です。
AI はそれらを組み合わせて実装できます。
適度な冗長性を許容する
AI 時代では、多少の重複コードは問題ではありません。
むしろ
- 明確
- 独立
- 理解しやすい
コードの方が重要になります。
シーン特化実装
共通コンポーネントを増やすより、
ユースケースに特化した実装
を生成する方が安全な場合もあります。
まとめ
これまで開発者は次の役割を担ってきました。
- コードを書く
- コードを理解する
- コードを保守する
しかし AI が開発に参加することで、この役割は変わりつつあります。
AI が「コードを書く」役割を担うなら、
開発者は次の役割に集中することになります。
- 制約を設計する
- 判断を行う
- リスクを管理する
つまり開発者は
コードを書く人から、システムを設計する人へ
より強くシフトしていくのかもしれません。
AI と協働する Web アーキテクチャは、
人間のためだけでなく
- AI が理解しやすい
- AI が修正しやすい
- テストで正しさを保証できる
設計である必要があります。
より明示的な契約、
より厳密なテスト、
よりフラットな構造。
これらが、AI 時代のアーキテクチャ設計の重要な要素になるのではないでしょうか。