🧞‍♂️

Agentic Codingの設計指針

に公開

生成AIと開発するとは何なのか

2〜3ヶ月ほど生成AIを使って開発して溜まった知見を言語化してみる。

生成AIが解くべき問題について考える

本題に入る前に、生成AIが解くべき課題、つまり「開発とは何か」を改めて考える必要がある。以下は考えやすくするための仮の分析であり、必要に応じて置き換えてよい前提モデル。

生成AIは魔法の杖ではない

よく言われているが、生成AIは魔法の杖ではない。「知識はあるが知恵がない」という表現がしっくり来る。膨大な知識(道具)を持っているが、適切な使い方(知恵)は自力では判断しにくい。極端な比喩で言えば、害虫駆除にロケットランチャーを向けたり、石像を作るのに歯科用ドリルを使おうとする感じだ。要は成果を出すには使う側に知恵が必要だということ。

開発に対して仮定を置く

生成AIと共に開発するには、「開発のどこで生成AIの知識を借りると成果が出るか」を人間が判断する必要がある。言い換えると開発工程を整理しなければならない。

ここからは説明のため、単純化した仮の分析を行う。

まず、開発を大胆に単純化して以下のフローと仮定する。

要件定義 → 全体設計 → 詳細設計・実装 → レビュー → テスト

次に、各フェーズへの期待値を仮に置く。

  • 要件定義:今までにないものを作ることが望ましい
  • 全体設計:既存パターンでも要件を満たせれば良い
  • 詳細設計・実装:既存パターンで要件を満たせれば良い
  • テスト:既存パターンで要件を満たせれば良い

生成AIの特徴を考える

生成AIは「一般的に見たことのあるもの」を高速に再構成するのが得意で、まったく新規の構造・概念を自律的に創造するのはまだ難しい。したがって開発において生成AIは「よくあるもの」を出力する特性を持つと言える。

どこで生成AIが力を発揮できるか

この特性と仮定した工程期待値を組み合わせると、現時点では 詳細設計・実装 の領域で最も力を発揮しやすい。

  • 要件定義:新規性要求が高い
  • 全体設計:膨大なコンテキストが必要になりがち
  • テスト:説明責任や信頼性の観点で完全委譲しづらい

現実世界での分析

ここまで仮の分析を行ってきたが、実際はチームなど組織単位で「自分たちにとっての開発とは何か」「生成AIとは何か」という議論と共に分析してほしい。導入前の課題分析が生成AIとの開発では肝となる。


生成AIとコーディングをする(Agent Coding)

最近は「agent coding」と呼ばれることが増えており、以下の3つの要素で成り立っていると考える。

  1. ワークフロー
  2. コンテキスト
  3. AIとの対話

ワークフロー

ここでいうワークフローとは「AIがコーディングを進める手順」のこと。例として TDD(テスト駆動開発)を挙げると:

  1. テストリストを作る
  2. テストリストから1つ選びテストを実装(失敗を確認)
  3. テストが通るよう実装
  4. リファクタ
  5. テストリストが空になるまで 2〜4 をループ

この「小さく分解して前進する」特徴は、AIにとって扱いやすいサイズのサブタスクに落とし込むことと相性が良い。TDDでなくても、「タスクをAIが扱える粒度に分解して順に検証する」 型は多くのケースでうまくいく。また近年は Cline や Claude Code といったエージェントツールが手順の一部を自動化してくれるため、どのエージェントを選ぶか自体も重要となる。ワークフローに“銀の弾丸”はなく、規模・複雑さ・モデルのコンテキスト制約に応じて調整が必要。

コンテキスト

ここでのコンテキストとは、全ての会話で共通利用される基礎情報(clinerule や CLAUDE.md 的なもの)を指す。多くの場合 ディレクトリ構成と各ディレクトリの責務、言語や利用ossの環境情報 を明確にするだけで十分なことが多い。

ディレクトリ構成と各ディレクトリの責務について少し補足する。Java を例に挙げると、一般的に「ディレクトリ構成」というと com.example.domain.entity や com.example.application.controller のようなレイヤー(横方向)の区分を指すことが多い。ここにレイヤー=横方向だけでなくドメイン境界(DDD でいう Bounded Context / Subdomain)=縦方向の定義も併置しておきたい。

具体的には「ドメイン一覧」を列挙する形でも良いし、より粗く「ページ/機能単位でドメインが分かれている」という形でも構わないが、何らかのドメイン境界の宣言を与えておくと、生成AI が安易な横断的“共通化”を拡散させず、適切に分離を維持しながら必要な共通化だけを検討する傾向がある(体感ベース)。これをしない場合、DRY 原則を過剰適用しやすく、その結果として抽象化コスト・結合度が跳ね上がる。

下記にECの注文apiで利用するコンテキストの例を示す

## ディレクトリ構成と責務
| パス                                 | コンテキスト | レイヤー          | 主要な責務                                  |
|--------------------------------------|--------------|-------------------|---------------------------------------------|
| `cart/presentation`                  | Cart         | Presentation      | API ルーティング/DTO バリデーション/認可 |
| `cart/application`                   | Cart         | Application       | ユースケース調整/TX 境界/外部呼び出し調停 |
| `cart/domain`                        | Cart         | Domain            | カート集約・VO/不変条件/ドメインイベント |
| `order/presentation`                 | Order        | Presentation      | 注文 API 入口/DTO バリデーション/認可    |
| `order/application`                  | Order        | Application       | 受注フロー統括/決済・在庫連携             |
| `order/domain`                       | Order        | Domain            | 受注集約/ステータス遷移/ドメインイベント |
| `shared/kernel`                      | Shared       | ―                 | 汎用値型 (`Money` 等)/共通エラー型        |
| `shared/infrastructure`              | Shared       | ―                 | ORM 設定/メッセージング/ログ・監視共通   |

## コンテキストの境界の決め方
- ユーザーの操作をコンテキストの境界とすること
  - 例:カート操作、注文操作、履歴操作等
- sharedを利用する際はユーザーに共通化していいか確認すること

コンテキストの話に戻ると、よくあるアンチパターンとして、Lint全文・長い理念・微細な運用メモなどを一括で投入する例がある。しかし生成AIは提示した全てを厳密には守らず、情報過多になるほど重要な情報が相対的に薄れてしまう。コンテキストは 「大枠を形成する最低限」 に留め、細部は後述の対話で補う。

一方、モデルやエージェント性能によっては“大枠”だけでは粗いコードを生成することもある。その場合は「any を使わない」「グローバル変数禁止」など最低限の追加規約だけを補足する。過度な羅列は避ける。

AIとの対話

ワークフローとコンテキストを適切に設計できると“60点”程度の初期出力が得られるようになる。そこから“80〜100点”へ引き上げるのは 対話 のプロセスである。

アンチパターン:

  • 一度に大量の仕様を詰め込んで単発プロンプトで全実装を要求する

    • 生成AIは100%遵守しない
    • 人間側も初回で完全仕様を整理し切れていない

望ましい形:

  • 生成物を確認し軌道が逸れたら即座に方向修正する
  • 得られた知見(不足インターフェース・性能懸念・境界ケース等)を次のプロンプトへフィードバックする
  • 反復で精度を上げる

この「何を・どの順でフィードバックするか」にはエンジニアとしての経験差が出るため、AI主導のコーディング時代でも研鑽は不可欠である。


まとめ

言いたいことは以下の2点に集約される。

  • 生成AIで解くべき課題(どこに使うか)を明確にする
  • ワークフローと最小限コンテキストで大枠を作り、対話で細部を詰める

この2点を意識してよりよい開発をしていきましょう。

Discussion