【注意】
本記事でいう「仕様駆動開発」とは、テキストで仕様・ルールを先に整理し、それを AI と人間の共通の参照軸として実装を進めるやり方を指します。SRS を中心としたウォーターフォール開発全体や、TDD / BDD / spec-by-example の厳密な手法そのものを指すわけではありません。
はじめに: 仕様駆動開発とは?
仕様駆動開発という言葉を聞いたことがありますか?
「まず仕様書を書いて、それに基づいて開発する」という、ソフトウェア開発の基本的な考え方です。
仕様書を作成 → 仕様に基づいて実装 → 仕様通りの成果物
最近、AIを使った開発が増える中で、この仕様駆動開発が再び注目されています。
理由は明確で:
「AIに明確な仕様を渡せば、正確に実装してくれる」
と考えられるからです。
1. 仕様駆動開発のメリット
実際にAIと組み合わせて開発する中で、仕様駆動開発にはいくつかのメリットがあることを実感しました。
メリット1: ルールを明文化するとAIの出力が安定する
AIに「良い感じにやって」と言っても、毎回結果が違います。
でも、ルールをファイル化して渡すと、一貫した出力になります。
例: コミットメッセージ
❌ 口頭指示: 「良い感じにコミットして」
→ "add user search feature" でコミットされる(毎回フォーマットが違う)
✅ ファイル化: 「.rules/commit.md に従ってコミット」
→ "✨feat: add user search feature" で統一される
例: コーディングスタイル
❌ 口頭指示: 「きれいなコードで書いて」
→ 毎回スタイルがバラバラ
✅ ファイル化: 「.rules/coding-style.md に従って」
→ 命名規則、ファイル構成、エラーハンドリングが統一される
AIは律儀なので、明確なルールがあれば忠実に従います。
「仕様を明確にする」→「その通りに実装される」
これが仕様駆動開発の本質的なメリットです。
メリット2: ドキュメントが自然と残る
従来の開発では、ドキュメントの陳腐化が問題でした。
Week 1: コード書く → ドキュメント書く
Week 5: コード修正 → ドキュメント更新忘れ
Week 10: ドキュメント = もう古い = 見ない
仕様駆動開発では、仕様書がそのまま実装の入力になるので:
仕様書 ← AIがこれを見て実装
↓
仕様書を更新しないと意図した実装にならない
↓
自然と最新の状態が保たれる
仕様書が「使われる」から、自然と更新されます。
メリット3: チームでの認識が揃う
仕様書があることで、チーム全員が同じ理解を持つことができます。
従来: 「この機能どうなってたっけ?」→ コードを読む → 認知負荷による見落としや誤解発生
仕様駆動: 「この機能どうなってたっけ?」→ 仕様書を見る → 全員同じ理解
メリット4: レビューの負担が減る
AIが仕様に沿って一貫したコードを生成するので、レビューで確認すべきポイントが明確になります。
従来: 「この実装、意図は何だろう?」→ 推測しながらレビュー
仕様駆動: 「仕様通りに実装されているか?」→ 仕様と照らし合わせてレビュー
2. でも、実際にやってみたら課題があった
ここまで読むと、仕様駆動開発は完璧に見えますよね。
僕もそう思って実践してみました。
期待していたこと:
完璧な仕様と設計を作る → AIに渡す → 完璧な実装が出来上がる
実際に起きたこと:
完璧だと思う仕様と設計を作る
↓
AIに渡す
↓
設計通りに実装完了
↓
でも、動かしてみると問題だらけ...
課題: 実装してみないと設計の問題点がわからない
特に多かったのがこのパターン:
「設計通りに作ったけど、実際に動かすとダメだった」
「実装してみて初めて、設計のアプローチが間違っていたことに気づく」
具体例:
Day 1-2: 完璧な設計を作成
→ アーキテクチャ、データ構造、状態管理、全部詰める
→ 「これで完璧だ!」
Day 3: AIに実装を依頼
→ 設計通りに実装完了
Day 4: 動かしてみる
→ 「あれ? このデータ構造だと遅い...」
→ 「この状態管理、複雑すぎて破綻してる...」
→ 「実装してみて初めてわかった...」
仕様駆動開発の弱点:
設計が完璧だと思ってもいざ実装してみたらうまく動かない。
設計なしでAIに丸投げした場合はどうなるか
じゃあ仕様駆動開発をやめて、AIに全部任せればいいのか?
それも試しました。
僕: 「この機能を実装して」
AI: 「了解です!」
✅ 1つ目 - 動いた
✅ 2つ目 - 動いた
✅ 3つ目 - 動いた
⚠️ 4つ目 - なんか怪しい...
❌ 5つ目 - エラー連発
⚠️ 6つ目 - 無理矢理なおしてもらう
❌ 7つ目 - 違うところでエラー
💥 統合 - コードがメチャクチャで崩壊
問題: AIが途中で忘れる、方針がブレる、根本解決するまでにコードが大量に編集される、最後に崩壊
どちらも極端だった
❌ 完璧主義: 設計に時間かけすぎ → 実装で設計ミス発覚 → 根本から作り直し
❌ 無計画: AIに丸投げ → 設計なしで迷走 → 修正地獄 → 最後に崩壊
「仕様駆動開発のメリットは活かしつつ、課題を解決する方法はないか?」
そう考えて試行錯誤した結果、ある形に行き着きました。
3. 解決策: 試作フェーズを入れる
発想を変えてみました。
従来の仕様駆動開発:
設計 → 実装(一方向)
改良版:
設計 → 試作 → 設計修正 → 本実装(フィードバックループ)
「完璧な設計を作ってから実装」ではなく、
「ざっくり設計を書いて、試作しながら設計を修正」
結果
試作フェーズを入れることで、本実装前に設計の問題を発見できるようになりました。
例えば:
- 「このAPIの呼び出し順だと競合が起きる」→ 設計修正
- 「この状態管理だと複雑すぎる」→ シンプルな方法に変更
- 「このUIだと操作しづらい」→ 別のアプローチに変更
先に問題を特定することで、設計の手戻りコストが劇的に減りました。
実はこれ、人間が普段やっていること
よく考えたら、エンジニアって普段からこうやって開発してますよね。
試行錯誤、失敗ありき。
仕様駆動開発も、この「人間のやり方」に合わせれば良いんじゃないか。
ということで、仕様駆動開発でも以下の5つのフェーズとして体系化しました。
┌─────────────┐ ┌────────┐ ┌──────────────┐ ┌────────────────┐ ┌───────────┐
│ investigate │───▶│ design │───▶│ implement-all│───▶│design-finalize │───▶│ implement │
└─────────────┘ └────────┘ └──────────────┘ └────────────────┘ └───────────┘
調査 暫定設計 ⭐️試作実装 設計確定 本実装
各フェーズの詳細を説明していきます。
4. 各フェーズの詳細
Phase 1: investigate(調査)
何をする:
- タスクを深掘りして実現性を確認
- 技術選定
- スコープが大きければ分割を提案
Phase 2: design(暫定設計)
何をする:
- ざっくり設計を書く(完璧を目指さない)
- タスクをPR単位に分解
アウトプット:
requirement-temp.mdtodo-temp.md
ポイント: この時点では「暫定」なので、ざっくりでOK。
Phase 3: implement-all(試作実装)⭐️
何をする:
- 全タスクを一括で試作
- 実際に動かして問題を洗い出す
実装してみて初めてわかることが多い:
- 「このデータ構造だと遅い」→ 設計ミス
- 「この状態管理だと破綻する」→ アプローチが間違い
- 「この設計だと拡張性がない」→ 根本的な設計変更が必要
早期に失敗することで、設計の手戻りを防ぐ。
Phase 4: design-finalize(設計確定)
何をする:
- 試作で見つかった問題を設計に反映
-
tempを外して正式版にする
アウトプット:
requirement.mdtodo.md
Phase 5: implement(本実装)
何をする:
- 確定した設計で本実装
- タスクごとにPRを作成
5. 実際にやってみた例
具体例として、あるプロジェクトで発生した「テーブルのスクロール位置がリセットされるバグ」の修正をclaude codeのcommandsを使って試してみました。
.claude/
└── commands/
├── investigate.md
├── design.md
├── implement-all.md
├── design-finalize.md
└── implement.md
問題
テーブルコンポーネントで、行をクリックすると横スクロール位置が左端に戻ってしまう。
Phase 1: investigate
調査結果:
原因: インラインで定義されたコンポーネントが、
親の再レンダリング時に新しいインスタンスとして再生成
→ ReactがDOM全体を再構築
→ スクロール位置リセット
Phase 2: design
暫定設計:
## 解決方針
- useRefでスクロール位置を保存
- useEffectで位置を復元
Phase 3: implement-all ⭐️
AIに実装してもらって、動かしてみました。
見つかった設計の問題:
-
応急処置では根本解決にならない
- スクロール位置の保存/復元だけでは、位置がリセットされる根本原因を解決できない
- → 設計変更: コンポーネント分離が必要
-
分離だけでは不十分
- 分離しても、props変更で再レンダリングが発生
- → 設計変更:
React.memoでメモ化が必要
-
イベントハンドラが毎回新しいインスタンス
- メモ化しても、propsのハンドラが変わると再レンダリング
- → 設計変更:
useCallbackで安定化が必要
実装してみて初めて、設計のアプローチが甘かったことに気づいた。
Phase 4: design-finalize
確定設計:
## 解決方針(3段階)
1. コンポーネントを独立ファイルに分離
2. React.memoでメモ化(カスタム比較関数付き)
3. useCallbackでイベントハンドラを安定化
Phase 5: implement
確定した設計で本実装 → レビュー → 完了
結果: 試作で設計を検証済みだったので、スムーズに完了。
6. まとめ
試作フェーズで早期に失敗することが、本実装への一番の近道
設計 → 試作 → 設計修正 → 本実装
そしてこれは、人間のやり方を体系化しただけです
エンジニアが普段やっていること:
ざっくり考える → 試しに作る → 動かす → 直す → また作る
この自然な開発プロセスを、仕様駆動開発に組み込んだだけです。
仕様駆動開発 × アジャイルな試行錯誤
この組み合わせが、結局一番速いなと思いました。
おわりに
今回紹介したのは、あくまで仕様駆動開発をベースにしたオリジナルのアレンジでした。
実は、本家の仕様駆動開発で用いられているフレームワークのspec-kitは触ったことがありません。こちらもいつか試して比較してみたいなと思っています。
また、AIの進化は目覚ましく、今回紹介した試作フェーズも、将来的には必要なくなるかもしれません。
しかし、いくらAIが進化しても、すべてをAIに任せず、ところどころに人間の工夫を凝らしていくことが大切だと考えています。
「どこで人間が関与すべきか」を考え続けることが、これからの開発には欠かせないのかなと。
この記事が、AIとうまく付き合うヒントになれば嬉しいです。
参考資料
関連ツール
- Kiro - 仕様駆動開発をサポートするAI開発ツール
- spec-kit - GitHubの仕様管理ツール
- Claude Code - AI開発支援ツール
コマンド一部紹介
.claude/commands/implement-all.md 例
# Implement-All コマンド(設計検証用の暫定実装)
`design-temp.md` と `todo-temp.md` で定義された内容をそのまま形にしてみて、設計段階での漏れや矛盾がないかを早期に確認するためのコマンドです。暫定的にフル実装し、体験を可視化したうえで設計の妥当性を検証します。
## ワークフロー内の位置づけ
【現在】
┌─────────────┐ ┌────────┐ ┌──────────────┐ ┌────────────────┐ ┌───────────┐
│ investigate │───▶│ design │───▶│ implement-all│───▶│design-finalize │───▶│ implement │
└─────────────┘ └────────┘ └──────────────┘ └────────────────┘ └───────────┘
研究 暫定設計 ★ここ 設計確定 本実装
---
## ゴール
- 設計どおりに暫定フル実装をまとめ、仕様の意図が正しく反映されるか確認する
- ユーザー/関係者にブラウザで挙動をチェックしてもらい、設計段階の見落としや課題を洗い出す
- 収集したフィードバックを `design-temp.md`・`todo-temp.md` に反映し、設計を最新化する
- 本実装(`/implement`)へ移る前に対応方針と課題を明文化する
---
## 前提
- 対象ディレクトリの `design.md`・`requirements.md`・`todo.md` が最新で、意図する仕様が揃っている
- `.rules/pr.md`, `.rules/branch.md`, `.rules/commit.md` などのプロジェクト規約を把握している
- 現在のブランチ上でローカル変更として実装し、コミットせずに検証する
---
## ワークフロー
### 1. 事前準備
1. `requirements.md` の目的・要件・受け入れ条件を再確認し、想定通りの動作を明文化する
2. `todo.md` の Implementation Plan / Validation を確認し、作業順序と依存関係を明確にする
3. **重要**: 暫定実装はブランチ作成・コミットを一切行わない(ローカル変更のみ)
### 2. 設計どおりの暫定フル実装
1. `/implement-all <target>` を起動し、`todo.md` のタスクを設計に沿って順番に進める
2. 実装は設計で決めたアプローチを忠実に再現し、想定と異なる点があれば理由をメモする
3. 可読性・テスト網羅よりも「設計通りに動作するか」の検証を優先し、必要箇所に `TODO:` コメントを残す
### 3. ブラウザ検証(設計ギャップの洗い出し)
1. ビルド/起動手順を共有し、ユーザーにブラウザで挙動を確認してもらう
2. 期待とのズレ・不具合・改善要望をヒアリングし、再現手順やスクリーンショットを収集する
3. フィードバックをリスト化し、どの要件やシナリオに関連するかを整理する
### 4. 設計ドキュメントの更新
1. `requirements.md` の受け入れ条件や制約を更新し、暫定実装で露呈したギャップを明記する
2. `todo.md` の Implementation Plan / Validation をアップデートし、本実装で解消するタスクを明確にする
3. 設計全体に矛盾がないかを見直し、必要であれば追加調査や設計変更を実施する
### 5. 次ステップへの引き継ぎ
1. フィードバックから導いた修正方針を `todo.md` に落とし込み、優先度と担当を明確にする
2. 設計更新内容を共有し、ユーザーと合意が取れたら、現在の差分を解消し `/implement <target>` で本実装へ移行する
---
## ベストプラクティス
- 設計に記載されたアプローチを忠実に再現し、ズレが出た箇所は必ずメモやコメントで可視化する
- 暫定実装では最低限のテストだけ保持し、速度重視で体験確認まで進める
- フィードバックは「起きた事象」「期待との差」「対応方針」で整理し、文書へ即反映する
- ローカル変更として検証し、本実装は別途 `/implement` コマンドで行う
- 検証結果で得た学びを `design.md` の補足セクションに記録し、後続タスクで活用する
---
## 使用例
/implement-all docs/20251010_measurement-table-scroll-fix
/implement-all latest
---
## 注意事項
- 暫定実装のまま コミット やPR作成を行わない。必ず設計更新と `/implement` による本実装を経る
- ユーザーへのフィードバック依頼後は、課題が文書化されるまで実装を進めない
- 設計内容を修正した場合は、`design.md`・`requirements.md`・`todo.md` を同じタイミングで更新し、差分理由を明記する
- 外部サービスやデータに影響が出る場合は、検証環境やモックを活用して安全性を確保する
- リポジトリに意図しない変更が発生した場合は、すぐにユーザーへ報告し指示を仰ぐ









