⚠️ まず知っておくべき:AIへの矛盾した指令は危険
AIは「矛盾をエラーで止める」コンパイラではありません。矛盾した指令を与えると、次のような問題が起きます。
| パターン | AIの実際の挙動 | 危険度 |
|---|---|---|
| 矛盾に気づいて質問する | 「どちらを優先しますか?」と聞いてくれる(理想) | 低 |
| どちらかを黙って優先する | 後に書いた方・強調した方を無断で選択。人間は気づかない | 🔴 高 |
| 両方を中途半端に満たす | どちらの要件も中途半端に満たした「なんとなく動く」コードが生成される | 🔴 高 |
| 古いルールを上書きする | 長い会話の後に新しい指令が入ると、最初のルールを静かに破壊する | 🔴 高 |
AIは「矛盾を解決する」のではなく「それっぽい出力を生成する」モデルです。
コンパイラと違って「矛盾を検出して止まる」という保証がありません。
Phase 1 設計フェーズ(コードを書かせる前)
ここが最も重要です。手を抜くと後で崩壊します。
1. 仕様を人間が先に決める
AIに渡す前に、以下を自分で決めます。
- 何をするソフトか(1〜3行で言えるレベル)
- 主要なエンティティ(データ構造)
- 外部依存(DB、API、ライブラリ)
- 非機能要件(パフォーマンス、認証など)
2. AIにアーキテクチャ設計をさせる(まだコードは書かせない)
以下のようなプロンプトで、構造だけを先に設計させます。
「以下の仕様のWebアプリを作ります。
コードは書かずに、まず:
1. ディレクトリ構成
2. 各ファイルの責務
3. ファイル間の依存関係
4. データモデル定義
のみを提案してください」
このアウトプットを人間がレビュー・確定させることが絶対条件です。省略しないでください。
3. ARCHITECTURE.md を作成・固定する
AIが会話を通じて参照し続ける「憲法」になります。以下のような内容をMarkdownファイルにまとめます。
# ARCHITECTURE.md
## 技術スタック
- Backend: FastAPI + Python 3.11
- DB: PostgreSQL (SQLAlchemy ORM)
- Frontend: React + TypeScript
## ディレクトリ構成
src/
api/ # ルーティング層(DBに直接触らない)
services/ # ビジネスロジック(唯一DBを触る)
models/ # SQLAlchemyモデル定義
schemas/ # Pydanticスキーマ(API入出力)
## 重要なルール
- serviceはDBセッションを引数で受け取る(DI)
- apiレイヤーはserviceのみ呼ぶ
Phase 2 実装フェーズ
実装順序:依存の「根っこ」から上へ
上位層から書くと「まだ存在しない関数」を呼ぶコードが生まれ、AIが幻覚を起こしやすくなります。
1. models/ → DBスキーマ(何にも依存しない)
2. schemas/ → データ型
3. services/ → ロジック(modelsに依存)
4. api/ → ルーティング(servicesに依存)
5. tests/ → 全てに依存
1ファイル1プロンプトの原則
AIに実装を依頼するときは、「1回のプロンプトで1ファイル」を守ります。ただし、ただ指定するだけでなく、人間が事前に把握・判断した依存関係も一緒に渡します。
「ECサイトのバックエンドを作ってください」
→ AIがファイル構成・依存関係・実装を全部決める
→ 人間が把握できない構造になる
「services/order_service.py を実装してください。依存するファイル:models/order.py(内容↓)、models/product.py(内容↓)。実装する関数はこの3つのみ:create_order / cancel_order / get_order_summary」
人間がすべての依存関係を把握しきれない場合は、実装プロンプトを投げる前に「このファイルを変える前に、依存するファイルを教えて」とAIに先に確認させるのが現実的な対処法です。
各ファイルへのプロンプト構造
【コンテキスト】
- ARCHITECTURE.md の内容(貼り付け)
- 既存の関連ファイル(貼り付け)
【タスク】
`services/user_service.py` を実装してください
【制約】
- 既存の models/user.py の User クラスを使うこと
- schemas/user.py の UserCreate を入力型とすること
- DBセッションは引数で受け取ること(グローバルに持たない)
- このファイル単体で完結させること(新しいファイルを作らない)
Phase 3 整合性の維持
変更時は「影響チェック → 確認 → 修正」の3ステップを守る
「user_service.py の get_user の返り値を
User から UserWithProfile に変えました。
この変更の影響を受けるファイルをリストアップし、
必要な修正箇所を指摘してください(まだ修正しないで)」
修正を一気にやらせず、影響範囲の確認 → 人間がGO → 修正実行の3ステップを守ります。
定期的な「整合性監査」
数ファイル実装するごとに以下を実行します。
「以下のファイル群を読んで、
1. インターフェースの不整合(型の不一致など)
2. ARCHITECTUREのルール違反
3. 重複している処理
を報告してください。修正はしないでください」
※なぜ「AIが作ったバグ」の修正は特に難しいか
人間が書いたコードのバグは:
書いた人に意図がある
→ 「なぜそう書いたか」を聞ける
→ デバッグの手がかりがある
AIが書いたコードのバグは:
意図がない(確率的に生成された)
→ 「なぜそう書いたか」が存在しない
→ 手がかりがコードそのものしかない
しかもAIは自信満々に間違えるので、バグがあっても一見正しそうに見えるのが最悪の組み合わせです。
実際に起きるパターン
パターン1:AIが直し続けるが永遠に直らない
バグ報告 → AIが修正案を出す
→ 別の場所が壊れる → また修正
→ 最初の問題が再発 → また修正
→ ループ
AIは「それっぽい修正」を出し続けるので、 堂々巡りに気づきにくい。
現実的な対策
対策1:「AIに直させる」のに時間制限を設ける
AIに同じバグを3回直させて直らなければ
→ 人間がゼロから読む
(これを決めておかないと無限にループする)
対策2:AIが生成した怪しいコードは最初から小さく保つ
後でデバッグできる量にしか作らせない。 理解できないコードを大量生成させるのが最大のリスク。
1ファイルを理解してからでないと
次のファイルを生成させない
対策3:バグの「観測」だけAIに任せる
修正ではなく診断だけに使う:
「このバグの原因として考えられる
可能性を全部列挙してください。
修正はしないでください」
→ 人間がリストを見て判断する
→ 有望な仮説だけ人間が調査する
対策4:理解できないコードをそもそも採用しない
AIが出したコードを
自分が説明できない → 採用しない
これを守るだけで
デバッグ不能なバグの大半は防げる
現状のAI開発は:
✅ 得意:定型的な処理・テストが書きやすい領域
✅ 得意:仕様が明確で境界が小さいコード
❌ 苦手:複雑な状態管理・並行処理・環境依存
❌ 苦手:自分が生み出したバグのデバッグ
「AIで全部作る」ではなく「AIが得意な領域だけAIに任せる」 という使い方が、今の技術レベルでは生産性が最大化します。
Phase 4 テストとバックアップ
テストは実装直後に書く
「今書いた user_service.py のユニットテストを
tests/test_user_service.py に書いてください。
DBはモックを使い、以下のケースを網羅:
- 正常系
- ユーザーが存在しない場合
- DB接続エラー時」
バックアップは「動作確認済み」のタイミングで
「プロンプトごと」より「動作確認してOKだった時点」がバックアップの正しい粒度です。Gitを使ってこまめにコミットするのが最も合理的です。
# 1ファイル実装して動作確認できたら即コミット
git add src/services/user_service.py
git commit -m "add user_service: get/create/delete(動作確認済み)"
特に以下のタイミングは必ずバックアップします。
- 大きなリファクタを頼む前(影響範囲が読めない)
- 「複数ファイルをまとめて修正して」と頼む前
- 長い会話が続いてAIのコンテキストが怪しくなってきた時
ツール選択の指針
| ツール | 向いているケース |
|---|---|
| Claude Code | ターミナル作業・コマンド実行が必要、ローカル環境での開発 |
| Cursor / Windsurf | エディタ上で会話しながら書きたい |
| Claude.ai(チャット) | 設計・レビュー・複雑な相談 |
| GitHub Copilot | 補完メイン、自動化より手動が好み |
実践的な組み合わせ例:設計 → Claude.ai / 実装 → Claude Code or Cursor / レビュー → Claude.ai
🏆 まとめ:失敗しないための鉄則
- コードより先に設計を固める(ARCHITECTURE.mdが「憲法」)
- 依存の根っこから実装する(モデル → サービス → API)
- 1回のプロンプトで1ファイル(依存関係を人間が把握・明示してから渡す)
- 変更前に影響範囲を確認する(修正と確認を分ける)
- 動作確認済みの状態をこまめにGitコミット
- AIを信用しすぎない(整合性チェックは人間が主導)
AIでのチーム開発ではAIの使い方を全員が守らないと深刻な結果に
通常のチーム開発なら「ルール違反」は人間が書くので比較的ゆっくり広がります。ところがAI開発では:
ルールを守らない開発者
↓
AIが大量のコードを一気に生成
↓
矛盾が広範囲に高速で伝播
↓
気づいた時には手遅れ
人間が手で書く10倍のスピードで壊れが広がります。
まだまだAI開発の方法論は発展段階で、AIの方も進歩が著しいです。
ご参考になりましたら幸いです。


