AIエージェントを前提とした、次世代の開発手法と設計思想
📚 この記事の位置づけ
本記事は、コンテキストエンジニアリングシリーズの第4弾です。
前提知識として、以下の記事を先にお読みいただくことをおすすめします:
- コーディングエージェント時代のコンテキストエンジニアリング実践ガイド - 個人利用の基礎
- コンテキストウィンドウの処理フローと動作メカニズム 完全解説 - 技術的詳細
- チーム開発のためのコンテキスト共有戦略 - チーム活用
本記事では、コンテキストを中心に据えた新しい開発手法を体系化します。
目次
- コンテキスト駆動開発(CDD)とは
- 従来の開発手法との違い
- CDDの基本原則
- コンテキストファーストの設計思想
- AI可読性を重視したコード設計
- コンテキストのテスト駆動開発
- ドキュメント駆動開発の再定義
- CDDのワークフロー
- 実践的な導入ステップ
- ケーススタディ
- メトリクスと評価
コンテキスト駆動開発(CDD)とは
「コードを書く前に、コンテキストを書く」——これがAI時代の開発の新常識です。
Context-Driven Development (CDD) は、従来の開発手法をAI時代に適合させた新しいアプローチです。コンテキストを「実行可能なドキュメント」として扱い、AIエージェントと人間の両方が読める形で知識を蓄積・活用することで、開発効率と品質を両立させます。
AIエージェントが高度なコード生成能力を持つようになった今、開発者の役割は「コードを書く人」から「コンテキストを設計する人」へとシフトしています。CDDは、この変化に対応した体系的な開発手法です。
定義
CDDの定義を明確にすることで、この開発手法の本質を理解しましょう。単なる「AIを使った開発」との違いを、ここで押さえておくことが重要です。
Context-Driven Development (CDD) は、AIエージェントが最高のパフォーマンスを発揮できるように、コンテキストを中心として扱う開発手法です。
従来の開発では「コードこそが真実」でしたが、CDDでは「コンテキストこそが真実」であり、コードはコンテキストから生成される成果物の一つに過ぎません。この発想の転換が、開発速度と品質の両方を飛躍的に向上させる鍵となります。
核心となる考え方
CDDの最も本質的な概念を、シンプルな対比で理解しましょう。この思考の転換こそが、AI時代の開発の出発点です。
従来: コードが真実の源泉
↓
CDD: コンテキストが真実の源泉
コードはコンテキストから生成される成果物の一つ
なぜ今CDDなのか
2024年は、開発手法が根本的に変わる転換点です。 Claude Code、Cursor、GitHub Copilotといった強力なAIエージェントが登場し、コード生成能力は人間レベルに到達しつつあります。この変化に適応した開発手法が、今まさに必要とされています。
1. AIエージェントの普及
AIエージェントは、もはや「あると便利なツール」ではなく、「なくてはならないパートナー」になりました。 しかし、その能力を最大限に引き出すには、適切なコンテキストを提供することが不可欠です。
// 2023年以前
開発者 → 直接コーディング → コード
// 2024年以降
開発者 → コンテキスト作成 → AIエージェント → コード
2. コードの寿命の変化
コードは「消耗品」になり、コンテキストが「資産」になる——これがAI時代の現実です。
AIがあれば、コンテキストさえあれば、コードは何度でも再生成できます。技術スタックが変わっても、要件が変わっても、コンテキストを更新してAIに再生成させればいいのです。したがって、時間をかけて磨くべきは「コード」ではなく「コンテキスト」なのです。
従来: コードは長期間保守される資産
→ 慎重に設計・実装
AI時代: コードは比較的短期で書き換えられる
→ コンテキストこそが長期資産
3. 開発速度の飛躍的向上
良質なコンテキストは、開発速度を10倍にします。 これは誇張ではなく、実際に多くのチームで観測されている数字です。そして、開発が加速すれば、コンテキストを改善する時間的余裕が生まれ、さらに開発が加速する——この正のフィードバックループが、CDDの最大の魅力です。
好循環: コンテキスト改善 → 開発加速 → さらなる改善
一度この好循環に入れば、チームの生産性は指数関数的に向上します。
従来の開発手法との違い
「CDDは既存の開発手法を置き換えるのか、それとも補完するのか?」——この質問に答えます。
CDDは、TDD (Test-Driven Development) やDDD (Domain-Driven Design) といった既存の開発手法とどう異なるのでしょうか。結論から言えば、CDDは既存手法と対立せず、むしろ強化します。本セクションでは、各手法との比較を通じて、CDDの独自性と、既存手法との効果的な組み合わせ方を明確にします。
TDD (Test-Driven Development) との比較
TDDとCDDは競合するのではなく、補完し合う関係にあります。それぞれの強みを理解することで、両者を効果的に組み合わせられます。
TDDは「テストから始める」、CDDは「コンテキストから始める」——どちらも「実装から始めない」という点で共通しています。
TDDとCDDは、実は非常に相性が良い開発手法です。TDDが「何をテストすべきか」を明確にするのに対し、CDDは「AIがどう実装すべきか」を明確にします。両者を組み合わせることで、テストとコンテキストの両方から実装を駆動できます。
観点 | TDD | CDD |
---|---|---|
駆動要素 | テスト | コンテキスト |
主な成果物 | テストコード + プロダクトコード | コンテキスト + 生成コード |
品質保証 | テストの網羅性 | コンテキストの明確性 |
リファクタリング | テストがあれば安全 | コンテキストがあれば再生成可能 |
AIとの親和性 | 中程度 | 非常に高い |
TDDのサイクル
TDDの伝統的な「Red-Green-Refactor」サイクルを見てみましょう。このリズミカルな反復が、品質の高いコードを生み出します。
CDDのサイクル
一方、CDDは「Define-Generate-Validate-Refine」のサイクルで進みます。コンテキストの継続的改善が、このサイクルの核心です。
DDD (Domain-Driven Design) との比較
DDDとCDDは、思想的に非常に近い関係にあります。DDDの概念をCDDで表現することで、ドメイン駆動とAI駆動の両方の利点を享受できます。
DDDの「ユビキタス言語」は、CDDの「コンテキスト」と完璧に調和します。
DDDで定義したドメインモデルやユビキタス言語を、AIが理解できる形式でコンテキスト化することで、ドメインの複雑性を適切に管理しながら、AIの力を最大限に活用できます。実際、DDDとCDDを組み合わせたチームが、最も高い生産性を達成しています。
観点 | DDD | CDD |
---|---|---|
中心概念 | ドメインモデル | コンテキスト |
主要なアーティファクト | ユビキタス言語、境界づけられたコンテキスト | AIが理解できるコンテキスト |
設計の焦点 | ドメインの複雑性の管理 | AIの理解可能性の最大化 |
実装との距離 | モデル駆動 | コンテキスト駆動 |
併用可能性 | 非常に高い | DDDの概念をコンテキスト化 |
重要: CDDはDDDと対立しない。むしろ、DDDで定義したドメインモデルをAIが理解できる形式で表現します。
従来のドキュメント駆動開発との違い
最も重要な違いがここにあります。CDDのコンテキストは、従来のドキュメントが抱えていた「更新されない」という根本的な問題を、構造的に解決します。
従来のドキュメントは「読まれない運命」にありました。CDDのコンテキストは「使われ続ける運命」にあります。
この違いは決定的です。従来のドキュメントは、実装が完了すると誰も更新しなくなり、徐々に現実と乖離していきました。しかしCDDのコンテキストは、AIがコードを生成するために常に参照されるため、古くなることが許されません。この「使われ続ける」という性質が、ドキュメントの鮮度を保つ本質的な動機になります。
従来のドキュメント駆動:
文書作成 → (人間が読む) → 実装
↓
文書が古くなる(更新されない)
CDD:
コンテキスト作成 → (AIが読む) → 自動生成
↓
常に最新(生成に必要だから)
CDDの基本原則
CDDは5つの基本原則に支えられています。 これらの原則を理解し、実践することが、CDD成功の鍵です。
これらの原則は、CDDの哲学を具体的な行動指針に落とし込んだものです。すべての原則を一度に実践する必要はありません。まずは1つか2つから始めて、徐々に取り入れていきましょう。
原則1: コンテキストは実行可能なドキュメント
この原則が、CDDと従来のドキュメント駆動開発を決定的に分けるポイントです。「実行可能」という言葉の意味を、しっかり理解しましょう。
「読むだけのドキュメント」から「実行できるドキュメント」へ——これがCDDの第一の革新です。
従来のドキュメントは「何をすべきか」を記述するだけで、具体的な実装方法が不明確でした。そのため、読み手によって解釈が異なり、一貫性のないコードが生まれていました。CDDでは、コンテキストに実際に動作するコード例を含めることで、AIも人間も正確に理解できるようにします。これにより、「曖昧さ」という最大の敵を排除できます。
❌ 従来のドキュメントの問題点
まずは、従来のアプローチの何が問題だったのかを確認しましょう。この問題を理解することが、CDDの価値を理解する第一歩です。
認証機能を実装する際は、JWTトークンを使用してください。
このような記述では、実装者によって解釈が異なり、一貫性のないコードが生まれてしまいます。
✅ CDDのコンテキストの例
対照的に、CDDのアプローチがどれほど具体的で実行可能かを見てください。この違いが、品質の差を生み出します。
## 認証実装パターン
**必須**: 以下のパターンに必ず従うこと
```typescript
// 1. JWTトークンの生成
import { JwtService } from '@nestjs/jwt';
export class AuthService {
constructor(private jwtService: JwtService) {}
async generateTokens(userId: string): Promise<TokenPair> {
const accessToken = await this.jwtService.signAsync(
{ sub: userId, type: 'access' },
{ expiresIn: '15m' }
);
const refreshToken = await this.jwtService.signAsync(
{ sub: userId, type: 'refresh' },
{ expiresIn: '7d' }
);
return { accessToken, refreshToken };
}
}
検証:
- アクセストークン有効期限: 15分
- リフレッシュトークン有効期限: 7日
- トークンペイロードに
type
フィールド必須
禁止パターン:
// ❌ 有効期限が長すぎる
{ expiresIn: '24h' }
// ❌ typeフィールドがない
{ sub: userId }
このアプローチのポイント:
なぜこのアプローチが効果的なのか、3つの観点から理解しましょう。
- 実行可能性: 実際に動作するコード例を含めることで、実装時の曖昧さを排除
- 検証可能性: 検証基準を明示することで、実装の正しさを確認可能
- 禁止パターンの明示: やってはいけないことを示すことで、よくある失敗を防止
コンテキストに具体的なコード例を含めることで、AIエージェントは一貫性のある高品質なコードを生成でき、人間も実装意図を正確に理解できます。
原則2: コンテキストは進化する生きたドキュメント
完璧を目指して最初の一歩を踏み出せないよりも、不完全でも始めて改善し続けることが重要です。この原則が、CDDを実践可能にします。
コンテキストは「書いて終わり」ではなく、プロジェクトとともに成長する生命体です。
最初から完璧なコンテキストを書くことは不可能です。そして、それは必要ありません。重要なのは、継続的にフィードバックを受け取り、改善していくことです。AIの生成結果が期待と違えば、それはコンテキストを改善するチャンスです。このフィードバックループを高速に回すことで、コンテキストの品質は急速に向上します。
コンテキストは「書いて終わり」ではなく、継続的に改善される生きたドキュメントです。
実際の開発では、最初に書いたコンテキストが完璧であることはまれです。AIによる生成結果を確認し、期待と異なる場合はコンテキストを改善します。このフィードバックループを繰り返すことで、コンテキストの品質が向上し、それに伴ってAIの生成品質も向上します。
継続的改善のサイクル:
このサイクルを理解し、実践することで、コンテキストは日々進化していきます。
- 初期コンテキストを作成
- AIがコードを生成
- 生成結果をレビュー
- 問題があればコンテキストを改善(曖昧な部分を明確化、例を追加など)
- 改善されたコンテキストで再生成
このサイクルを回すことで、プロジェクト全体のコンテキスト品質が向上し、開発速度も加速します。
原則3: AIと人間の両方が理解できる
二者択一ではなく、両立を目指す——これがCDDの賢明なアプローチです。幸い、AIが理解しやすいコンテキストは、多くの場合、人間にとっても理解しやすいのです。
「AIのため」でも「人間のため」でもなく、「両方のため」のコンテキストを書く——これがCDDのバランス感覚です。
過度に機械的な記述は人間には読みにくく、逆に曖昧な自然言語はAIには理解しづらい。CDDでは、構造化された形式と自然な説明を組み合わせることで、両者が正確に理解できるコンテキストを作成します。コンテキストは、AIエージェントが機械的に解析しやすく、同時に人間が読んで理解しやすい形式である必要があります。
❌ 悪い例1: AIだけが理解できる(人間には難解)
{
"patterns": [
{"id": "p1", "type": "auth", "impl": "jwt", "exp": 900}
]
}
このような過度に抽象化・記号化された記述は、AIは解析できても人間が理解するのに時間がかかります。
❌ 悪い例2: 人間だけが理解できる(AIには曖昧)
認証は適切に実装してください。セキュリティに注意。
曖昧な表現は、人間なら文脈で理解できても、AIは具体的な実装方法を判断できません。
✅ 良い例: 両方が理解できる
## 認証実装ルール
**形式**: JWT(JSON Web Token)
**トークン種別と有効期限**:
- **アクセストークン**: 15分(900秒)
- **リフレッシュトークン**: 7日(604800秒)
**実装時の必須チェック**:
1. トークンにユーザーIDを含める
2. トークンタイプを識別子に含める
3. 有効期限を正確に設定
**セキュリティ要件**:
- トークンはHTTPS経由のみで送信
- リフレッシュトークンはHttpOnly Cookieに保存
- アクセストークンはメモリ上に保持(LocalStorage禁止)
**コード例**:
```typescript
// 実装パターンを参照
@src/modules/auth/auth.service.ts
バランスの取り方:
以下の4つのポイントを意識することで、両者にとって理想的なコンテキストを作成できます。
- 構造化: マークダウンの見出しやリストを活用して構造を明確にする
- 具体性: 抽象的な表現ではなく、具体的な数値や条件を記述する
- コード例: 重要な部分には必ず実装可能なコード例を含める
- 自然言語: 機械的な表現だけでなく、人間が読みやすい説明も含める
このように、具体的かつ構造化された記述により、AIと人間の両方が正確に理解できるコンテキストを作成できます。
原則4: コンテキストから全てを生成可能
この原則は理想論に聞こえるかもしれませんが、技術的には十分実現可能です。そして、この理想に近づくほど、プロジェクトは保守しやすくなります。
コンテキストは「Single Source of Truth」——すべての成果物の源泉です。
CDDの理想は、コンテキストさえあれば、プロジェクト全体を再構築できることです。プロダクトコード、テストコード、APIドキュメント、マイグレーションスクリプト、インフラ設定——これらすべてがコンテキストから生成可能であるべきです。これは単なる理想ではなく、実現可能な目標です。
コンテキスト
↓
├── プロダクトコード
├── テストコード
├── APIドキュメント
├── マイグレーションスクリプト
└── インフラ設定
コンテキストを「真実の源泉(Single Source of Truth)」として位置づけることで、以下のような利点が得られます:
- 一貫性: 全ての成果物が同じコンテキストから生成されるため、矛盾が生じない
- 再現性: プロジェクトを最初から作り直す場合でも、同じコンテキストから同じ品質のコードを生成できる
- 保守性: コンテキストを更新するだけで、関連する全ての成果物を更新できる
- 拡張性: 新しい要件が追加されても、コンテキストを更新してAIに生成させれば対応できる
実際には、全てを自動生成するのではなく、重要な部分や定型的な部分から段階的にコンテキスト化していくアプローチが現実的です。
原則5: コンテキストの品質 = プロダクトの品質
最後の原則は、CDDの投資対効果を示す重要な洞察です。どこに時間を使うべきかが、この原則で明確になります。
コンテキストに投資することが、最も効率的な品質改善の方法です。
従来の開発では「コードレビュー」が品質の砦でしたが、CDDでは「コンテキストレビュー」がより重要になります。なぜなら、コンテキストの品質が、AIが生成するコードの品質を決定するからです。高品質なコンテキストからは高品質なコードが生まれ、低品質なコンテキストからは低品質なコードしか生まれません。この因果関係を理解することが、CDDの本質を掴む鍵です。
コンテキストの品質が、そのままプロダクトの品質に直結します。これはCDDの最も重要な原則です。
従来の開発では、「コードの品質 = プロダクトの品質」と考えられてきました。しかしAI時代においては、コンテキストの品質が、AIが生成するコードの品質を決定します。
品質の連鎖:
この因果関係を図式化すると、コンテキスト投資の重要性が一目瞭然です。
高品質なコンテキスト
→ AIの正確な理解
→ 高品質なコード生成
→ 高品質なプロダクト
したがって、CDDでは「コンテキストの品質向上」に時間を投資することが、最も効率的な品質改善の方法となります。コードレビューと同様に、コンテキストレビューを重視する文化が重要です。
コンテキストファーストの設計思想
「コードを書く前に、まずコンテキストを書く」——これがコンテキストファーストの本質です。
従来の開発では、設計と実装とドキュメントが別々のフェーズとして扱われ、しばしばドキュメントが後回しにされました。コンテキストファーストでは、コンテキストの作成が開発の最初のステップになります。これにより、実装とドキュメントの乖離という古典的な問題が、構造的に解決されます。
設計の順序が変わる
「何を最初に書くか」——この選択が、開発全体の流れを決定します。順序を変えるだけで、これほど大きな違いが生まれるのです。
開発の順序を変えることで、開発の質が変わります。
従来のアプローチ
従来の開発フローの問題点を可視化してみましょう。多くのプロジェクトで見られるパターンです。
問題: ドキュメントが更新されない、実装と乖離する
CDDアプローチ
対照的に、CDDではコンテキストが常に最新に保たれる仕組みが組み込まれています。
利点: コンテキストが常に最新、実装と一致
コンテキストファーストな機能開発フロー
新しい機能を開発する際、最初に書くのはコードではなくコンテキストです。
CDDでは、コーディングを始める前に、まずコンテキストを作成します。以下の5つのステップで、機能開発のコンテキストを段階的に構築していきます。各ステップは、AIが正確にコードを生成するために必要な情報を、段階的に積み上げていくプロセスです。
この5ステップのプロセスを習得することで、どんな機能でも体系的にコンテキスト化できるようになります。最初は時間がかかるかもしれませんが、慣れれば自然に実践できるようになるでしょう。
ステップ1: ゴールのコンテキスト化
すべての旅は、目的地を知ることから始まります。開発も同じです。
「何を作るのか」が明確でなければ、AIは何も作れません。
最初に、「何を実現したいのか」を明確にします。成功基準を具体的にリストアップすることで、実装のゴールが明確になります。チェックリスト形式で記述することで、「完成」の定義が客観的になり、実装の抜け漏れを防げます。
# 機能: ユーザープロフィール編集
## ゴール
ユーザーが自分のプロフィール情報(名前、メールアドレス、アバター)を更新できるようにする
## 成功基準
- [ ] ユーザーは名前を変更できる
- [ ] ユーザーはメールアドレスを変更できる(確認メール送信)
- [ ] ユーザーはアバター画像をアップロードできる
- [ ] 変更はリアルタイムに反映される
- [ ] バリデーションエラーは即座に表示される
## 非機能要件
- 画像アップロードは5MB以下
- レスポンスタイム: 200ms以内
- メール送信は非同期処理
成功基準をチェックリスト形式で記述することで、実装が完了したかどうかを客観的に判断できます。
ステップ2: 制約のコンテキスト化
制約は「自由を奪うもの」ではなく、「判断を明確にするもの」です。
次に、実装時に守るべき制約を明確にします。ビジネスルール、技術的制約、セキュリティ制約を分類して記述することで、実装時の判断基準が明確になります。制約が明確であればあるほど、AIは適切な実装を選択でき、セキュリティやパフォーマンスの問題を未然に防ぐことができます。
## 制約事項
### ビジネスルール
- メールアドレス変更時は再確認が必要
- 確認リンクの有効期限: 24時間
- 同じメールアドレスは登録不可
### 技術的制約
- 画像形式: JPEG, PNG, WebPのみ
- 画像サイズ: 最大5MB
- アップロード先: AWS S3
- ファイル命名: `avatars/{userId}/{timestamp}.{ext}`
### セキュリティ制約
- 自分のプロフィールのみ編集可能
- JWTトークンによる認証必須
- CSRFトークン検証
制約を明確にすることで、AIは実装時に適切な判断を下すことができ、セキュリティやパフォーマンスの問題を防ぐことができます。
ステップ3: 実装パターンのコンテキスト化
「既存のパターンに従う」——この一貫性が、保守性の高いコードベースを作ります。
プロジェクトのアーキテクチャや既存のコードパターンをコンテキストに含めることで、AIは一貫性のあるコードを生成できます。新しい機能が既存のコードと統一感のあるスタイルで実装されることで、コードベース全体の可読性と保守性が向上します。
## 実装パターン
### アーキテクチャ
このプロジェクトはClean Architectureを採用
**レイヤー構成**:
Controller (HTTP層)
↓
UseCase (ビジネスロジック層)
↓
Repository (データアクセス層)
### エンドポイント設計
```typescript
// PUT /api/v1/users/:userId/profile
interface UpdateProfileRequest {
name?: string;
email?: string;
avatar?: File;
}
interface UpdateProfileResponse {
user: {
id: string;
name: string;
email: string;
emailVerified: boolean;
avatarUrl: string;
updatedAt: string;
};
emailVerificationRequired: boolean;
}
エラーハンドリング
エラー | HTTPステータス | エラーコード | メッセージ |
---|---|---|---|
ユーザーが存在しない | 404 | USER_NOT_FOUND | User not found |
権限なし | 403 | FORBIDDEN | Cannot update other user's profile |
メール重複 | 409 | EMAIL_ALREADY_EXISTS | Email already in use |
ファイルサイズ超過 | 400 | FILE_TOO_LARGE | File size exceeds 5MB |
不正なファイル形式 | 400 | INVALID_FILE_TYPE | Only JPEG, PNG, WebP allowed |
ファイルアップロードフロー
エンドポイント設計やエラーハンドリングの仕様を明確にすることで、AIは適切なAPIを実装できます。
ステップ4: テストケースのコンテキスト化
テストケースをコンテキストに含めることで、「仕様」と「検証」が一体化します。
テストケースをGiven-When-Then形式で記述することで、期待する動作を明確に定義します。この形式は人間にもAIにも理解しやすく、そのままテストコードに変換できます。正常系だけでなく異常系も記述することで、エッジケースにも対応した堅牢な実装が可能になります。
## テストケース
### 正常系
**テストケース1: 名前の更新**
- Given: ログイン済みユーザー
- When: 名前を"John Doe"に更新
- Then:
- ステータスコード 200
- レスポンスに更新された名前が含まれる
- DBに反映されている
**テストケース2: メールアドレスの更新**
- Given: ログイン済みユーザー
- When: メールアドレスを"new@example.com"に更新
- Then:
- ステータスコード 200
- `emailVerificationRequired: true`
- 確認メールが送信される
- `emailVerified: false`になる
### 異常系
**テストケース3: 他人のプロフィール更新**
- Given: ユーザーAでログイン
- When: ユーザーBのプロフィールを更新しようとする
- Then:
- ステータスコード 403
- エラーコード `FORBIDDEN`
**テストケース4: ファイルサイズ超過**
- Given: ログイン済みユーザー
- When: 6MBの画像をアップロード
- Then:
- ステータスコード 400
- エラーコード `FILE_TOO_LARGE`
正常系と異常系の両方を記述することで、エッジケースにも対応した堅牢な実装が可能になります。
ステップ5: AIに生成を依頼
ここまで準備すれば、あとはAIに任せるだけです。
ステップ1〜4で作成したコンテキストを元に、AIエージェントに実装を依頼します。コンテキストを明示的に指定することで、AIは一貫性のある高品質なコードを生成できます。複数のコンテキストファイルを階層的に参照することで、プロジェクト全体の一貫性を保ちながら、特定の機能に必要な情報を提供できます。
エージェントへの指示:
以下のコンテキストを読み込んで、ユーザープロフィール編集機能を実装してください:
1. @.ai/team/context.md(プロジェクト全体のコンテキスト)
2. @.ai/domains/users/context.md(ユーザードメインのコンテキスト)
3. @.ai/features/profile-edit.md(この機能のコンテキスト)
実装する内容:
- Controller: ProfileController
- UseCase: UpdateProfileUseCase
- Repository: UserRepository の更新メソッド
- DTO: UpdateProfileDto
- テスト: 上記コンテキストのテストケース全て
既存パターンに従ってください:
@src/modules/users/users.controller.ts(参考実装)
ポイント: 複数のコンテキストファイルを階層的に参照することで、プロジェクト全体の一貫性を保ちながら、特定の機能に必要な情報を提供できます。
コンテキストファーストな設計パターン
コンテキストの作り方にもパターンがあります。 効果的なパターンを知ることで、質の高いコンテキストを効率的に作成できます。
パターン1: 意思決定のコンテキスト化(ADR)
「なぜこの技術を選んだのか」——この問いに答えられることが、技術的成熟度の証です。
アーキテクチャ上の重要な決定は、ADR(Architecture Decision Record)として記録します。なぜその技術を選択したのか、どんなトレードオフがあったのかを明確にすることで、将来の変更時の判断材料になります。ADRは単なる記録ではなく、チームの集合知を形式知として蓄積する強力なツールです。
# ADR-023: プロフィール画像の保存先
## ステータス
承認済み
## コンテキスト
ユーザーのプロフィール画像をどこに保存するか決定する必要がある。
## 検討した選択肢
### 選択肢1: データベースにBLOB保存
**長所**:
- バックアップが簡単
- トランザクション管理が容易
**短所**:
- DBサイズが肥大化
- 読み込みパフォーマンスが悪い
- スケールしにくい
### 選択肢2: ローカルファイルシステム
**長所**:
- シンプルな実装
- コストが低い
**短所**:
- 水平スケールが困難
- バックアップが複雑
- CDN連携が難しい
### 選択肢3: AWS S3
**長所**:
- スケーラブル
- CDN連携が容易(CloudFront)
- 高可用性
- バックアップ不要
**短所**:
- 外部サービスへの依存
- コストが発生
## 決定
**AWS S3を採用**
## 理由
- スケーラビリティが最重要
- CloudFrontでグローバル配信可能
- 将来的な動画対応も視野
- 運用負荷の低減
## 実装詳細
### バケット構成
```
Bucket: {project-name}-user-avatars-{env}
Region: ap-northeast-1
Access: Private(署名付きURL経由でのみアクセス)
Lifecycle: 削除されたユーザーの画像は90日後に自動削除
```
### ファイル命名規則
```
avatars/{userId}/{timestamp}-{randomId}.{ext}
例: avatars/usr_123abc/1697123456789-x8k2n.jpg
```
### アクセス制御
- S3バケット: Private
- アプリケーション: IAM Role経由でアクセス
- ユーザー: 署名付きURL(有効期限7日)で画像取得
### コスト試算
- 月間1,000ユーザー
- 平均画像サイズ: 500KB
- 月間ストレージ: 500MB ≈ $0.025
- 月間リクエスト: 100,000回 ≈ $0.40
- **合計: 約$0.50/月**
## 影響範囲
- [ ] S3バケットのプロビジョニング(Terraform)
- [ ] IAM Role/Policy設定
- [ ] アップロード機能実装
- [ ] 署名付きURL生成機能
- [ ] 古い画像の削除バッチ
## モニタリング
- S3バケットサイズ
- アップロード成功率
- 署名付きURL生成エラー率
## 将来の拡張
- 動画アップロード対応
- 画像の自動リサイズ(Lambda)
- 複数サイズの生成(サムネイル)
ADRを記録する利点:
- 透明性: なぜその決定をしたのかが明確
- 比較: 他の選択肢との比較が記録される
- 継続性: 将来の変更時の判断材料になる
- 教育: 新メンバーが過去の経緯を理解できる
ADRは一度書いたら終わりではなく、状況が変わったら見直すことも重要です。「このADRは古くなった」という記録自体が、プロジェクトの進化を示す貴重な情報になります。
パターン2: ドメイン知識のコンテキスト化
ドメイン知識は、最も価値のあるコンテキストです。
ビジネスロジックやドメインルールは、エンジニアだけでは正確に理解できないことが多く、ドメインエキスパートの知識が不可欠です。ドメイン固有の知識や業務ルールは、専門用語の定義と具体的なビジネスルールをコンテキストとして記述します。この「暗黙知を形式知に変換する」プロセスこそが、CDDの最も重要な活動の一つです。
# ドメイン: 決済処理
## ドメイン概要
このシステムでは、Stripeを使用してクレジットカード決済を処理します。
## 重要なドメイン用語
### Payment(支払い)
ユーザーが商品やサービスに対して行う金銭的取引。
**ライフサイクル**:
```mermaid
stateDiagram-v2
[*] --> Pending: 作成
Pending --> Processing: 決済開始
Processing --> Succeeded: 成功
Processing --> Failed: 失敗
Failed --> Pending: リトライ
Succeeded --> Refunded: 返金
Refunded --> [*]
Failed --> [*]
```
**属性**:
- `id`: 支払いID(内部)
- `stripePaymentIntentId`: Stripe側のID
- `amount`: 金額(最小通貨単位、円なら1円単位)
- `currency`: 通貨コード(ISO 4217、例: "jpy")
- `status`: ステータス
- `customerId`: 顧客ID
- `metadata`: メタデータ(注文IDなど)
### PaymentMethod(支払い方法)
ユーザーが登録した支払い手段(クレジットカードなど)。
**セキュリティ**:
- カード情報は**絶対に**自社DBに保存しない
- Stripeに保存し、`paymentMethodId`のみ保持
### Invoice(請求書)
定期課金やまとめ請求の際に発行される請求書。
## ビジネスルール
### ルール1: 決済の最小金額
**日本円の場合**: 50円以上
**米ドルの場合**: 0.50ドル以上
```typescript
// 実装例
const MINIMUM_AMOUNT: Record<string, number> = {
jpy: 50,
usd: 50, // 0.50ドル = 50セント
};
function validateAmount(amount: number, currency: string): void {
const minimum = MINIMUM_AMOUNT[currency];
if (amount < minimum) {
throw new PaymentAmountTooSmallError(
`Amount must be at least ${minimum} ${currency}`
);
}
}
```
### ルール2: 決済のリトライポリシー
**自動リトライ**: 3回まで
**リトライ間隔**: 指数バックオフ(1秒、2秒、4秒)
**リトライ対象エラー**:
- カード情報の一時的エラー
- ネットワークエラー
- Stripe APIの一時的障害
**リトライ対象外**:
- カード残高不足
- カード無効
- 不正検知による拒否
### ルール3: 返金ポリシー
- 全額返金: 決済から30日以内
- 部分返金: 決済から90日以内
- 返金は1回の決済につき1回まで
- 返金処理は非同期(ジョブキュー)
## エラーハンドリング
### Stripe APIのエラーマッピング
| Stripeエラー | 内部エラー | HTTPステータス | ユーザーメッセージ |
|-------------|-----------|---------------|------------------|
| card_declined | CARD_DECLINED | 400 | カードが拒否されました |
| insufficient_funds | INSUFFICIENT_FUNDS | 400 | 残高不足です |
| incorrect_cvc | INVALID_CVC | 400 | セキュリティコードが正しくありません |
| expired_card | CARD_EXPIRED | 400 | カードの有効期限が切れています |
| api_error | PAYMENT_PROVIDER_ERROR | 500 | 決済処理中にエラーが発生しました |
### エラー処理の実装パターン
```typescript
// ✅ 正しいエラーハンドリング
try {
const paymentIntent = await this.stripe.paymentIntents.create({
amount,
currency,
customer: customerId,
payment_method: paymentMethodId,
confirm: true,
});
return this.mapToPayment(paymentIntent);
} catch (error) {
if (error instanceof Stripe.errors.StripeCardError) {
// カード関連エラー
throw new CardError(
this.mapStripeCardError(error.code),
{ stripeErrorCode: error.code }
);
} else if (error instanceof Stripe.errors.StripeAPIError) {
// Stripe APIエラー
this.logger.error('Stripe API error', { error });
throw new PaymentProviderError(
'Payment provider error',
{ retryable: true }
);
} else {
// 予期しないエラー
this.logger.error('Unexpected payment error', { error });
throw error;
}
}
```
## セキュリティ要件
### PCI DSS準拠
**絶対に守ること**:
1. カード情報を自社サーバーに保存しない
2. カード情報をログに出力しない
3. カード情報をエラーメッセージに含めない
### ログ出力の注意
```typescript
// ❌ 絶対にダメ
logger.info('Payment', { cardNumber: '4242-4242-4242-4242' });
// ✅ 正しいログ
logger.info('Payment created', {
paymentId: payment.id,
amount: payment.amount,
currency: payment.currency,
customerId: payment.customerId,
last4: payment.cardLast4, // 下4桁はOK
});
```
### Webhook署名検証
Stripeからのwebhookは**必ず**署名検証する:
```typescript
// ✅ 必須
const signature = req.headers['stripe-signature'];
let event: Stripe.Event;
try {
event = this.stripe.webhooks.constructEvent(
req.body,
signature,
process.env.STRIPE_WEBHOOK_SECRET
);
} catch (error) {
throw new UnauthorizedError('Invalid webhook signature');
}
// イベント処理
await this.handleWebhookEvent(event);
```
## パフォーマンス要件
### 決済APIのレスポンスタイム
- 目標: 95%ile < 500ms
- 最大: 2秒(タイムアウト)
### Webhook処理
- 同期処理: 200ms以内にレスポンス
- 実際の処理: 非同期ジョブキューで実行
### リトライとタイムアウト
```typescript
const STRIPE_TIMEOUT_MS = 10000; // 10秒
const RETRY_CONFIG = {
retries: 3,
factor: 2,
minTimeout: 1000,
maxTimeout: 5000,
};
```
## テストデータ
### Stripeテストカード
| カード番号 | 用途 |
|-----------|------|
| 4242 4242 4242 4242 | 成功 |
| 4000 0000 0000 0002 | カード拒否 |
| 4000 0000 0000 9995 | 残高不足 |
| 4000 0000 0000 0069 | 有効期限切れ |
| 4000 0000 0000 0127 | CVC不一致 |
### テスト環境での注意
- 本番のAPIキーは**絶対に**コミットしない
- `.env.test`でテスト用キーを使用
- CIでは環境変数からキーを取得
## 参考リンク
- [Stripe API リファレンス](https://stripe.com/docs/api)
- [Stripe Testing](https://stripe.com/docs/testing)
- [PCI DSS ガイドライン](https://www.pcisecuritystandards.org/)
ドメインコンテキストの重要性:
- 専門用語の統一: チーム全体で同じ用語を使うことで、コミュニケーションが円滑になる
- ビジネスルールの明確化: 暗黙知を形式知に変換することで、実装の一貫性が向上
- セキュリティ要件の徹底: 絶対に守るべきルールを明示することで、セキュリティリスクを低減
- テストデータの提供: 開発・テスト時に使用できる具体的なデータを提供
ドメイン知識は、そのドメインに詳しい人(ドメインエキスパート)と協力して作成することが理想的です。
AI可読性を重視したコード設計
「人間可読性」に加えて「AI可読性」——これが次世代のコード品質の指標です。
従来、私たちは「人間が読みやすいコード」を書くことを心がけてきました。しかしAI時代においては、「AIが理解しやすいコード」も同様に重要です。幸いなことに、AIが理解しやすいコードは、多くの場合、人間にとっても理解しやすいコードです。
AI可読性とは
新しい概念には、明確な定義が必要です。「AI可読性」という言葉の意味を、ここでしっかり押さえましょう。
定義: AIエージェントがコードの意図、構造、パターンを正確に理解できる度合い
原則: コードは人間とAIの両方のため
この原則を理解すれば、「どちらか」ではなく「両方」を満足させるコードが書けるようになります。
良いコードは、人間にもAIにも優しいコードです。
略語だらけの変数名や、過度に凝ったトリッキーなコードは、人間にもAIにも理解が困難です。逆に、明確な命名、適切な型定義、シンプルな構造を持つコードは、両者にとって理解しやすくなります。AI可読性を重視したコードは、AIエージェントが理解しやすいだけでなく、人間にとっても読みやすいコードです。以下の例で、その違いを見てみましょう。
// ❌ 人間にもAIにも読みにくい
const f = (u, p) => {
const h = c.createHmac('sha256', k);
h.update(p);
return h.digest('hex') === u.p;
};
// ⚠️ 人間には読めるが、AIには曖昧
const verifyPassword = (user, password) => {
// Check password
return hash(password) === user.hashedPassword;
};
// ✅ 人間にもAIにも明確
/**
* ユーザーのパスワードを検証する
*
* @param user - 検証対象のユーザー
* @param plainPassword - 平文のパスワード
* @returns パスワードが正しければtrue
*
* @example
* const isValid = await verifyUserPassword(user, 'password123');
* if (!isValid) {
* throw new InvalidPasswordError();
* }
*/
export async function verifyUserPassword(
user: User,
plainPassword: string
): Promise<boolean> {
const hashedInput = await hashPassword(plainPassword, user.passwordSalt);
return crypto.timingSafeEqual(
Buffer.from(hashedInput),
Buffer.from(user.hashedPassword)
);
}
このように、適切な命名、型定義、コメントを組み合わせることで、AIと人間の両方が正確に理解できるコードになります。
パターン1: 意図を明確にする命名
「名前がすべてを語る」——これが良いコードの第一原則です。
変数名や関数名は、その目的や動作を明確に表現する必要があります。略語や短縮形は避け、完全な単語を使用することで、AIと人間の両方が理解しやすくなります。「タイピングの手間を省く」ために略語を使うのは、短期的な効率と引き換えに、長期的な可読性を犠牲にする悪手です。
// ❌ AIが意図を推測できない
function process(data: any): any {
const result = transform(data);
return validate(result) ? result : null;
}
// ✅ AIが意図を理解できる
function validateAndTransformUserInput(
rawInput: unknown
): ValidatedUserInput | null {
const transformedInput = transformToUserInput(rawInput);
const isValid = validateUserInputSchema(transformedInput);
return isValid ? transformedInput : null;
}
命名の原則:
- 動詞 + 名詞の組み合わせ(
createUser
,validateEmail
) - booleanは
is/has/can
で始める - 配列は複数形(
users
,items
) - 略語は避ける(
usr
→user
,pwd
→password
)
これらの命名規則に従うことで、コードを読むだけで何をしているのかが分かり、別途ドキュメントを参照する必要が減ります。
パターン2: 型による自己文書化
型は、最も正確なドキュメントです。
TypeScriptなどの型システムを活用することで、コード自体がドキュメントの役割を果たします。適切な型定義は、AIの理解を助けるだけでなく、バグの早期発見にもつながります。「any」や「unknown」を多用するのは、型システムの恩恵を自ら放棄する行為です。
// ❌ 型情報が不足
interface User {
name: string;
email: string;
status: string; // "active" | "inactive" | "suspended" ??
role: number; // 0, 1, 2 が何を意味する?
}
// ✅ 型で意図を明確化
type UserStatus = 'active' | 'inactive' | 'suspended' | 'pending_verification';
enum UserRole {
ADMIN = 'admin',
USER = 'user',
GUEST = 'guest',
}
interface User {
/** ユーザーの表示名 */
name: string;
/** ユーザーのメールアドレス(一意) */
email: string;
/** アカウントの状態 */
status: UserStatus;
/** ユーザーのロール(権限レベル) */
role: UserRole;
/** メール認証済みフラグ */
emailVerified: boolean;
/** 最終ログイン日時(初回ログイン前はnull) */
lastLoginAt: Date | null;
}
Union型やEnum、詳細なJSDocコメントを使用することで、型だけで多くの情報を伝えることができます。これにより、AIは正確にコードを理解し、適切な修正や拡張を行えます。
パターン3: ファイル構造での意図表現
ディレクトリ構造は、アーキテクチャの可視化です。
ファイルやディレクトリの配置自体が、プロジェクトの構造や設計思想を表現します。一貫性のある構造は、AIが新しいコードを生成する際の参考になります。「このファイルはどこに置くべきか」が自明な構造であれば、新しいメンバーもAIも、迷わず適切な場所にファイルを配置できます。
// ❌ フラットで意図が不明
src/
├── user.ts
├── auth.ts
├── profile.ts
├── payment.ts
└── order.ts
// ✅ 構造で意図を表現
src/
├── modules/
│ ├── users/
│ │ ├── domain/
│ │ │ ├── user.entity.ts # ドメインモデル
│ │ │ └── user.repository.ts # リポジトリインターフェース
│ │ ├── application/
│ │ │ ├── create-user.usecase.ts
│ │ │ └── update-user.usecase.ts
│ │ ├── infrastructure/
│ │ │ └── user.repository.impl.ts
│ │ └── presentation/
│ │ ├── users.controller.ts
│ │ └── dtos/
│ │ ├── create-user.dto.ts
│ │ └── update-user.dto.ts
│ │
│ └── auth/
│ └── ... (同様の構造)
構造の原則:
- レイヤーごとにディレクトリを分ける
- 責務が一目でわかる構造にする
- AIがパターンを学習しやすい一貫性を保つ
このような構造化されたディレクトリ配置により、AIは「この機能を追加する場合、どこにファイルを作成すべきか」を正確に判断できます。
パターン4: コメントではなくコードで表現
「コメントが必要なコード」は、「改善が必要なコード」です。
良いコードは、コメントに頼らずとも意図が伝わります。コメントは「なぜ」を説明し、「何を」はコード自体で表現するのが理想です。関数を小さく保ち、適切に命名することで、コメントなしでも理解できるコードが書けます。コメントは、「なぜこのアルゴリズムを選んだのか」「なぜこのワークアラウンドが必要なのか」といった、コードだけでは伝わらない背景情報を記述するためのものです。
// ❌ コメントに依存
// ユーザーがアクティブで、メール認証済みで、
// 最終ログインが30日以内の場合はtrueを返す
function checkUser(user: User): boolean {
return user.status === 'active'
&& user.emailVerified
&& (Date.now() - user.lastLoginAt.getTime()) < 30 * 24 * 60 * 60 * 1000;
}
// ✅ コードで意図を表現
const THIRTY_DAYS_IN_MS = 30 * 24 * 60 * 60 * 1000;
function isUserActive(user: User): boolean {
return user.status === 'active';
}
function isEmailVerified(user: User): boolean {
return user.emailVerified;
}
function hasRecentLogin(user: User): boolean {
if (!user.lastLoginAt) return false;
const daysSinceLastLogin = Date.now() - user.lastLoginAt.getTime();
return daysSinceLastLogin < THIRTY_DAYS_IN_MS;
}
function isEligibleUser(user: User): boolean {
return (
isUserActive(user) &&
isEmailVerified(user) &&
hasRecentLogin(user)
);
}
原則: コメントは「なぜ」を説明し、「何を」はコードで表現する
関数を小さく保ち、適切な命名を行うことで、コメントなしでも理解できるコードになります。これにより、AIはコードの意図を正確に把握し、一貫性のある修正を行えます。
パターン5: エラーハンドリングの標準化
一貫したエラーハンドリングは、保守性の要です。
エラーハンドリングを標準化することで、AIは適切なエラー処理を生成でき、デバッグも容易になります。カスタムエラークラスを使用し、エラーコードで一意に識別可能にすることで、運用時のトラブルシューティングが劇的に改善します。「Error: Something went wrong」のような曖昧なエラーメッセージは、デバッグの悪夢です。
// カスタムエラークラスの定義
export abstract class AppError extends Error {
abstract readonly code: string;
abstract readonly statusCode: number;
constructor(
message: string,
public readonly context?: Record<string, unknown>
) {
super(message);
this.name = this.constructor.name;
Error.captureStackTrace(this, this.constructor);
}
toJSON() {
return {
name: this.name,
code: this.code,
message: this.message,
statusCode: this.statusCode,
context: this.context,
};
}
}
// ドメインごとのエラー
export class UserNotFoundError extends AppError {
readonly code = 'USER_NOT_FOUND';
readonly statusCode = 404;
constructor(userId: string) {
super(`User not found: ${userId}`, { userId });
}
}
export class EmailAlreadyExistsError extends AppError {
readonly code = 'EMAIL_ALREADY_EXISTS';
readonly statusCode = 409;
constructor(email: string) {
super(`Email already exists: ${email}`, { email });
}
}
// 使用例
async function createUser(dto: CreateUserDto): Promise<User> {
// メールアドレスの重複チェック
const existing = await this.userRepository.findByEmail(dto.email);
if (existing) {
throw new EmailAlreadyExistsError(dto.email);
}
// ユーザー作成
const user = await this.userRepository.create(dto);
// メール送信(失敗してもユーザー作成は成功させる)
try {
await this.emailService.sendWelcomeEmail(user.email);
} catch (error) {
this.logger.warn('Failed to send welcome email', { userId: user.id, error });
}
return user;
}
エラーハンドリングの原則:
- 型安全性: 全てのエラーは型付きクラスとして定義
- 識別可能性: エラーコードで一意に識別可能
- コンテキスト保持: エラー発生時の状況を記録
- HTTP対応: HTTPステータスコードとの対応を明確化
このようなエラーハンドリングの標準化により、AIは一貫性のあるエラー処理を生成でき、運用時のトラブルシューティングも容易になります。
コンテキストのテスト駆動開発
TDDを知っている人なら、このアプローチの革新性がすぐに理解できるでしょう。TDDの良いところを残しつつ、AIの力を最大限に活用します。
TDDの「テストファースト」を、CDDでは「コンテキストファースト」にアップグレードします。
従来のTDD(Test-Driven Development)は「テストを書いてから実装する」という革新的なアプローチでした。Context-TDDは、これをさらに一歩進めて「コンテキストを書いてから、テストも実装も生成する」アプローチです。コンテキストに期待する動作を明確に定義すれば、AIがテストコードと実装コードの両方を生成できます。
Context-TDD: 新しいテスト駆動開発
Context-TDDは、TDDをAI時代に適応させた進化形です。
Context-TDDは、従来のTDD(Test-Driven Development)をAI時代に適応させた開発手法です。テストコードを先に書く代わりに、テスト可能なコンテキストを先に書きます。
従来のTDDでは「Red-Green-Refactor」のサイクルを回しますが、Context-TDDでは「Define-Generate-Validate-Refine」のサイクルを回します。コンテキストに期待する動作を明確に定義することで、AIが正確なコードとテストを生成できます。
ステップ1: テスト可能なコンテキストを書く
Given-When-Then形式は、テストケースを記述する普遍的な言語です。
Given-When-Then形式でテストケースを記述します。この形式は、ビヘイビア駆動開発(BDD)で広く使われており、人間にもAIにも理解しやすい形式です。非エンジニアのステークホルダーでも理解できるため、仕様の合意形成にも使えます。
# 機能: ユーザー作成
## 期待する動作
### 正常系1: 有効なデータでユーザーを作成
**Given**:
- メールアドレス: "test@example.com"
- パスワード: "SecurePass123!"
- 名前: "John Doe"
**When**: createUser を呼び出す
**Then**:
- ユーザーが作成される
- `id` が生成される(UUID v4形式)
- `email` は小文字に正規化される
- `hashedPassword` にはbcryptハッシュが保存される
- `emailVerified` は `false`
- `createdAt` は現在時刻
- ウェルカムメールが送信される
**検証コード**:
```typescript
const user = await userService.createUser({
email: 'TEST@example.com', // 大文字でも
password: 'SecurePass123!',
name: 'John Doe',
});
expect(user.id).toMatch(/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/);
expect(user.email).toBe('test@example.com'); // 小文字化されている
expect(user.hashedPassword).not.toBe('SecurePass123!'); // ハッシュ化されている
expect(user.hashedPassword).toMatch(/^\$2[aby]\$/); // bcryptハッシュ
expect(user.emailVerified).toBe(false);
expect(user.createdAt).toBeInstanceOf(Date);
異常系1: メールアドレス重複
Given: メールアドレス "existing@example.com" のユーザーが既に存在
When: 同じメールアドレスでcreateUserを呼び出す
Then:
-
EmailAlreadyExistsError
がスローされる - エラーコード:
EMAIL_ALREADY_EXISTS
- HTTPステータス: 409
- DBにはユーザーが作成されない
検証コード:
await expect(
userService.createUser({
email: 'existing@example.com',
password: 'SecurePass123!',
name: 'Jane Doe',
})
).rejects.toThrow(EmailAlreadyExistsError);
異常系2: 弱いパスワード
Given: パスワード "123" (脆弱)
When: createUserを呼び出す
Then:
-
WeakPasswordError
がスローされる - エラーメッセージに具体的な要件を含む
パスワード要件:
- 最低8文字
- 英大文字、英小文字、数字、記号を各1文字以上含む
検証コード:
await expect(
userService.createUser({
email: 'test@example.com',
password: '123',
name: 'John Doe',
})
).rejects.toThrow(WeakPasswordError);
Given-When-Then形式で記述することで、テストケースが明確になり、AIは適切なテストコードを生成できます。
ステップ2: コンテキストから自動テスト生成
テストコードを書く時間を、テストケースの設計に集中できます。
ステップ1で作成したコンテキストを元に、AIにテストコードを生成させます。Given-When-Thenで明確に定義されたテストケースは、そのままテストコードに変換できます。テストコードの記述という「機械的な作業」をAIに任せることで、開発者は「何をテストすべきか」という本質的な設計に集中できます。
// AIへの指示例
/*
@.ai/features/user-creation.md のテストケースを
Jestのテストコードとして実装してください。
各テストケースの Given-When-Then を
describe-it 構造に変換してください。
*/
// AIが生成するテストコード
describe('UserService.createUser', () => {
describe('正常系', () => {
it('有効なデータでユーザーを作成できる', async () => {
// Given
const dto = {
email: 'TEST@example.com',
password: 'SecurePass123!',
name: 'John Doe',
};
// When
const user = await userService.createUser(dto);
// Then
expect(user.id).toMatch(/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/);
expect(user.email).toBe('test@example.com');
expect(user.hashedPassword).not.toBe('SecurePass123!');
expect(user.hashedPassword).toMatch(/^\$2[aby]\$/);
expect(user.emailVerified).toBe(false);
expect(user.createdAt).toBeInstanceOf(Date);
// ウェルカムメール送信の検証
expect(emailService.sendWelcomeEmail).toHaveBeenCalledWith('test@example.com');
});
});
describe('異常系', () => {
it('メールアドレスが重複している場合、EmailAlreadyExistsErrorをスローする', async () => {
// Given
await userService.createUser({
email: 'existing@example.com',
password: 'SecurePass123!',
name: 'Existing User',
});
// When & Then
await expect(
userService.createUser({
email: 'existing@example.com',
password: 'SecurePass123!',
name: 'Jane Doe',
})
).rejects.toThrow(EmailAlreadyExistsError);
});
it('弱いパスワードの場合、WeakPasswordErrorをスローする', async () => {
// When & Then
await expect(
userService.createUser({
email: 'test@example.com',
password: '123',
name: 'John Doe',
})
).rejects.toThrow(WeakPasswordError);
});
});
});
AIはコンテキストに記述されたテストケースを、そのままテストコードに変換できます。これにより、テストコードの記述時間を大幅に削減できます。
ステップ3: コンテキストの品質を測定
測定できないものは改善できません。コンテキストの品質も例外ではありません。
コンテキストの品質を定量的に測定することで、改善すべき点が明確になります。以下のようなスクリプトで品質を測定できます。これらのメトリクスをCIに組み込むことで、コンテキストの品質を継続的に監視し、品質が低下した場合は自動的にアラートを発することができます。
// .ai/scripts/measure-context-quality.ts
interface ContextQualityMetrics {
testCoverage: number; // テストケースのカバレッジ
specificationClarity: number; // 仕様の明確さ
exampleCompleteness: number; // 実装例の完全性
errorHandling: number; // エラーケースの網羅性
}
async function measureContextQuality(
contextPath: string
): Promise<ContextQualityMetrics> {
const context = await readContextFile(contextPath);
// 1. テストケースのカバレッジ
const testCases = extractTestCases(context);
const testCoverage = calculateTestCoverage(testCases);
// 2. 仕様の明確さ(Given-When-Thenの完全性)
const specificationClarity = testCases.filter(tc =>
tc.given && tc.when && tc.then
).length / testCases.length;
// 3. 実装例の完全性
const codeExamples = extractCodeExamples(context);
const exampleCompleteness = codeExamples.filter(ex =>
ex.isRunnable && ex.hasExpectedOutput
).length / codeExamples.length;
// 4. エラーケースの網羅性
const errorCases = testCases.filter(tc => tc.type === 'error');
const normalCases = testCases.filter(tc => tc.type === 'normal');
const errorHandling = errorCases.length / (normalCases.length + errorCases.length);
return {
testCoverage,
specificationClarity,
exampleCompleteness,
errorHandling,
};
}
// 品質基準
const QUALITY_THRESHOLDS = {
testCoverage: 0.8, // 80%以上
specificationClarity: 0.9, // 90%以上
exampleCompleteness: 0.7, // 70%以上
errorHandling: 0.3, // 30%以上(エラーケース)
};
// CIで自動チェック
async function validateContextQuality() {
const contexts = await findAllContexts('.ai/');
for (const contextPath of contexts) {
const metrics = await measureContextQuality(contextPath);
console.log(`\
📊 ${contextPath}`);
console.log(` Test Coverage: ${(metrics.testCoverage * 100).toFixed(1)}%`);
console.log(` Specification Clarity: ${(metrics.specificationClarity * 100).toFixed(1)}%`);
console.log(` Example Completeness: ${(metrics.exampleCompleteness * 100).toFixed(1)}%`);
console.log(` Error Handling: ${(metrics.errorHandling * 100).toFixed(1)}%`);
// しきい値チェック
const failures: string[] = [];
if (metrics.testCoverage < QUALITY_THRESHOLDS.testCoverage) {
failures.push('Test Coverage');
}
if (metrics.specificationClarity < QUALITY_THRESHOLDS.specificationClarity) {
failures.push('Specification Clarity');
}
// ... 他の指標も同様
if (failures.length > 0) {
throw new Error(
`Context quality check failed for ${contextPath}: ${failures.join(', ')}`
);
}
}
}
これらのメトリクスをCIに組み込むことで、コンテキストの品質を継続的に監視できます。品質が低下した場合は、自動的にアラートを発することも可能です。
ドキュメント駆動開発の再定義
従来のドキュメント駆動開発が失敗した理由を理解し、CDDがその問題をどう解決するかを見ていきます。
従来のDDD (Documentation-Driven Development)の問題点
「ドキュメントは嘘をつく」——これは、多くの開発者が経験してきた真実です。
仕様書作成 → 実装 → (ドキュメントが古くなる)
従来のドキュメント駆動開発では、以下の問題がありました:
- 乖離: 実装が進むにつれ、ドキュメントと実装が一致しなくなる
- メンテナンスコスト: ドキュメントの更新が後回しにされる
- 信頼性の低下: 古いドキュメントは誰も信じなくなる
ドキュメントが古くなる根本原因は、「ドキュメントを更新しなくても、コードは動き続ける」という構造的な問題にあります。CDDは、この構造自体を変えることで、問題を根本から解決します。
CDDにおけるドキュメント:実行可能な真実の源泉
CDDのコンテキストは「使われ続ける」ため、「古くならない」のです。
コンテキスト = 実行可能なドキュメント = 実装の源泉
CDDでは、コンテキストとドキュメントを同一視します:
- 必須性: コンテキストなしでは実装できないため、常に最新に保たれる
- 一致性: コンテキストから実装を生成するため、乖離が生じない
- 信頼性: AIの生成に必要なため、自然と品質が保たれる
この「必須性」こそが、CDDがドキュメント駆動開発を成功させる決定的な要因です。コンテキストが古いとAIが正しいコードを生成できないため、開発者は自然とコンテキストを最新に保つようになります。
実行可能なドキュメントの作り方
「実行可能」とは、コピー&ペーストで動くということです。
実行可能なドキュメントとは、読むだけでなく、そのまま実行・検証できるドキュメントです。以下の要素を含めることが重要です。抽象的な説明や疑似コードではなく、実際に動作するコード例を含めることで、ドキュメントの信頼性が劇的に向上します。
1. 具体的なコード例を含める
「動くコード例」は、千の言葉に勝ります。
APIの使用例を実際に実行可能な形式で記述します。curl コマンドやHTTPリクエストの例を含めることで、開発者は実際に試しながら理解を深めることができます。
## API使用例
### ユーザー作成
**リクエスト**:
```http
POST /api/v1/users
Content-Type: application/json
Authorization: Bearer {admin_token}
{
"email": "newuser@example.com",
"password": "SecurePass123!",
"name": "New User"
}
成功レスポンス (201 Created):
{
"user": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "newuser@example.com",
"name": "New User",
"emailVerified": false,
"role": "user",
"createdAt": "2024-10-12T10:30:00Z"
}
}
エラーレスポンス (409 Conflict):
{
"error": {
"code": "EMAIL_ALREADY_EXISTS",
"message": "Email already exists: newuser@example.com",
"statusCode": 409
}
}
curlでのテスト:
curl -X POST http://localhost:3000/api/v1/users \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_ADMIN_TOKEN" \
-d '{
"email": "newuser@example.com",
"password": "SecurePass123!",
"name": "New User"
}'
実行可能なコード例を含めることで、開発者は実際に試しながら理解でき、AIも正確にパターンを学習できます。
2. 視覚的な図を含める
「一目でわかる」——これが図の価値です。
複雑なシステムやフローは、図で表現することで理解しやすくなります。Mermaidなどのテキストベースの図表記法を使うことで、コードと同様にバージョン管理できます。アーキテクチャ図、シーケンス図、状態遷移図——これらの視覚的な表現は、テキストだけでは伝わりにくい情報を直感的に伝えます。
## システムアーキテクチャ
```mermaid
graph TB
Client[クライアント] --> LB[Load Balancer]
LB --> API1[API Server 1]
LB --> API2[API Server 2]
API1 --> Cache[Redis Cache]
API2 --> Cache
API1 --> DB[(PostgreSQL)]
API2 --> DB
API1 --> Queue[Job Queue]
API2 --> Queue
Queue --> Worker1[Worker 1]
Queue --> Worker2[Worker 2]
Worker1 --> S3[AWS S3]
Worker2 --> S3
```
## データフロー
```mermaid
sequenceDiagram
participant U as User
participant A as API
participant C as Cache
participant D as DB
participant Q as Queue
participant W as Worker
U->>A: POST /users
A->>D: ユーザー作成
D->>A: User created
A->>C: キャッシュ保存
A->>Q: ウェルカムメールジョブ
A->>U: 201 Created
Q->>W: ジョブ取得
W->>W: メール送信
W->>D: 送信記録保存
```
図を含めることで、システム全体の構造やデータの流れが一目で理解できます。
3. 技術選定の根拠を記録する
「なぜ」を記録することが、「次の選択」を成功させます。
技術選定の際は、なぜその技術を選んだのか、他の選択肢とどう比較したのかを明確に記録します。これにより、将来の技術変更時の判断材料になります。3年後にチームメンバーが入れ替わっていても、技術選定の背景を理解できることが重要です。
## なぜPostgreSQLを選んだのか
### 検討した選択肢
1. MySQL
2. PostgreSQL
3. MongoDB
### 評価基準
| 基準 | 重要度 | MySQL | PostgreSQL | MongoDB |
|------|--------|-------|------------|---------|
| JSON型サポート | 高 | △ | ◎ | ◎ |
| トランザクション | 高 | ◎ | ◎ | △ |
| 全文検索 | 中 | △ | ◎ | ◎ |
| パフォーマンス | 高 | ◎ | ◎ | ◎ |
| 運用実績 | 高 | ◎ | ◎ | △ |
| コスト(RDS) | 中 | ◎ | ◎ | △ |
### 決定: PostgreSQL
**理由**:
1. JSONBによる柔軟なスキーマ対応
2. 強力なトランザクション機能
3. チームの経験値が高い
4. AWS RDSでの運用が容易
5. pgvectorでベクトル検索も可能(将来の拡張)
**懸念点と対策**:
- MySQL比でやや複雑 → チーム内勉強会を実施
- レプリケーション遅延 → モニタリング強化
**今後の見直しポイント**:
- データ量が10TB超えたら再検討
- NoSQL的な使い方が増えたら一部MongoDB移行も検討
このように、選択の理由、他の選択肢との比較、将来の見直しポイントまで記録することで、技術選定の透明性が保たれます。
CDDのワークフロー
理論は理解した。では、実際の開発でどう使うのか?——ここからが実践編です。
CDDを実際の開発に取り入れる際の具体的なワークフローを説明します。日常的な機能開発から大規模なエピックまで、実際のコマンド例とともに見ていきましょう。このワークフローは、数多くのプロジェクトで磨かれ、実証された手順です。
日常的な開発フロー
毎日の開発サイクルが、このフローで効率化されます。
従来の「設計→実装→テスト→ドキュメント」というリニアなフローではなく、CDDでは「コンテキスト→生成→検証→改善」という反復的なフローを回します。このサイクルは、数分から数時間という短い間隔で回せるため、素早いフィードバックが得られます。
実際のコマンド例
理論だけではわかりにくい——実際のコマンド例で、CDDのワークフローを体感しましょう。
以下は、「ユーザープロフィール編集機能」を開発する際の、実際のコマンドラインでの操作例です。各ステップで何をしているのか、なぜそれが必要なのかを理解することで、CDDのワークフローを自分のプロジェクトに適用できます。
# 1. タスク開始
git checkout -b feature/user-profile-edit
# 2. コンテキスト確認
cat .ai/team/context.md
cat .ai/domains/users/context.md
# 3. 機能コンテキスト作成
mkdir -p .ai/features
cat > .ai/features/user-profile-edit.md << 'EOF'
# 機能: ユーザープロフィール編集
... (コンテキストを記述)
EOF
# 4. コンテキスト検証
npm run ai:validate
# 5. AI に実装依頼(Claude Code使用例)
claude code \
--context .ai/team/context.md \
--context .ai/domains/users/context.md \
--context .ai/features/user-profile-edit.md \
"ユーザープロフィール編集機能を実装してください"
# 6. テスト実行
npm test
# 7. コンテキストをコミット
git add .ai/features/user-profile-edit.md
git commit -m "docs(context): ユーザープロフィール編集機能のコンテキスト"
# 8. 実装をコミット
git add src/
git commit -m "feat: ユーザープロフィール編集機能を実装"
# 9. PR作成
gh pr create --fill
大規模機能の開発フロー
大きなエピックは、適切に分割することで、管理可能なサイズになります。
大規模な機能開発(エピック)では、まず全体のコンテキストを設計し、それを複数の小さな機能に分割します。各機能は独立して開発できるため、チームメンバーが並行して作業できます。この分割戦略により、大規模な開発も着実に進めることができます。
実例: 決済機能の開発(4週間のスプリント)
実際のプロジェクトで、4週間のスプリントをCDDでどう進めるか——週ごとの具体的な活動を見ていきます。
この事例は、実際のスタートアップで実施されたスプリントの記録です。Stripe決済を統合するという複雑な機能を、CDDのアプローチで段階的に開発した過程を追体験できます。
Week 1: コンテキスト設計
最初の週は、コーディングではなく、コンテキストの設計に集中します。 この投資が、後の3週間の開発速度を決定します。
# エピック定義
mkdir -p .ai/epics
cat > .ai/epics/payment-integration.md << 'EOF'
# エピック: 決済機能統合
## 目標
Stripeを使用した決済機能の実装
## スコープ
- クレジットカード決済
- 決済履歴
- 返金機能
- Webhook処理
EOF
# ADR作成
cat > .ai/team/adr/024-stripe-integration.md << 'EOF'
# ADR-024: Stripe決済の統合方式
...(決定内容)
EOF
# ドメインコンテキスト整備
cat > .ai/domains/payment/context.md << 'EOF'
# ドメイン: 決済処理
...(詳細な仕様)
EOF
Week 2-3: 機能実装
コンテキストが整備されていれば、実装は驚くほど速く進みます。 AIが一貫性のあるコードを生成してくれるため、開発者は本質的なビジネスロジックの検証に集中できます。
# 機能1: 決済処理
cat > .ai/features/payment-processing.md << 'EOF'
# 機能: 決済処理
...
EOF
claude code --context ... "決済処理を実装"
npm test
git commit -m "feat: 決済処理実装"
# 機能2: 決済履歴
cat > .ai/features/payment-history.md << 'EOF'
# 機能: 決済履歴
...
EOF
claude code --context ... "決済履歴を実装"
npm test
git commit -m "feat: 決済履歴実装"
# 機能3: 返金機能
cat > .ai/features/refund.md << 'EOF'
# 機能: 返金処理
...
EOF
claude code --context ... "返金機能を実装"
npm test
git commit -m "feat: 返金機能実装"
Week 4: 統合とリリース
最終週は、個別の機能を統合し、全体として機能することを確認します。 コンテキストがしっかりしていれば、統合時の問題は最小限に抑えられます。
# 統合テスト
npm run test:integration
# E2Eテスト
npm run test:e2e
# コンテキストの最終レビュー
npm run ai:validate
# リリース
git tag v2.0.0
git push --tags
実践的な導入ステップ
「明日から全部CDDで」は失敗の元です。段階的に、確実に導入しましょう。
CDDを既存のプロジェクトや新規プロジェクトに導入する際の、段階的なアプローチを紹介します。無理に一度に全てを変えるのではなく、少しずつ導入していくことが成功の鍵です。多くのチームが「完璧を目指して何も始められない」罠に陥ります。重要なのは、小さく始めて、継続的に改善していくことです。
フェーズ1: 基礎準備(1週間)
最初の一週間は、インフラの整備に集中します。
まずは、CDDに必要なディレクトリ構造を整備し、最小限のコンテキストを作成します。この段階では完璧を目指さず、「動く最小限の構成」を作ることが目標です。
Day 1-2: ディレクトリ構造の整備
良い家は、良い基礎から始まります。
# 1. .aiディレクトリの作成
mkdir -p .ai/{team,domains,features,templates,scripts}
# 2. 基本的なREADME作成
cat > .ai/README.md << 'EOF'
# AIコンテキストディレクトリ
このディレクトリには、AIエージェントが高品質なコードを生成するための
コンテキスト情報が格納されています。
## 構造
- `team/`: チーム共通のコンテキスト
- `domains/`: ドメイン別のコンテキスト
- `features/`: 機能別のコンテキスト
- `templates/`: 再利用可能なテンプレート
- `scripts/`: コンテキスト管理スクリプト
## 使い方
新しい機能を開発する際は:
1. 関連するコンテキストを確認
2. 必要に応じて機能コンテキストを作成
3. AIエージェントにコンテキストを読み込ませる
EOF
# 3. .gitignoreの設定
echo ".ai/personal/*" >> .gitignore
echo "!.ai/personal/.gitkeep" >> .gitignore
Day 3-4: 初期コンテキストの作成
「完璧なドキュメント」を目指すのではなく、「使えるコンテキスト」を作ります。
最初のコンテキストは、最小限の情報から始めます。詳細はあとから追加できますが、まずはAIが基本的なコード生成をできる程度の情報があれば十分です。
# .ai/team/context.md
最小限の情報から始める:
1. プロジェクト名と目的
2. 技術スタック(主要なもののみ)
3. ディレクトリ構造
4. 基本的なコーディング規約
**重要**: 完璧を目指さない。まずは動かすことが優先。
この段階で、チームメンバー全員にレビューしてもらい、フィードバックを収集します。
Day 5: 検証スクリプトの準備
自動化は早めに導入——手作業での品質管理は続きません。
コンテキストの品質を自動的にチェックするスクリプトを用意します。最初はシンプルなチェックから始め、徐々に高度な検証を追加していきます。
// .ai/scripts/validate-context.ts
import * as fs from 'fs';
import * as path from 'path';
// シンプルな検証から始める
function validateContext(filePath: string): boolean {
const content = fs.readFileSync(filePath, 'utf-8');
// 基本的なチェック
const checks = [
{ name: 'ファイルが空でない', pass: content.length > 0 },
{ name: 'マークダウン形式', pass: filePath.endsWith('.md') },
{ name: '最低限の見出しがある', pass: content.includes('#') },
];
const failed = checks.filter(c => !c.pass);
if (failed.length > 0) {
console.error(`❌ ${filePath}`);
failed.forEach(f => console.error(` - ${f.name}`));
return false;
}
console.log(`✅ ${filePath}`);
return true;
}
// 全コンテキストを検証
const contextFiles = [
'.ai/team/context.md',
// 他のファイルを追加
];
const results = contextFiles.map(validateContext);
const success = results.every(r => r);
process.exit(success ? 0 : 1);
この段階では、完璧を目指さず、基本的な構造を作ることを優先します。
フェーズ2: 小規模な機能での実験(2週間)
「いきなり本番」ではなく、「安全な実験」から始めます。
いきなり大規模な機能でCDDを導入するのはリスクが高いため、まずは小規模な機能で実験します。この実験フェーズで、チームはCDDの感覚を掴み、自分たちのプロジェクトに合わせた調整ができます。
ステップ1: パイロットプロジェクトの選定
最初の成功体験が、チームの信頼を勝ち取ります。
成功しやすい機能を選ぶことが重要です。失敗すると「CDDは使えない」という誤った結論に至る可能性があるため、慎重に選びます。
選定基準:
- 影響範囲が限定的(失敗しても影響が小さい)
- 複雑すぎない(3-5日で完成できる)
- チーム全員が理解できる(ドメイン知識が特殊すぎない)
良い例:
- ✅ 新しいAPIエンドポイントの追加
- ✅ 既存機能のリファクタリング
- ✅ ユーティリティ関数の追加
避けるべき例:
- ❌ 認証システムの刷新
- ❌ データベーススキーマの大幅変更
- ❌ レガシーコードの全面書き換え
ステップ2: コンテキストの作成と実験
実験は、学びのチャンスです。失敗を恐れず、多くを学びましょう。
パイロットプロジェクトでは、コンテキストの作成から実装、そして振り返りまで、CDDの全プロセスを一通り経験します。この経験から、自分たちのチームに最適なCDDのやり方が見えてきます。
# パイロット機能のコンテキスト作成
cat > .ai/features/pilot-feature.md << 'EOF'
# パイロット機能: ユーザー検索API
## 目的
CDDの有効性を検証するための実験的な機能実装
## ゴール
- ユーザーを名前・メールで検索できる
- ページネーション対応
- レスポンスタイム < 200ms
## 実装パターン
...(詳細)
EOF
# AI生成
claude code --context .ai/team/context.md \
--context .ai/features/pilot-feature.md \
"ユーザー検索APIを実装してください"
# テスト
npm test
# 結果の記録
cat > .ai/experiments/pilot-001-results.md << 'EOF'
# パイロット実験 001: ユーザー検索API
## 結果
- 開発時間: 4時間(従来比 60%削減)
- コード品質: ✅ 全テスト合格
- AI理解度: 90%(1回目で意図通り)
## 学んだこと
- コンテキストにコード例があると精度が高い
- エラーハンドリングの明示が重要
- テストケースも生成できた
## 改善点
- パフォーマンス要件をより明確に
- 既存コードとのパターン統一
EOF
ステップ3: 振り返りと改善
振り返りなき実験は、単なる作業です。学びを言語化し、次に活かしましょう。
パイロットプロジェクトの終了後、チーム全体で振り返り会を開催します。この振り返りが、CDDの導入成功の鍵となります。
# チームでの振り返り会
## 議題
1. CDDの効果測定
2. 困った点・課題
3. 次のステップ
## 効果測定の指標
- 開発時間の短縮率
- コード品質(テスト合格率、バグ発生率)
- チームメンバーの満足度
- コンテキストの理解度
## よくある課題と対策
| 課題 | 対策 |
|------|------|
| コンテキスト作成に時間がかかる | テンプレートを用意する |
| AIの出力が期待と違う | コンテキストの具体例を増やす |
| 既存コードとの整合性 | 既存パターンをコンテキストに含める |
| チームの習熟度のばらつき | ペアプログラミングで知識共有 |
パイロットプロジェクトで得た知見を元に、導入方法を改善していきます。
フェーズ3: チーム全体への展開(4週間)
パイロットの成功を、チーム全体の成功に拡大します。
パイロットプロジェクトで効果が確認できたら、チーム全体に展開します。この段階では、パイロットで得た学びを活かし、チーム全体がCDDを日常的に使えるようにします。
Week 1: トレーニング
知識の共有は、成功の共有です。
チーム全員がCDDの基礎を理解できるよう、体系的なトレーニングを実施します。パイロットプロジェクトのメンバーが講師となり、実際の経験を共有することで、説得力のあるトレーニングができます。
# トレーニングプログラム
## Day 1: CDDの基礎(2時間)
- CDDとは何か
- なぜCDDが必要か
- 基本的なワークフロー
## Day 2: コンテキストの書き方(3時間)
- 良いコンテキストの条件
- テンプレートの使い方
- 実践演習
## Day 3: AI エージェントの活用(3時間)
- Claude Code / Cursor の使い方
- 効果的なプロンプト
- トラブルシューティング
## Day 4-5: ハンズオン(各3時間)
- 実際の機能開発
- ペアプログラミング
- Q&A
Week 2-3: 段階的な適用
一度に全てを変えるのではなく、段階的に適用範囲を広げます。
適用ルール:
- 新機能は必ずCDDで開発(強制)
- 既存コードの修正時はコンテキストを更新(推奨)
- コンテキストなしのPRはマージしない(Week 3以降)
段階的に適用することで、チームの負担を最小化しながら、CDDを定着させることができます。
Week 4: 定着化
一時的なブームで終わらせないために、仕組みとして定着させます。
## 定着化のための施策
### 1. コンテキストレビューの義務化
- PRレビューでコンテキストもレビュー
- チェックリストの活用
- **ポイント**: コードと同じく、コンテキストも品質管理の対象
### 2. コンテキストチャンピオンの任命
- 各ドメインにオーナーを配置
- 月1回のコンテキストレビュー会
- **ポイント**: 責任を明確にすることで、継続性を確保
### 3. 継続的な改善
- 月次でメトリクス測定
- 四半期でプロセス見直し
- **ポイント**: データに基づいた改善で、効果を可視化
定着化施策を継続することで、CDDがチームの文化として根付きます。「やらされ感」ではなく「やりたくなる」環境を作ることが重要です。
フェーズ4: 最適化とスケール(継続的)
定着したら、次は最適化——CDDを組織の競争力に変えます。
CDDが定着したら、自動化やメトリクス測定を導入し、さらに効率化を進めます。このフェーズでは、CDDを単なる開発手法から、組織の強みへと昇華させます。
自動化の導入
人間の手を離れて、自動的に品質が保たれる仕組みを作ります。
CI/CDパイプラインにコンテキスト品質チェックを組み込みます。これにより、人間がレビューする前に、基本的な品質が保証されます。
# .github/workflows/context-quality.yml
name: Context Quality Check
on:
pull_request:
paths:
- '.ai/**'
- 'src/**'
jobs:
validate-context:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '20'
- name: Install dependencies
run: npm ci
- name: Validate Context
run: npm run ai:validate
- name: Measure Context Quality
run: npm run ai:measure
- name: Check Context Coverage
run: |
# 変更されたソースファイルに対応する
# コンテキストが更新されているかチェック
node .ai/scripts/check-context-coverage.js
- name: Comment PR
uses: actions/github-script@v6
with:
script: |
const metrics = require('./context-metrics.json');
const comment = `
## 📊 Context Quality Report
- Test Coverage: ${(metrics.testCoverage * 100).toFixed(1)}%
- Specification Clarity: ${(metrics.specificationClarity * 100).toFixed(1)}%
- Example Completeness: ${(metrics.exampleCompleteness * 100).toFixed(1)}%
- Error Handling: ${(metrics.errorHandling * 100).toFixed(1)}%
`;
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: comment
});
ケーススタディ
理論は信じられない?では、実際の数字を見てみましょう。
実際にCDDを導入したチームの事例を紹介します。数値データを含めて、具体的な効果を示します。これらは実際のプロジェクトから得られたデータであり、CDDの効果を客観的に評価する参考になります。
ケース1: スタートアップ(5人チーム)の事例
「少人数だからこそ、効率化が死活問題」——スタートアップでのCDD導入記録です。
背景
- 企業: B2B SaaSスタートアップ
- チーム構成: エンジニア5名(全員フルスタック)
- 期間: 3ヶ月
- 目標: MVP開発の加速
- 課題: 限られたリソースで迅速な開発が必要
このチームは、限られたリソースで迅速にプロダクトを開発する必要がありました。競合他社との時間勝負の中、開発速度を上げる必要に迫られていました。
Before: 従来の開発(CDD導入前)
まず、CDD導入前の状況を見てみましょう。多くのチームが直面している典型的な問題です。
## 開発フロー
1. Notion で仕様書作成(1日)
2. 設計ミーティング(半日)
3. 実装(3-5日)
4. レビュー&修正(1-2日)
5. ドキュメント更新(半日、しばしばスキップ)
**合計**: 約6-8日/機能
## 課題
- Notionの仕様書が古くなる
- メンバー間で解釈が異なる
- コードレビューで「なんでこう実装した?」が多発
- 新メンバーのオンボーディングに2週間
After: CDD導入後
同じチーム、同じメンバーで、開発速度が劇的に変わりました。
## 開発フロー
1. コンテキスト作成(半日)
2. AIで実装(1-2日)
3. レビュー(半日)
4. (ドキュメントは常に最新)
**合計**: 約2-3日/機能
## 改善効果
- ✅ 開発時間 60%削減
- ✅ コンテキストが常に最新
- ✅ メンバー間の認識統一
- ✅ 新メンバーのオンボーディング3日に短縮
導入プロセス
どうやってこの変化を実現したのか?——4週間の導入プロセスを追います。
Week 1: 基礎準備
最初の一週間は、全員でCDDの基礎を学び、最小限の環境を整えました。
# Day 1
- .aiディレクトリ作成
- 基本コンテキストの記述(プロジェクト概要、技術スタック)
# Day 2-3
- チーム全員でCDDワークショップ(3時間)
- サンプル機能で練習
# Day 4-5
- パイロットプロジェクト(ユーザー管理機能)
- 結果測定とフィードバック
Week 2-4: 本格導入
練習は終わり。実際のプロジェクトで使い始めます。
# Week 2
- 新機能はすべてCDDで開発
- 既存コードのコンテキスト化(優先度順)
# Week 3
- ドメインコンテキストの整備
- ADRの導入
# Week 4
- CI/CDへの組み込み
- メトリクス測定開始
具体的な成果
数字が全てを物語ります——3ヶ月後の測定結果です。
## 定量的成果(3ヶ月後)
### 開発速度
| 指標 | 導入前 | 導入後 | 改善率 |
|------|--------|--------|--------|
| 機能開発時間 | 5日 | 2日 | 60%削減 |
| バグ修正時間 | 4時間 | 1.5時間 | 63%削減 |
| コードレビュー時間 | 2時間 | 30分 | 75%削減 |
| オンボーディング | 2週間 | 3日 | 85%削減 |
### コード品質
- テストカバレッジ: 65% → 85%
- バグ発生率: 30%削減
- コードの一貫性: 主観評価 3.2 → 4.5/5.0
### チーム満足度
- 開発体験: 3.1 → 4.3/5.0
- ドキュメント信頼度: 2.8 → 4.6/5.0
- AIエージェント活用度: 3.5 → 4.7/5.0
この事例から、CDDは特にスピードが求められるスタートアップ環境で大きな効果を発揮することがわかります。開発時間の削減だけでなく、コード品質やチーム満足度も向上しています。
重要な学び: 小規模チームこそ、CDDの恩恵を最大限に受けられます。全員が同じコンテキストを共有することで、コミュニケーションコストが劇的に下がります。
メトリクスと評価
「測定できないものは改善できない」——CDDの効果を数値で追跡しましょう。
CDDの効果を測定し、継続的に改善していくためのメトリクスを紹介します。これらのメトリクスを定期的に測定することで、CDDの投資対効果を客観的に評価し、経営層への説明材料としても活用できます。
CDDの成功を測る指標
CDDの成功は、多面的に測定する必要があります。 単一の指標だけでなく、複数の視点から評価することで、全体像が見えてきます。
1. コンテキスト品質指標
コンテキストの品質が、全ての出発点です。
interface ContextMetrics {
// 完全性
completeness: {
hasOverview: boolean; // プロジェクト概要
hasTechStack: boolean; // 技術スタック
hasArchitecture: boolean; // アーキテクチャ
hasConventions: boolean; // コーディング規約
hasExamples: boolean; // コード例
score: number; // 0-1
};
// 明確性
clarity: {
ambiguousStatements: number; // 曖昧な表現の数
codeExamplesRatio: number; // コード例の割合
diagramsCount: number; // 図の数
score: number; // 0-1
};
// 鮮度
freshness: {
lastUpdated: Date; // 最終更新日
daysSinceUpdate: number; // 更新からの日数
isStale: boolean; // 古くなっているか
score: number; // 0-1
};
// AI可読性
aiReadability: {
structuredContent: number; // 構造化された内容
machineReadableFormats: number; // 機械可読な形式
score: number; // 0-1
};
// 総合スコア
overallScore: number; // 0-100
}
2. 開発生産性指標
コンテキストの品質が上がると、生産性も上がります。
コンテキスト品質指標と生産性指標の相関を見ることで、コンテキストへの投資が実際の開発速度に与える影響を定量的に把握できます。
interface ProductivityMetrics {
// 開発速度
velocity: {
averageFeatureTime: number; // 平均機能開発時間(時間)
bugFixTime: number; // 平均バグ修正時間(時間)
codeReviewTime: number; // 平均レビュー時間(時間)
};
// AI活用度
aiUsage: {
codeGenerationRatio: number; // AI生成コードの割合
aiAssistedPRs: number; // AI支援されたPR数
contextReferences: number; // コンテキスト参照回数
};
// 品質
quality: {
testCoverage: number; // テストカバレッジ (%)
bugRate: number; // バグ発生率
codeConsistency: number; // コード一貫性スコア
};
}
3. チーム健全性指標
技術的な成功だけでなく、チームの幸福度も重要な指標です。
持続可能な開発には、チームメンバーの満足度とエンゲージメントが不可欠です。CDDによってチームの働き方がどう変わったかを測定します。
interface TeamHealthMetrics {
// 知識共有
knowledgeSharing: {
contextContributions: number; // コンテキスト貢献数
reviewParticipation: number; // レビュー参加率 (%)
documentationUpdates: number; // ドキュメント更新数
};
// オンボーディング
onboarding: {
timeToFirstPR: number; // 初PRまでの日数
timeToProductive: number; // 生産的になるまでの日数
mentorTime: number; // メンター時間(時間)
};
// 満足度
satisfaction: {
developerExperience: number; // 開発体験 (1-5)
toolSatisfaction: number; // ツール満足度 (1-5)
documentationTrust: number; // ドキュメント信頼度 (1-5)
};
}
ダッシュボード設計
一目で状況を把握できるダッシュボードが、継続的改善の鍵です。
メトリクスは測定するだけでなく、可視化することで初めて価値を発揮します。以下は、実際のプロジェクトで使われているダッシュボードの例です。
# CDD メトリクスダッシュボード
## 概要(リアルタイム)
┌─────────────────────────────────────────┐
│ 📊 総合スコア: 87/100 (↑ +5) │
│ │
│ Context Quality: 92/100 ██████████ │
│ Development Speed: 85/100 █████████ │
│ Code Quality: 88/100 █████████ │
│ Team Health: 84/100 ████████ │
└─────────────────────────────────────────┘
## コンテキスト品質(週次)
### 完全性
- プロジェクト概要: ✅
- 技術スタック: ✅
- アーキテクチャ: ✅
- コーディング規約: ✅
- ADR: 23件(今週 +2)
### 鮮度
- 最終更新: 2時間前
- 古いコンテキスト: 0件
- 更新頻度: 週3.2回
### AI可読性
- コード例カバレッジ: 78%
- 図表数: 45個
- 曖昧な表現: 3箇所 ⚠️
## 開発生産性(月次トレンド)
### 速度
機能開発時間
5日 ━━━━━━━━━━━━━━━━━━ (3ヶ月前)
4日 ━━━━━━━━━━━━━━ (2ヶ月前)
3日 ━━━━━━━━━━ (1ヶ月前)
2日 ━━━━━━ (今月) ↓60%
### AI活用度
- コード生成率: 65% (↑ +10%)
- コンテキスト参照: 147回/週 (↑ +23%)
- AI支援PR: 89% (↑ +15%)
## コード品質(累積)
### テストカバレッジ
85% ██████████████████
Branch: 82%
Line: 87%
Function: 91%
### バグ率
- 本番バグ: 2件/月 (↓ 30%)
- ステージングバグ: 8件/月 (↓ 25%)
- PR段階で発見: 35件/月 (↑ 40%)
## チーム健全性
### オンボーディング
- 新メンバー: 2名
- 初PRまで: 平均3.5日 (↓ 85%)
- 自立まで: 平均2週間 (↓ 75%)
### 満足度(5段階評価)
- 開発体験: ⭐⭐⭐⭐☆ 4.3
- ドキュメント信頼度: ⭐⭐⭐⭐⭐ 4.6
- AI活用満足度: ⭐⭐⭐⭐⭐ 4.7
## アクションアイテム
⚠️ 曖昧な表現が3箇所あります → [確認する]
✅ 今週のコンテキスト更新: 8回
📈 AI生成コード品質: 向上中
ベストプラクティス集
成功するチームと失敗するチームの違いは、細部にあります。
CDDを成功させるための実践的なベストプラクティスを紹介します。これらは、多くのプロジェクトでの試行錯誤の末に確立された、実証済みの指針です。
✅ DO: やるべきこと
これらの習慣が、CDDの成功を決定します。
1. コンテキストをバージョン管理
コンテキストもコードです。同じように扱いましょう。
# コンテキストはコードと同じリポジトリで管理
git add .ai/
git commit -m "docs(context): 決済ドメインのコンテキストを更新"
コンテキストをGitで管理することで、変更履歴が追跡でき、問題があれば以前のバージョンに戻すことができます。
2. コンテキストを小さく保つ
大きなファイルは、誰も読みません。
コンテキストファイルは、1ファイルあたり300-500行程度に保つのが理想です。それ以上大きくなったら、分割を検討しましょう。
❌ Bad: 1ファイルに全部詰め込む
.ai/context.md (5000行) ← 誰も読まない
✅ Good: 適切に分割
.ai/team/context.md (300行) ← 読みやすい
.ai/team/architecture.md (400行)
.ai/domains/auth/context.md (250行)
.ai/domains/payment/context.md (300行)
3. 具体的な例を含める
抽象的な説明は、誤解を生みます。
「こうしてください」と言うだけでなく、「このコードを参考にしてください」と示すことで、解釈のズレがなくなります。
❌ Bad: 抽象的な説明のみ
認証にはJWTを使用してください。
← 実装方法が不明確
✅ Good: 実装可能なコード例
```typescript
// 認証実装パターン
export class AuthService {
async generateTokens(userId: string): Promise<TokenPair> {
const accessToken = await this.jwtService.signAsync(
{ sub: userId, type: 'access' },
{ expiresIn: '15m' }
);
return { accessToken, refreshToken };
}
}
← コピペで使える
#### 4. 禁止パターンも明示
**「やってはいけないこと」を明示することで、よくある失敗を防げます。**
人間は、良い例だけを見ても、悪い例を自然と避けられるわけではありません。明示的に「これはダメ」と示すことが重要です。
```markdown
## エラーハンドリング
✅ 推奨パターン
```typescript
throw new UserNotFoundError(userId);
❌ 禁止パターン
throw new Error('User not found'); // カスタムエラークラスを使う
console.error('Error:', error); // ロガーを使う
#### 5. 定期的にコンテキストをレビュー
**メンテナンスされないドキュメントは、腐っていきます。**
コンテキストも例外ではありません。定期的にレビューし、古くなった情報を更新し、不要な情報を削除することで、コンテキストの鮮度を保ちます。
```markdown
# コンテキストレビュー会(月次)
## アジェンダ
1. 古くなったコンテキストの特定(10分)
2. 不明瞭な部分の洗い出し(15分)
3. 新規追加すべき内容の議論(15分)
4. 優先度付けと担当者決定(10分)
## 次回までのアクション
- [ ] 決済ドメインのコンテキスト更新(@alice)
- [ ] ADR-024作成(@bob)
- [ ] コード例の追加(@charlie)
❌ DON'T: やってはいけないこと
これらのアンチパターンは、CDDの効果を台無しにします。
1. コンテキストを古いまま放置
古いコンテキストは、ないよりも悪いです。 誤った情報を元にAIがコードを生成してしまいます。
❌ Bad:
最終更新: 6ヶ月前 ← これは「嘘のドキュメント」です
✅ Good:
- 機能追加時に必ず更新
- 設計変更時に即座に更新
- 月次レビューで鮮度チェック
2. 曖昧な表現を使う
「基本的に」「なるべく」——これらの言葉は、AIを混乱させます。
曖昧な表現は、人間でも解釈が分かれます。AIにとっては、さらに理解が困難です。
❌ Bad:
- 基本的にJWTを使う ← いつ使わないの?
- なるべくテストを書く ← どれくらい?
- 適宜リファクタリングする ← いつ?
✅ Good:
- 認証は必ずJWTを使用する(例外: OAuth連携)
- 全ての公開APIにテストを書く(カバレッジ80%以上)
- コード行数が300行を超えたらリファクタリングする
3. AIに依存しすぎる
AIは強力ですが、完璧ではありません。
AIはアシスタントであり、あなたの判断を代替するものではありません。最終的な品質の責任は、人間が負います。
❌ Bad:
コンテキストを与えれば完璧なコードが生成されるはず
↓
生成コードをレビューせずにマージ ← 危険!
✅ Good:
コンテキスト → AI生成 → 人間がレビュー → 改善
↓
AIはアシスタント、最終判断は人間
トラブルシューティング
CDDを実践していると、様々な問題に遭遇します。よくある問題と解決策を知っておくことで、素早く対処できます。
問題1: AIの生成コードが期待と違う
最もよく遭遇する問題です。しかし、原因は明確で、解決策もシンプルです。
症状:
- コンテキストを読ませているのに意図と違うコードが生成される
- 毎回違うパターンで実装される
原因分析:
1. コンテキストが曖昧
→ 「基本的に」「なるべく」などの表現
2. 例が不足
→ 実装パターンが示されていない
3. 禁止パターンが明示されていない
→ 「やってはいけないこと」が書かれていない
解決策:
## Before(曖昧)
認証にはJWTを使ってください。
## After(明確)
### 認証実装パターン
**必須要件**:
- JWTトークンを使用
- アクセストークン: 15分
- リフレッシュトークン: 7日
**実装例**:
```typescript
// このパターンに必ず従う
export class AuthService {
async generateTokens(userId: string): Promise<TokenPair> {
// 実装...
}
}
禁止パターン:
// ❌ セッションベース
req.session.userId = userId;
// ❌ 長すぎる有効期限
expiresIn: '24h'
問題2: コンテキストが大きくなりすぎた
成長の痛み——プロジェクトが大きくなると、コンテキストも大きくなります。
症状:
- context.mdが1000行超え
- 何がどこに書いてあるかわからない
- AIの応答が遅くなる
これは成功の証でもありますが、適切に対処しないと、逆に生産性を下げてしまいます。
解決策:
# ステップ1: 分析
npm run ai:analyze-context
# 出力例:
# context.md: 1247行
# - プロジェクト概要: 150行
# - アーキテクチャ: 400行 ← 分割候補
# - コーディング規約: 300行 ← 分割候補
# - 技術スタック: 200行
# - その他: 197行
# ステップ2: 分割
mkdir -p .ai/team
mv .ai/context.md .ai/team/context.md
# アーキテクチャを抽出
code .ai/team/architecture.md # 400行をコピー
# 元ファイルから削除して参照に置き換え
echo "## アーキテクチャ" > temp.md
echo "詳細は [architecture.md](./architecture.md) を参照" >> temp.md
# ステップ3: 相互参照を設定
# context.md
echo "関連ドキュメント:" >> .ai/team/context.md
echo "- [アーキテクチャ](./architecture.md)" >> .ai/team/context.md
echo "- [コーディング規約](./conventions.md)" >> .ai/team/context.md
問題3: チームメンバーがコンテキストを更新しない
最も深刻な問題——技術的な問題ではなく、文化的な問題です。
症状:
- 実装は進むがコンテキストが古いまま
- 新メンバーが混乱する
- コンテキストの信頼性が低下
原因:
- コンテキスト更新が面倒(手間がかかる)
- 更新の重要性が理解されていない(意識の問題)
- 更新フローが不明確(やり方がわからない)
この問題を放置すると、CDDは形骸化します。早期に対処することが重要です。
解決策:
### 1. PRテンプレートに組み込む
## Pull Request Checklist
- [ ] コードを実装した
- [ ] テストを追加した
- [ ] **コンテキストを更新した**(該当する場合)
**コンテキスト更新が必要なケース**:
- 新しい設計パターンを導入した
- 技術的な決定をした
- エラーハンドリングパターンを追加した
### 2. CI/CDで強制チェック
```yaml
# .github/workflows/pr-check.yml
name: Check Context Update
on:
pull_request:
paths:
- 'src/**'
jobs:
check-context:
runs-on: ubuntu-latest
steps:
- name: Check if context updated
run: |
# コード変更がある場合、コンテキスト更新もチェック
if git diff --name-only origin/main | grep -q '^src/'; then
if ! git diff --name-only origin/main | grep -q '^\.ai/'; then
echo "⚠️ Warning: Code changed but context not updated"
echo "Consider updating .ai/ if you introduced new patterns"
fi
fi
3. 更新を簡単にするツール
# コンテキスト更新ヘルパー
npm run ai:update
# 対話的にコンテキスト更新
? What did you change?
› New authentication pattern
? Which context file?
› .ai/domains/auth/context.md
? Provide a brief description:
› Added OAuth2 integration pattern with Google
✅ Context updated!
📝 Don't forget to commit: git add .ai/
まとめ
長い記事でしたが、ここまで読んでいただき、ありがとうございます。最後に、CDDの本質をもう一度確認しましょう。
本記事では、AIエージェントを前提とした新しい開発手法「コンテキスト駆動開発(CDD)」について解説しました。
CDDの本質
CDDの本質は、たった一つのシンプルな原則に集約されます。
CDDの本質は、コンテキストを開発の中心に据えることです。コードではなく、コンテキストが「真実の源泉(Single Source of Truth)」になる——これがパラダイムシフトの核心です。
CDDがもたらす変化
CDDを導入することで、あなたのチームに何が起こるのか——具体的な変化を見てみましょう。これは単なる理想論ではなく、実際に起きている現実です。
CDDは、開発者、チーム、プロダクトの全てを変えます。
開発者の変化
あなた自身の仕事の内容が、根本的に変わります。そして、それはより創造的で価値の高い仕事へのシフトです。
役割の再定義——開発者は「実装者」から「設計者」へ。
Before: コードを書く人
After: コンテキストを設計する人
チームの変化
チーム全体のダイナミクスが変わります。情報の不均衡がなくなり、全員が同じスタートラインに立てるようになります。
知識の民主化——誰もが同じ情報にアクセスできる。
Before: 個人の暗黙知に依存
After: 明文化された知識で協働
プロダクトの変化
プロダクト自体の性質が変わります。変化に強く、進化し続けるプロダクトを作れるようになります。
資産の再定義——何を大切にするかが変わる。
Before: コードが資産
After: コンテキストが資産、コードは成果物
成功のための5つの鍵
CDDを導入しても失敗するチームと、大成功するチームがいます。その違いは何でしょうか。成功するチームは、この5つの鍵を握っています。
これら5つの鍵を握ることが、CDDを成功させる秘訣です。
1. コミットメント
中途半端な導入は、中途半端な結果しか生みません。
中途半端では効果は出ません。 コンテキストファーストを徹底する文化を作りましょう。
2. 一貫性
チーム全体で統一されたアプローチを取ることが、CDDの効果を最大化します。
一部だけ導入しても、効果は限定的です。 全ての機能開発でCDDを実践することで、初めて真価を発揮します。
3. 継続性
最初の熱意だけでは続きません。仕組みとして継続できる体制を作りましょう。
一時的なブームで終わらせない。 コンテキストを常に最新に保つ仕組みを作りましょう。
4. 透明性
情報を隠すのではなく、オープンにすることで、チーム全体の力を引き出せます。
コンテキストは秘密ではありません。 全員がアクセスでき、全員が改善に貢献できる環境を作りましょう。
5. 改善
測定なくして改善なし。データに基づいて継続的に改善しましょう。
測定し、学び、改善する。 メトリクスを測定し、継続的に改善するサイクルを回しましょう。
今日から始める3ステップ
理論を学んだら、次は実践です。この3ステップのロードマップに従えば、誰でもCDDを始められます。
完璧を目指さず、まず始めましょう。小さな一歩が、大きな変化につながります。
## ステップ1: 今日(30分)
**まずは最小限の構成から。**
1. `.ai/team/context.md` を作成
2. プロジェクト概要を3行で書く
3. 使っている技術スタックをリストアップ
**ポイント**: 完璧である必要はありません。まず書くことが重要です。
## ステップ2: 今週(2時間)
**チームで共有し、フィードバックを得ましょう。**
1. コーディング規約の基本を記述
2. 既存コードの代表的なパターンを抽出
3. チームで共有してフィードバック
**ポイント**: 一人で完璧にするのではなく、チームで育てていきます。
## ステップ3: 今月(継続)
**実践を通じて、改善していきましょう。**
1. 新機能はCDDで開発
2. 週1でコンテキストレビュー
3. メトリクスの測定開始
**ポイント**: 継続的な改善が、CDDの真価を引き出します。
次のステップ
CDDの基礎を学んだら、さらに深く学びたくなるでしょう。このシリーズの他の記事が、あなたの次の一歩をサポートします。
関連記事(コンテキストエンジニアリングシリーズ)
-
コーディングエージェント時代のコンテキストエンジニアリング実践ガイド
- 個人利用の基礎(前提知識)
-
コンテキストウィンドウの処理フローと動作メカニズム 完全解説
- 技術的詳細(深い理解)
-
プロンプトエンジニアリング2.0 - コンテキストを制する者がAIを制する
- コンテキスト管理 + プロンプト設計の統合
-
コーディングエージェントのメモリ設計 - 長期記憶システムの実装
- 外部化したコンテキストの管理・検索
-
- チーム活用(組織展開)
-
コンテキスト駆動開発(CDD) - AIファーストな開発手法
- 開発手法としての体系化
-
- 複数エージェントの協調動作
-
- トラブルシューティングに特化
おわりに
長い記事をここまで読んでいただき、ありがとうございます。あなたは今、新しい開発の扉の前に立っています。
私たちは、開発の歴史の転換点に立っています。
コンテキスト駆動開発(CDD)は、AIエージェントが当たり前になる時代の新しいスタンダードです。これは一時的なトレンドではなく、開発の本質的な進化です。
パラダイムシフト
この変化を理解することが、次の10年を生き抜く鍵になります。
「何を書くか」から「何を伝えるか」へ——これが21世紀の開発です。
これまでの開発手法は「人間がコードを書く」ことを前提としていました。しかし、AIが高度なコード生成能力を持つ今、何を書くかよりも何を伝えるかが重要になっています。
CDDの本質は、コンテキストを第一級市民として扱うこと。コンテキストが明確であれば、AIは最適なコードを生成し、チームは一貫した品質を保ち、新メンバーは迅速にキャッチアップできます。
今日から始める
この記事を読み終えたら、すぐに行動に移しましょう。明日ではなく、今日です。
大きな旅も、一歩から始まります。
小さく始めましょう。今日、.ai/context.md
に3行書くことから始めてください:
- プロジェクトの目的
- 使用している主な技術
- 基本的なディレクトリ構造
完璧である必要はありません。まず始めることが重要です。
継続的な改善
一度始めたら、止まらないでください。継続こそが、CDDの真の力を引き出します。
CDDは「やり方」ではなく、「文化」です。
そして継続しましょう。コンテキストを育て、改善し、チーム文化にすることで、CDDの真価が発揮されます。
一週間後、一ヶ月後、一年後——あなたのチームがどれだけ変わったかを振り返ってみてください。驚くほどの変化があるはずです。
最後に
AIとの協働の未来は、優れたコンテキストから始まります。
この記事があなたとあなたのチームの、新しい開発の旅の出発点になれば幸いです。CDDは単なる開発手法ではなく、AI時代を生き抜くための新しいマインドセットです。
そして、その未来は、今日から始めることができます。
さあ、あなたの.ai/context.md
を開いて、最初の一行を書きましょう。
コピペ実行ガイド(すぐ試せる)
読者が迷わず実行できるよう、記事内のコード/コマンドは以下のガイドに準拠します。
ガイドライン
- コマンドは
bash
フェンス内に、先頭記号($や#)は付けない(コピペしやすさ重視) - ファイル内容は言語に合わせたフェンス(
typescript
/yaml
/json
/markdown
)で提示 - 入出力がある例は「前提→コマンド→期待結果」の順で最小構成にする
- 長い例は
<!-- copy:start -->
と<!-- copy:end -->
で囲い、コピー範囲を明示
例: 環境セットアップと検証
npm ci
npm run build
npm run ai:validate
期待結果(抜粋):
✅ context: OK (links: 0 broken)
✅ rules: OK (ambiguity: low)
例: CDDワークフロー最小コマンド
# コンテキスト更新 → 生成 → 検証
npm run ai:context:update -- docs/api.md
npm run ai:gen -- docs/api.md
npm run ai:validate -- docs/api.md
例: 「コピー範囲」明示テンプレート
<!-- copy:start -->
## PRテンプレ(コンテキスト更新項目)
- [ ] 影響するコンテキスト更新済み
- [ ] 変更理由を記録(Why/Decision/Alternatives)
- [ ] ai:validate 通過(ログ添付)
<!-- copy:end -->
このガイドに合わせて既存のスニペットも順次整備していくと、読者/チームが迷わず実行できます。