スペック駆動開発への旅 ~ A Journey to the Spec-Driven Development
※はじめに
本記事は、都内某所において、生成AIを使ったスペック駆動開発に初めて触れる若手のソフトウェア開発者に向けて、スペック駆動開発のオンボーディング用に作成したドキュメントです。
実際にスペック駆動開発でソフトウェアを開発した後、その生成AI(Gemini)のコンテキストを使って執筆したものです。
目次
- はじめに:AI時代に、なぜ「スペック」が最強の武器になるのか?
- 第1章: AI開発の羅針盤、なぜ「スペック駆動開発」なのか?
- 第2章: SPECSフォルダ:AIへの「指示書一式」を準備する
- 第3章: 要求仕様(
requirements.md):AIに「目的」を教える - 第4章: 設計書(
design.md):AIに「制約」と「骨格」を与える - 第5章: 開発タスク(
tasks.md):AIに「具体的な手順」を渡す - 第6章: AIとの対話術:スペックを「魔法の呪文(プロンプト)」に変える
- 第7章: 実践編:トラブルシューティングと同期の技術
- 第8章: 変化との付き合い方:AIとスペックを「育て」続ける
- 第9章: さあ、冒険を始めよう:あなたの最初のAI+SDDプロジェクト
- おわりに:AIを操る「指揮者」になろう
- 参考文献:さらなる冒険のために
はじめに:AI時代に、なぜ「スペック」が最強の武器になるのか?
こんにちは、未来の素晴らしいエンジニアであるあなたへ。
今、私たちの開発現場は、AIという黒船の登場によって、大きな変革の波に洗われています。「AIがコードを書くなら、エンジニアの仕事はなくなるのか?」そんな不安を感じたことはありませんか?
断言します。答えは「No」です。
しかし、エンジニアの役割は確実に変わります。単純なコーダーはAIに代替されるでしょう。これからの時代に求められるのは、AIを 「賢く使いこなし、意図したものを、高速かつ高品質に創り出す」 ことができるエンジニアです。
では、どうすればAIを賢く使いこなせるのか?AIに「いい感じのログイン機能作って」とお願いしても、望むものは決して出てきません。AIは、あなたが何を、なぜ、どのように作りたいのか、その「文脈(コンテキスト)」を全く知らないからです。
本書の結論を先に言います。
AI時代における最強の武器、それこそが「スペック(仕様)」です。
この本は、単なるスペック駆動開発(SDD)の解説書ではありません。AIによる開発で生産性を飛躍的に向上させることを最終目的とし、そのための最も効果的な開発手法としてSDDを学ぶ、 次世代のAIネイティブ開発者のための「冒険の書」 です。
私たちが開発したアプリ「M」の航海記録を通じて、SPECS(スペック)という共通言語を使い、AIという名の強力なパートナーと共に、いかにして高速に、そして正確にプロダクトを創り上げていくか、その実践的な旅路をあなたと共有します。
さあ、AIを操る「指揮者」になるための旅へ、一緒に出発しましょう。
第1章: AI開発の羅針盤、なぜ「スペック駆動開発」なのか?
AI開発時代にSDDがなぜ重要なのか?それは、SDDがもたらすメリットが、AI開発の課題と驚くほど噛み合うからです。
1. メリット1:AIに「完璧なコンテキスト」を提供できる
AIの性能は、入力されるコンテキストの質で決まります。SPECSフォルダに格納されたドキュメント群は、AIにとってこの上ない「完璧なコンテキスト」となります。
-
product.md: この機能が、製品全体のどの目的を達成するためのものか -
requirements.md: この機能が、ユーザーのどんな課題を解決するのか -
tech.md,structure.md: この機能が、どんな技術的制約と作法の上で成り立つべきか -
design.md: この機能が、どんなコンポーネントとデータ構造で実現されるべきか
これらを渡すことで、AIは「ただのコード生成器」から、プロジェクトの目的を理解した「思考するパートナー」へと進化します。
2. メリット2:AIの「ハルシネーション」を抑制し、出力を検証可能にする
AIは時々、もっともらしい嘘をつきます(ハルシネーション)。存在しない関数を呼び出したり、プロジェクトの規約を無視したアーキテクチャを提案したり…。
SPECSは、AIの創造性を「正しい方向」に導くためのガードレールです。
-
あなた: 「この設計(
design.md)に従って、このタスク(tasks.md)を実装して」 - AI: (設計書という強い制約の中で、逸脱せずにコードを生成する)
そして、生成されたコードが本当に正しいかどうかを、私たちはSPECSを基準にレビューできます。「このコードは、要求仕様を満たしているか?」「設計書のシーケンス図通りに動くか?」― SPECSが、客観的な「正解」の役割を果たしてくれるのです。
3. メリット3:AIへの指示を「委任」のレベルに引き上げる
SPECSがない場合、AIへの指示は「この配列をソートする関数を書いて」といった、マイクロマネジメントになりがちです。
しかし、SPECSがあれば、指示の抽象度を劇的に上げることができます。
「requirements.mdの要件5に基づき、design.mdで定義された設計に従って、ユーザープロフィール表示機能を実装してください。関連するタスクはtasks.mdのPhase13を参照してください。」
これはもはや「指示」ではなく「委任」です。あなたはプロジェクトマネージャーのように振る舞い、AIはあなたの指示を忠実に実行する優秀な部下となります。これこそが、生産性を飛躍させる鍵なのです。
小話:AIに「お任せ」して生まれた、謎のボタン
プロジェクト初期、「設定画面を作って」と大雑把にAIに依頼したことがありました。すると、ログアウトボタンや保存ボタンと並んで、用途不明の「同期」ボタンが実装されて返ってきました。AIが他の一般的なアプリの例から「設定画面には同期ボタンがあるものだ」と類推(ハルシネーション)してしまったのです。もちろん、私たちの
requirements.mdにそんな要件はありませんでした。この経験から、私たちは「何を(What)」だけでなく「何でないか(What not)」も定義することの重要性を学びました。
第2章: SPECSフォルダ:AIへの「指示書一式」を準備する
SPECSフォルダは、単なるドキュメント置き場ではありません。それは、AIにプロジェクトの全体像を渡し、高品質な作業をさせるための「指示書一式」と考えるべきです。
1. 旅の三種の神器:AIを動かすための3つの指示書
-
requirements.md(目的指示書): AIに「なぜこれを作るのか」を伝えます。開発の最上位の目的であり、AIが判断に迷ったときに立ち返るべき北極星です。 -
design.md(技術指示書): AIに「どうやって作るのか」の骨格を伝えます。アーキテクチャ、コンポーネント、APIのIFなど、AIが逸脱してはならない技術的な制約を課します。 -
tasks.md(手順指示書): AIに「どの順番で、何をすべきか」を伝えます。複雑な実装を、AIでも確実に実行できるステップバイステップの命令に分解したものです。
2. ステアリングファイル:AIの思考を制約するガードレール
これらは、AIが何かを生成・提案する際に、常に前提として与えるべき「ガードレール」です。
-
product.md: 「この製品はFediverseの探検ツールである」とAIに教えることで、「友人とのチャット機能」のような見当違いな提案をさせないようにします。 -
tech.md: 「このプロジェクトではaxiosを使う」とAIに教えることで、fetchAPIを使ったコードを生成するのを防ぎます。 -
structure.md: 「コンポーネント名はPascalCaseで」とAIに教えることで、プロジェクトの命名規則に沿ったコードを生成させます。
Tips:SPECSは、最高のプロンプトエンジニアリングである
「プロンプトエンジニアリング」というと、小手先の言い回しを工夫するテクニックだと思われがちです。しかし、AIとの開発における最高のプロンプトエンジニアリングとは、構造化され、一貫性のあるSPECSを書き、それをコンテキストとしてAIに与えることに他なりません。
第3章: 要求仕様(requirements.md):AIに「目的」を教える
要求仕様書は、AIに「なぜこのコードを書くのか」という開発の目的を教えるための、最も重要なドキュメントです。
1. ユーザーストーリー:AIのための「物語」
「フローティングボタンを実装して」と指示するだけでは、AIはそのボタンが持つ意味を理解できません。ユーザーストーリーは、AIにその機能の背景にある「物語」を伝えます。
「タイムラインを見ているユーザーとして、思いついたことをすぐに投稿したい。なぜなら、インスピレーションが消える前に共有したいからだ」
この物語を読んだAIは、「なるほど、このボタンは素早いアクセスが最優先なのだな。であれば、表示アニメーションは最小限にすべきかもしれない」といった、目的を理解した上での提案ができるようになります。
2. EARS記法:AIのための「絶対的なルール」
EARS記法で書かれた受け入れ基準は、AIにとって「絶対に守るべきルール」として機能します。
- システムは、ユーザーがホームタイムラインを表示しているとき、画面右下にフローティングボタンを表示しなければならない。
この明確なルールがあれば、AIが「ユーザー設定でボタンを隠せるようにしましょう」といった、要求にない余計な機能を提案してくることを防げます。
小話:AIを混乱させた「または」
「投稿をタップしたとき、またはリプライボタンを押したとき、返信モーダルを開く」という基準を書いたところ、AIは2つの異なるイベントハンドラを実装し、それぞれが同じモーダルを開こうとする競合バグを作り込みました。これは人間の言葉の曖昧さが原因です。私たちはこれを「投稿の長押しメニューから『返信する』を選択したとき」「スレッド内の投稿から返信するとき」のように、トリガーとなるイベントを明確に分離して書き直すことで、AIの混乱を解消しました。
3. 要求仕様に「書いてはいけないこと」:AIを惑わす実装の詳細
要求仕様に実装の詳細を書くと、AIはそれを過度に重視し、より良い代替案を考えることをやめてしまいます。
-
NG例: 「投稿ボタンをタップしたら、
postStatus関数を呼び出す」 - OK例: 「ユーザーが投稿ボタンをタップしたとき、システムは、入力された内容で新しい投稿を作成しなければならない」
postStatusという関数名は、設計段階で変わるかもしれません。要求段階では、AIに特定の関数名や実装方法を意識させず、純粋に「ユーザーから見た振る舞い」だけを定義することに集中しましょう。
第4章: 設計書(design.md):AIに「制約」と「骨格」を与える
設計書は、AIの自由な発想を、プロジェクトの技術的な制約とアーキテクチャという「骨格」の中に収めるための、強力なガードレールです。
1. 要求と技術スタックを繋ぐ:AIへの「翻訳」プロセス
設計とは、ユーザーの言葉(要求)を、AIが理解できるエンジニアの言葉(コンポーネント、関数、データ構造)へと「翻訳」するプロセスです。この翻訳作業を人間が行うことで、プロジェクト全体の技術的な一貫性を担保します。
2. 全体像からコンポーネントへ:AIの活動範囲を限定する
アーキテクチャを定義し、コンポーネントの役割を明確にすることは、AIの「活動範囲」を限定することに繋がります。
「PostItemコンポーネントを修正して」と指示すれば、AIはservicesやcontextsを勝手に書き換えることなく、与えられたコンポーネントの責務の範囲内でコードを生成します。これにより、AIによる予期せぬ副作用を防ぐことができます。
3. 「絵」は言葉を超える:AIのための視覚的な指示書
シーケンス図やコンポーネント図は、AIにとっても非常に有効な指示書です。Mermaidのようなテキストベースの図は、AIが直接読み解くことができます。
小話:シーケンス図がAIのバグを防いだ話
「外部ユーザーのプロフィール表示」機能のシーケンス図をAIに渡して実装を依頼したところ、AIからこんな質問が返ってきました。「シーケンス図では、
lookupAccountAPIが失敗した場合、すぐにsearchAccountを呼び出しています。しかし、ネットワークエラーのように一時的な失敗の可能性を考慮し、リトライ処理を挟むべきではありませんか?」これは、図によって処理の流れが明確になったからこそ、AIが「例外ケース」に気づき、より堅牢な実装を提案できた素晴らしい例です。もし文章だけの設計だったら、この提案は得られなかったかもしれません。
4. 完璧な設計を目指さない勇気:AIを壁打ち相手にする
設計は、AIとの「壁打ち」に最適なテーマです。
-
あなた: 「ユーザー情報表示機能の設計案として、AとBを考えた。それぞれのメリット・デメリットと、
tech.mdの技術スタックを考慮した場合の推奨案を教えてほしい」 -
AI: 「A案は実装がシンプルですが、パフォーマンスに懸念があります。B案は初期実装が複雑ですが、拡張性に優れています。
tech.mdでReact Queryの採用が検討されているなら、キャッシュ機構と相性の良いB案を推奨します。」
このように、AIを設計のパートナーとすることで、一人では気づけなかった視点を得ることができます。
第5章: 開発タスク(tasks.md):AIに「具体的な手順」を渡す
開発タスクは、AIに「今、この一行のコードを書いてほしい」と伝えるための、最も具体的で、最も細かい粒度の指示書です。
1. 「1タスク = 1コミット = 1プロンプト」の原則
AI開発におけるタスク分割の目標は 「1タスク = 1プロンプト」 です。一つのタスクが一つの明確な指示となり、AIはその指示だけを忠実に実行します。
-
悪いタスク:
ユーザー情報ビューを実装する→ 悪いプロンプト:ユーザー情報ビューを実装して -
良いタスク:
[ ] getAccount APIを呼び出し、アバターと名前を表示する→ 良いプロンプト: 「UserScreen.tsxに、getAccountAPIを呼び出し、返り値のavatarとdisplay_nameを、それぞれImageコンポーネントとTextコンポーネントに表示するコードを追加してください。」
この粒度まで分解することで、AIの作業は単純な「コード片の生成」となり、ハルシネーションの入り込む余地を極限まで減らすことができます。
2. チェックリスト:AIとの共同作業の進捗管理
tasks.mdのチェックリストは、あなたとAIの共同作業における進捗管理ボードです。AIが一つのタスクを完了するたびに、あなたはそれをレビューし、問題がなければチェックを入れる [ ] → [x]。
このリズムが、複雑な機能開発を、まるで工場でベルトコンベアを流れる部品を組み立てるかのような、確実で予測可能なプロセスへと変えてくれます。
3. タスクとコミットメッセージ:AIの作業記録
完了したタスクは、そのままコミットメッセージになります。「このコミットは何?」と聞かれたら、tasks.mdの完了した一行を指差せば良いのです。これは、AIが何をしたかの明確な「作業記録」にもなります。
第6章: AIとの対話術:スペックを「魔法の呪文(プロンプト)」に変える
これまでの章で、SPECSがAIへの指示書として機能することを学びました。この章では、それらの指示書を、いかにして効果的な「プロンプト」としてAIに渡すか、その対話術に焦点を当てます。
1. AIはあなたの「相棒」であり「新人パートナー」
AIに「ログイン機能を作って」と丸投げしても、質の高い成果は得られません。AIは、あなたが育て、導くべき「新人パートナー」だと考えましょう。あなたの役割は、優れたコンテキストを与え、出てきた成果物をレビューし、フィードバックを与えることで、AIをプロジェクトの優秀な戦力に「教育」することです。
2. AIへの「良い指示」の出し方:WHY, WHERE, WHAT, CONTEXT
良い指示とは、以下の4つの要素を含んだ、明確で誤解の余地のない命令です。
- WHY(なぜやるのか): 「ユーザーが自分のプロフィールに素早くアクセスできるようにするため」
-
WHERE(どこでやるのか): 「
AppNavigator.tsxのTimelineScreenのoptionsの中で」 - WHAT(何をやるのか): 「ヘッダーの左側に、ログイン中ユーザーのアバター画像を表示し、タップしたらプロフィール画面に遷移するコンポーネントを配置する」
-
CONTEXT(文脈): 「関連する要求仕様は
requirements.mdの要件17です。ヘッダーの具体的なデザインはdesign.mdのナビゲーションの項目を参照してください。」
Tips:このプロジェクトで役立った、AIへの「神プロンプト」集
- 実装依頼: 「
requirements.mdの要件15と、design.mdのImageModalコンポーネントの設計に基づき、画像の全画面表示機能を実装してください。」- リファクタリング依頼: 「
PostItem.tsxが非常に長くなってきた。design.mdのコンポーネント設計原則に基づき、関心事をhooksやservicesに切り出すリファクタリング案を提案してください。」- ドキュメント更新依頼: 「先ほどのコミットで行った変更点を
requirements.mdとdesign.mdに反映してください。トレーサビリティが維持されるように、追記を基本としてください。」
3. AIが生成したコードとの付き合い方:レビューこそが人間の仕事
AIは、あなたが与えたSPECSというガードレールの範囲内で、最短距離のコードを生成します。しかし、そのコードが100%完璧である保証はありません。
AIの生成物は、あくまで「レビュー前のプルリクエスト」です。それを人間の目でレビューし、品質を担保するのは、あなたに残された重要な仕事です。AIの提案に疑問を感じたら、必ずdesign.mdやstructure.mdといったドキュメントに立ち返り、「このコードは、我々の設計思想に合致しているか?」と自問しましょう。
4. 対話型SDD:AIを「仕様記述パートナー」にする
これまでの章では、人間が書いたSPECSをAIに渡す方法を説明しました。しかし、このプロセスに慣れてきたら、さらに一歩進んだ、より高速なワークフローを導入できます。それが、 AIにSPECSそのものをドラフトさせる「対話型SDD」 です。
これは、人間が「発案者」と「レビューア」に徹し、AIが仕様の文章化から実装までを一気通貫で担当する、まさに次世代のペア開発手法です。
対話型SDDのサイクル
このワークフローは、あなたとAIとの短い対話の繰り返しで進みます。
- あなた(発案): 機能のアイデアを、口頭のような自然な言葉でAIに伝えます。
-
AI(要求の文章化): そのアイデアを解釈し、
requirements.mdに追記するためのユーザーストーリーと受け入れ基準(EARS記法)を生成します。 - あなた(レビュー): AIが生成した要求仕様をレビューし、承認(Approve)します。
-
AI(設計): 承認された要求仕様に基づき、
design.mdに追記するための設計案(機能概要、コンポーネント、APIなど)を生成します。 - あなた(レビュー): 設計案をレビューし、承認します。
-
AI(タスク化): 承認された設計に基づき、
tasks.mdに追記するための具体的な開発タスクリストを生成します。 - あなた(レビュー): タスクリストをレビューし、承認します。
- AI(実装): 承認されたタスクリストに基づき、最初のタスクから順にコードを実装します。
このサイクルの美点は、人間が面倒なドキュメントの「清書」から解放される点にあります。あなたの役割は、アイデアを出し、AIの成果物が正しい方向を向いているかを確認する「ディレクション」と「レビュー」に集中できます。
実例:対話型SDDで「投稿コピー機能」を追加する
あなた: 「投稿を長押ししたときに、『本文をコピー』というメニューを追加したいな。ユーザーが長い文章を引用したい時に便利だと思うんだ。」
AI: 「承知しました。その要求を
requirements.mdに追加するため、以下のユーザーストーリーと受け入れ基準を提案します。レビューをお願いします。」#### 要件XX: 投稿本文のコピー機能 - **ユーザーストーリー**: 投稿の読者として、私は、投稿の本文テキスト全体をクリップボードに簡単にコピーしたい。これにより、他のアプリでの引用や共有が容易になる。 - **Acceptance Criteria**: - システムは、ユーザーが投稿を長押ししたときのアクションメニューに、「本文をコピー」という選択肢を表示しなければならない。 - ユーザーが「本文をコピー」を選択した場合、システムは、その投稿の本文テキストをクリップボードにコピーしなければならない。 - コピーが成功した場合、システムは、「コピーしました」といった簡単なフィードバックをユーザーに表示しなければならない。あなた: 「素晴らしい。この内容で承認します。次は設計案を作成してください。」
AI: 「承知しました。
design.mdのPostItemコンポーネントの機能詳細に、以下のアクションを追加します。」- **本文のコピー**: アクションメニューに「本文をコピー」を追加。`expo-clipboard`ライブラリの`setStringAsync`メソッドを利用して、`post.content`をクリップボードに設定する。成功時には`Toast`メッセージを表示する。あなた: 「設計もOKです。では、この設計を
tasks.mdに分解してください。」AI: 「承知しました。
tasks.mdに以下のタスクを追加します。」- [ ] `expo-clipboard`ライブラリをインストールする - [ ] `PostItem.tsx`のアクションメニューに「本文をコピー」を追加する - [ ] 「本文をコピー」が選択された際に、`setStringAsync`を呼び出すハンドラを実装する - [ ] コピー成功時にToastメッセージを表示する機能を実装するあなた: 「完璧だ。では、最初のタスクから実装を開始してください。」
AI: 「承知しました。
expo install expo-clipboardを実行します...」
このように、一連の開発プロセスが、AIとの自然な対話を通じて、ドキュメントと共に生成されていくのです。
第7章: 実践編:トラブルシューティングと同期の技術
1. スペック通りなのに動かない!AIとのトラブルシューティング術
「要求通りに設計し、設計通りにタスクをこなし、AIに実装させた。完璧なはずだ…なのに、なぜかアプリがクラッシュする!」。
安心してください。これは、すべてのエンジニアが経験する道です。スペックは万能ではなく、ライブラリのバージョン、OSの癖、設定ファイルの見落としなど、スペックの粒度ではカバーしきれない「現実世界の壁」が必ず存在します。
重要なのは、パニックにならず、問題を解決し、その知見を未来のチームのために資産として残すことです。ここでは、AIを相棒としたトラブルシューティングと、その後の「仕上げ」のプロセスを解説します。
ステップ1:現象を正確にAIに伝える
まず、AIに「動きません」とだけ伝えるのは最悪手です。これでは、医者に「体調が悪いです」とだけ言うのと同じです。AIが優れた診断を下すためには、正確で豊富な情報が必要です。
-
NGな伝え方: 「
srcにファイルを移したら、ビルドがこけるようになった。助けて」 -
OKな伝え方: 「
srcディレクトリへソースコードを移行後、expo startを実行するとAndroidでビルドに失敗します。以下が、ターミナルに表示されたエラーメッセージです。Android Bundling failed 3959ms src\index.js (1542 modules) Unable to resolve "../config" from "src\hooks\useAuth.ts"useAuth.tsの該当するimport文はこれです。import { REDIRECT_URI } from '../config';config.tsはプロジェクトのルートディレクトリにあります。」
ポイント:
-
何をしたか:
srcディレクトリへの移行 - 何が起きたか: ビルド失敗
- どうやって分かったか: エラーメッセージの完全なコピー
- 関連情報: 該当箇所のコード、ファイルの配置状況
ステップ2:AIと仮説を立て、検証する
正確な情報を受け取ったAIは、質の高い仮説を立てることができます。
- あなた: 「このエラーの原因として、何が考えられる?」
-
AI: 「
src/hooks/useAuth.tsから../configという相対パスで解決しようとすると、src/config.tsを探しに行きます。しかし、実際のファイルはルートディレクトリにあるため、見つけられずにエラーになっている可能性が高いです。これは、Metroバンドラのモジュール解決のルートがsrcディレクトリ内を向いてしまっていることが原因かもしれません。」
この仮説を元に、AIに検証方法を尋ねます。
- あなた: 「Metroバンドラの設定を確認するには、どのファイルを見ればいい?」
-
AI: 「
metro.config.jsを確認してください。また、Expoの設定ファイルであるapp.jsonも関連している可能性があります。」
AIの助けを借りてmetro.config.jsやapp.jsonを読み解き、設定が不足していることを突き止めます。
ステップ3:修正と「仕上げ」
原因が特定できたら、修正は目前です。今回のケースでは、config.tsをsrcディレクトリに移動させ、metro.config.jsやapp.jsonに必要な設定を追記することで解決しました。
しかし、ここで終わりにしてはいけません。このトラブルは、我々のスペックに「考慮漏れ」があったことを示唆しています。これを「仕上げ」としてドキュメントに反映させましょう。
-
コードを修正する:
config.tsをsrcに移動し、metro.config.jsなどを修正する。 -
ドキュメントへの反映を検討する:
-
問い: なぜこの問題は起きたのか? → 「
srcディレクトリ構造を採用する際の、バンドラ設定に関する知見がstructure.mdに書かれていなかったから」 -
アクション:
structure.mdまたはtech.mdに、「srcレイアウトを採用する場合の注意点」として、metro.config.jsやapp.jsonの設定例を追記する。
-
問い: なぜこの問題は起きたのか? → 「
-
(任意)
tasks.mdに記録する:[x] metro.config.js の watchFolders と resolver.nodeModulesPaths を設定する[x] tech.md に src レイアウト時の Metro の設定について注記を追加する
この「仕上げ」のプロセスを経ることで、単なるバグ修正が、未来の自分や新しいチームメンバーが同じ問題でハマるのを防ぐための、価値ある「資産」に変わるのです。
2. セッション外の変更をAIと同期する技術
開発の現場では、常にAIとの対話だけで作業が進むわけではありません。IDEで直接コードを修正したり、同僚が更新した最新のコードをgit pullしたりすることもあるでしょう。
このようなAIの知らないところで行われた「セッション外の変更」は、AIの持つコンテキスト(文脈)を古びさせてしまいます。古いコンテキストのまま作業を依頼すると、AIは間違った修正案を提示したり、存在しないコードについて言及したりして、混乱の原因となります。
そうならないために、作業を再開する際には、まずAIとあなたの認識を「同期」させることが重要です。
同期戦略1:口頭で伝える(単純な変更の場合)
もし変更がごく小規模で自己完結しているなら、口頭で伝えるだけで十分な場合があります。
-
あなた: 「セッション外で、
README.mdのタイポを修正しておきました。次の作業に進んでください。」 -
AI: 「承知しました。
README.mdのタイポが修正されたことをコンテキストに反映します。」 -
あなた: 「先ほど、
PostItem.tsxのformatDate関数を、toLocaleStringを使う形に少しリファクタリングしました。」 -
AI: 「了解です。
formatDate関数が更新されたのですね。その前提で次の提案を行います。」
これは、AIにコードの正確なスナップショットを与えるというよりは、「そのファイルは少し変わった」というヒントを与え、AIの内部的な注意を向けさせる効果があります。
同期戦略2:差分(diff)を見せる(明確なコード変更の場合)
コードに具体的な変更が加わった場合、最も正確に同期する確実な方法は「差分(diff)」を見せることです。
-
あなた: 「AIとのセッション外で、
design.mdの記述を元にPostItem.tsxを一部修正しました。次の作業を始める前に、この変更をコンテキストに含めてください。以下がgit diff HEAD src/components/PostItem.tsxの実行結果です。」--- a/src/components/PostItem.tsx +++ b/src/components/PostItem.tsx @@ -312,7 +312,7 @@ if (isPublic) { Alert.alert('未実装', 'この機能はまだ実装されていません。'); - } else { + } else if (postToShow.id) { // 投稿IDが存在することを確認 navigation.navigate('Thread', { statusId: postToShow.id }); } } -
AI: 「差分情報を確認しました。
postToShow.idが存在する場合のみスレッドに遷移するよう修正されたのですね。この変更を反映した上で、次のタスクを検討します。」
git diffの結果は、変更の意図と内容を最も雄弁に語るドキュメントです。これを共有することで、AIは即座にあなたの現在地に追いつくことができます。
同期戦略3:ファイルを丸ごと読ませる(大規模な変更・不明な変更の場合)
複数のファイルにまたがる変更を行った場合や、しばらく時間が空いてどこをどう変えたか自分でも曖昧な場合は、ファイルを丸ごとAIに読ませるのが最も確実です。
-
あなた: 「週末にいくつかのファイルをローカルで修正しました。現在の最新状態で作業を始めたいので、まず
src/hooks/useAuth.tsとsrc/contexts/AuthContext.tsxを読み込んで、現在の実装を把握してください。」 - AI: 「承知しました。2つのファイルを読み込み、現在の状態をコンテキストに反映しました。何か変更点について特筆すべきことはありますか?なければ、次のタスクに進みます。」
これは最も時間がかかる方法ですが、AIとの認識のズレを完全にリセットできる、いわば「伝家の宝刀」です。
「同期」の後の「仕上げ」
AIとの同期が完了したら、最後に一つだけ自問しましょう。「この手動修正は、SPECSドキュメントに反映する必要があるか?」。もし修正がバグフィックスではなく、新しい振る舞いの追加や、設計からの逸脱を含む場合は、必ずrequirements.mdやdesign.mdを更新し、トレーサビリティを確保することを忘れないでください。
第8章: 変化との付き合い方:AIとスペックを「育て」続ける
仕様変更は、AI開発においては特に注意が必要です。なぜなら、あなたが見ているドキュメントと、AIが見ているドキュメント(コンテキスト)がズレると、AIは平気で古い仕様に基づいたコードを生成し始めるからです。
1. 「トレーサビリティ」:AIの暴走を防ぐ命綱
SPECSによって担保されたトレーサビリティは、仕様変更の影響範囲を特定するのに役立つだけでなく、AIの「暴走」を防ぐ命綱にもなります。「この要求を変えると、AIに指示を出すべき設計書の箇所と、タスクがこれだけ変わる」ということが明確になり、AIへの指示漏れを防ぎます。
2. 実装の変更を、スペックに逆反映する:AIの「記憶」をアップデートする
コードを修正したら、それはAIの「記憶」の元となるSPECSを更新する義務が発生した、ということです。この逆反映のプロセスを怠ると、AIのコンテキストは古い情報のまま取り残され、じわじわと「嘘」をつき始め、やがて大きな手戻りを生むことになります。
小話:「srcフォルダへ移動」大作戦。AIの記憶を更新する
プロジェクトの途中で、私たちはソースコード全体を
srcディレクトリに移動するという大きな構造変更を行いました。このとき、私たちはstructure.mdを即座に更新しました。後日、AIに新しいコンポーネントの作成を依頼した際、「structure.mdの規約に従って、src/componentsに作成してください」と一言添えるだけで、AIは新しい構造を完全に理解し、正しい場所にファイルを作成してくれました。もしドキュメントの更新、つまりAIの記憶の更新を怠っていたら、AIは古い構造のままコードを生成し、私たちはその修正に追われていたことでしょう。
3. 更新か、追記か:AIが「歴史」を学ぶための判断基準
ドキュメントを修正する際、安易に古い記述を消してしまうと、「なぜ以前はそうなっていたのか」というAIが学ぶべき貴重な「歴史」が失われてしまいます。基本は「追記」とし、AIが変更の経緯も学習できるようにしてあげましょう。
第9章: さあ、冒険を始めよう:あなたの最初のAI+SDDプロジェクト
この本を読んで、AIと共に開発を行う未来にワクワクしてくれたなら、これ以上嬉しいことはありません。しかし、知識は実践してこそ、本当の力になります。
この最後の章では、あなたが明日から、ゼロから新しいプロジェクトを「AIを使ったスペック駆動開発」で始めるための、具体的な最初のステップをガイドします。
ステップ0:アイデアを一行で書く
すべてのプロジェクトは、一行のアイデアから始まります。
- 「Mastodonのタイムラインを横断できるモバイルアプリ」
- 「読んだ本の感想を記録するWebアプリ」
- 「今日の献立を提案してくれるSlackボット」
この一行が、あなたの冒険の始まりです。
ステップ1:SPECS フォルダを作成する
なにはともあれ、まずプロジェクトのルートに SPECS フォルダを作成しましょう。これが、あなたとAIの「作戦司令室」になります。
ステップ2:ステアリングファイルで「航海の方針」を決める
コードを書き始める前に、AIとあなたが守るべき「航海の方針」を決めます。
-
product.mdを書く: ステップ0のアイデアを元に、「誰の、どんな課題を解決するのか」「製品の目的は何か」を2〜3パラグラフで記述します。 -
tech.mdを書く: あなたが使いたい、あるいは使うべき技術スタックをリストアップします。(例:React/Next.js,Python/FastAPI,Expo/React Native) -
structure.mdを書く: ファイルの命名規則やディレクトリ構成など、基本的なコーディング規約を定義します。最初はシンプルで構いません。
ステップ3:最初の「要求」を決める (requirements.md)
いきなりすべての機能を定義する必要はありません。製品の最もコアとなる、たった一つの機能について、最初の要求を書きましょう。
- ユーザーストーリー: 「ユーザーとして、私は〇〇したい。なぜなら△△だからだ」
- 受け入れ基準: EARS記法で、そのストーリーが「完了」したと言える条件を3〜5個書き出す。
ステップ4:最初の「設計図」を描く (design.md)
ステップ3で書いた要求を満たすための、ごく簡単な設計図を描きます。
- 機能概要: 要求を、エンジニアの言葉で説明し直します。
-
コンポーネント: その機能を実現するために必要そうなコンポーネントを2〜3個リストアップします。(例:
Timeline,PostItem) - API/データモデル: 外部APIが必要なら、どのエンドポイントを叩くか、どんなデータが返ってくるかを記述します。
ステップ5:最初の「タスクリスト」を作る (tasks.md)
ステップ4の設計図を元に、具体的な作業をチェックリスト形式で書き出します。目標は「1タスク = 1プロンプト」です。
[ ] 〇〇画面の基本的なレイアウトを作成する[ ] 〇〇APIを呼び出すサービス関数を作成する[ ] 取得したデータを画面に表示する
ステップ6:AIに最初の「委任」をする
おめでとうございます!これで、AIに高度な指示を出すための準備がすべて整いました。SPECSフォルダに作ったドキュメントをコンテキストとして渡し、最初のタスクを「委任」してみましょう。
最初のプロンプト例:
「これから新しいReact Nativeアプリの開発を始めます。開発の全体像は
SPECSフォルダの各ドキュメントを参照してください。まずは、
tasks.mdの最初のタスクである「〇〇画面の基本的なレイアウトを作成する」に着手します。design.mdで定義したコンポーネント構成に基づき、src/screens/ディレクトリに〇〇Screen.tsxを作成してください。現時点では、ダミーデータを表示するだけで構いません。」
ステップ7:レビューし、チェックを入れ、次のタスクへ
AIが生成したコードをあなたがレビューし、問題がなければtasks.mdにチェック [x] を入れます。そして、次のタスクについて、再びAIに指示を出すのです。
この「スペック定義 → AIへ委任 → レビュー」という小さなサイクルを繰り返すこと。それこそが、AI時代の新しい開発プロセスです。あなたの冒険の成功を、心から祈っています!
おわりに:AIを操る「指揮者」になろう
ここまで、AI時代の開発手法としてのスペック駆動開発(SDD)を巡る旅にお付き合いいただき、ありがとうございました。
本書で最も伝えたかったことは、これからのエンジニアは、自らコードを書く「演奏者」であると同時に、AIというパワフルな演奏者を率いる 「指揮者」 にならなければならない、ということです。
そして、その指揮者が振るタクト、すなわちオーケストラ全体に指示を出すための「楽譜」、それこそが 「スペック」 なのです。
- 要求仕様は、曲のテーマや物語を伝える「表題」。
- 設計書は、各楽器のパートや曲の構成を記した「総譜」。
- 開発タスクは、一小節ごとの具体的な演奏指示。
完璧な楽譜(スペック)があれば、AIという名の百人規模のオーケストラが、あなたの意図通りに、一糸乱れぬシンフォニー(プロダクト)を奏でてくれるでしょう。
この本を閉じたら、ぜひあなたのプロジェクトで、まずはたった一行のユーザーストーリーから、あなただけの楽譜を書き始めてみてください。
その小さな一歩が、あなたをAI時代の「マエストロ」へと変える、偉大な旅の始まりになることを信じています。
参考文献:さらなる冒険のために
本書で紹介した考え方をさらに深く探求するための、古典的名著や良書をいくつか紹介します。
-
『達人プログラマー(第2版) 職人から名匠への道』 (著:David Thomas, Andrew Hunt)
- 原題: The Pragmatic Programmer: From Journeyman to Master
- なぜ読むべきか?:特定の技術にとらわれない、プロフェッショナルなソフトウェア開発者としての心構えや実践的なヒントが詰まっています。SDDの根底にある思想とも多くの部分で共鳴します。
-
『Clean Architecture 達人に学ぶソフトウェアの構造と設計』 (著:Robert C. Martin)
- 原題: Clean Architecture: A Craftsman's Guide to Software Structure and Design
- なぜ読むべきか?:本書で触れた「コンポーネント分割」や「関心の分離」といった設計の原則を、より深く、体系的に学ぶことができます。良い設計とは何かを考えるための、強力な理論的支柱となります。
-
『ユーザーストーリーマッピング』 (著:Jeff Patton)
- 原題: User Story Mapping: Discover the Whole Story, Build the Right Product
- なぜ読むべきか?:本書の第3章で紹介した「ユーザーストーリー」を、さらに強力なツールにするための実践的な手法が解説されています。顧客の要求を一枚のマップに可視化することで、チーム全体で製品の全体像を共有できます。
-
『人月の神話【新装版】』 (著:Frederick P. Brooks, Jr.)
- 原題: The Mythical Man-Month: Essays on Software Engineering
- なぜ読むべきか?:半世紀近く前に書かれた本ですが、ソフトウェア開発の難しさに関する洞察は今も色褪せません。「なぜプロジェクトは遅れるのか」「設計はなぜ重要なのか」を考える上で、歴史的な視座を与えてくれます。
-
『エリック・エヴァンスのドメイン駆動設計』 (著:Eric Evans)
- 原題: Domain-Driven Design: Tackling Complexity in the Heart of Software
- なぜ読むべきか?:少し上級者向けですが、複雑なビジネスロジックをどうソフトウェアに落とし込むかという「ドメインモデリング」の技術は、要求仕様を深く理解し、質の高い設計を行う上で非常に役立ちます。「ユビキタス言語」の概念は、チームのコミュニケーションを次のレベルに引き上げてくれるでしょう。
Discussion