数ある「駆動開発」を整理して、なぜ今 SDD(仕様駆動開発)なのかを腹落ちさせる記事です。
この記事は 概念編 です。実際に BE/FE を分けて動かす 実践編 は別記事で扱います。
はじめに
駆動開発を学び始めると、まずこれにぶつかります。
TDD、BDD、DDD、ATDD、FDD……多すぎて違いが分からない
私もそうでした。さらに、いざ SDD(Spec-Driven Development)をやろうとしたとき、こんな素朴な疑問で詰まりました。
「仕様」と「振る舞い」って、結局なにが違うの?
この2つが分かっていないと、SDD は「なんとなく仕様書を先に書く流儀」くらいにしか見えません。逆にここが腹落ちすると、TDD も BDD も DDD も、バラバラの知識ではなくひとつの地図の上に並んで見えてきます。
この記事のゴールは2つです。
- 主要な駆動開発を、同じ土俵で比較できる地図を手に入れる
- 「AIを使うならなぜ SDD なのか」を、自分の言葉で説明できるようになる
対象読者は、私と同じ若手・SDD初学者です。
1. まず地図を持つ:「〜DD」は何を"駆動"しているのか
個々の手法に入る前に、補助線を1本引きます。これがあると一気に見通しが良くなります。
"〜Driven Development" は全部、「何を起点(出発点)にして開発を進めるか」の違いである。
- Test Driven → テストを起点にする
- Behavior Driven → 振る舞いを起点にする
- Domain Driven → **業務領域(ドメイン)**を起点にする
- Spec Driven → 仕様を起点にする
「何から書き始めるか」「何を正(=信頼できる基準)とするか」が違うだけ、と捉えると、対立ではなく着眼点の違いとして並べられます。
では、主要な3つを順に見ていきます(TDD → DDD → BDD)。検証を担うTDD、実装コードの設計を担うDDD、振る舞いの記述を担うBDD —— それぞれ担当が違います。3つを説明したあと、混同しやすい DDD と BDD の違いを改めて整理します。各説明の最後に「SDDではこの役割で生きる」という伏線を置きます。後で回収します。
2. 主要な駆動開発を一つずつ
2-1. TDD(テスト駆動開発):すべての出発点
テストを先に書いてから実装する手法です。「失敗するテストを書く → 通す → リファクタリング」を繰り返します(Red-Green-Refactor)。
# 先にテストを書く(まだ greet() は存在しない=失敗する)
def test_日本語を選ぶ():
assert greet(2) == "こんにちは、世界!"
テストが「実装が満たすべき仕様」の役割を果たすので、コードが正しいかを常に機械的に確認できます。BDD も DDD も、この「先に基準を決めてから実装する」発想の延長線上にあります。駆動開発の原点です。
🔖 SDDでの役割:実装が仕様どおり動くかを最終的に保証する「検証」を担う。
2-2. DDD(ドメイン駆動設計):実装コードを業務の言葉に揃える
TDD が「検証の出発点」なら、DDD は「コードの設計」を担当します。業務領域(ドメイン)を設計の中心に据え、実装コードの構造と名前を、業務の概念に一致させる手法です。中核にあるのが ユビキタス言語(Ubiquitous Language) という考え方です。
業務の専門家と開発者が、同じ一つの言葉を、会話・ドキュメント・コードのすべてで使う。
たとえば業務の人が「注文を確定する」と言うなら、実装コードもこう書きます。
class Order: # 「注文」という業務概念が、そのままクラスになる
def confirm(self): # 「確定する」が、そのままメソッド名になる
self.status = Confirmed # 状態の名前も業務の言葉
updateStatus(1) のような業務と無関係な命名を避け、コードの中身そのものを業務の言葉で組み立てる。クラスをどう分けるか、何をどう名付けるか、業務概念をどうコードの構造に落とすか —— この「実装の設計」がDDDの仕事です。
現場では、DDD はいつも使うわけではありません。学習コストが高く、見合うのは業務ロジックが複雑なシステムです。単純な CRUD 中心のシステムや Hello world 程度なら、かえって過剰。「複雑なドメインを扱うなら導入を検討する」のが実態です。役割は明確(コードの設計)だが、投資が見合う場面は選ぶ、という手法です。
🔖 SDDでの役割:実装コードの構造・命名を業務の言葉に揃え、仕様・Gherkin・コードを一貫させる。
2-3. BDD(振る舞い駆動開発):振る舞いを業務の言葉で書く
「こう操作したらこうなる」という振る舞いを記述する手法です。Given / When / Then という自然言語に近い形式で書き、この記述に使う専用言語が Gherkin です。
Feature: 多言語あいさつ機能
Scenario: 日本語を選ぶ
Given 番号 2 を指定する
When あいさつを取得する
Then "こんにちは、世界!" が返る
ポイントは、エンジニアでない人(ビジネス側)も読めること。要件を共有する「共通の仕様」として機能します。Given(前提)/ When(操作)/ Then(結果)の3つで、ひとつの振る舞いを表します。
🔖 SDDでの役割:仕様の中の「受け入れ基準」を、業務の言葉で具体例に固定する。
2-4. DDD と BDD は何が違うのか
ここまで読むと、ある疑問が湧きます(私もそうでした)。DDD も BDD も「業務の言葉を使う」と言っている。同じことでは?
違いは、業務の言葉を"どこに"書くかです。
| 業務の言葉を使う対象 | 例 | |
|---|---|---|
| DDD | 実装コードの構造・名前(中の作り) | class Order: def confirm() |
| BDD / Gherkin | テスト・仕様(外から見た振る舞い) | Then 注文が確定状態になる |
決定的なのは、Gherkin はコードの中身を決めないこと。「注文を確定したら確定状態になる」という外から見た振る舞いは書きますが、その裏で Order クラスがあるのか、confirm() なのか updateStatus() なのか —— そこにはノータッチです。その「コードの中身の設計」を担当するのがDDDです。
レストランで喩えると、Gherkin(BDD)はメニューと注文票(客から見たやり取り)、DDDは厨房の設計(中の構造)。メニューがあれば注文は通るが、厨房がぐちゃぐちゃだと複雑な料理で破綻する。
そして両者は独立して使えます。実際の現場では、DDD を導入せず BDD だけ使うケースのほうがむしろ多い —— 上の Gherkin も、ユビキタス言語をきっちり定義していなくても普通に書けます。両者は「必須」の関係ではなく、「揃うと噛み合う」関係です。DDD でコードの語彙が統一されていれば、Gherkin の言葉と実装の言葉がブレずに一貫する、という相乗効果が生まれます。
3. 記事の核心:「仕様」と「振る舞い」は違う
ここが、私が一番詰まったところです。Hello world の例で、両者の違いをはっきりさせます。
仕様(spec)= 何を・なぜ(方針の宣言)
仕様は、全体のルールや方針を言葉で書いたものです。具体的な動きの列挙ではありません。
# 仕様:多言語あいさつ機能
## 目的(Why)
利用者が番号で言語を選び、その言語の「こんにちは世界」を得たい。
## 要件(What)
- 番号を受け取り、対応する言語のあいさつ文字列を返す
- 対応外の番号は、英語をデフォルトとして返す
注目してほしいのは、「対応外はデフォルト英語」とは書いてあるけれど、「99 を入れたら?」「0 なら?」という一個一個の動きまではまだ確定していないこと。読み手(人間でもAIでも)が解釈する余地が残っています。
振る舞い(behavior)= こう入れたらこう出る(具体例の固定)
振る舞いは、その方針を「具体的な入力と出力のペア」に落とし込んだものです。
Scenario: 対応外はデフォルト英語
Given 番号 99 を指定する
When あいさつを取得する
Then "Hello, World!" が返る # ← 99 という具体的な数字に固定された
仕様では「対応外はデフォルト英語」という方針だけだったものが、振る舞いでは「99 を入れたら Hello, World! が返る」と、逃げ場のない具体例に固定されています。
並べると違いが見える
| 仕様(spec) | 振る舞い(behavior) | |
|---|---|---|
| 何を語るか | 全体の方針・ルール・なぜ | 個別の「入力→出力」 |
| 形 | 説明的な文章(Markdown) | 具体例(Gherkin) |
| 例 | 「対応外はデフォルト英語」 | 「99 → Hello, World!」 |
| 曖昧さ | 解釈の余地が残る | 余地がない(一意) |
| 検証 | そのままでは測れない | 自動で合否判定できる |
両者は対立しません。1つの仕様(方針)から、複数の振る舞い(具体例)が生まれる親子関係です。
4. SDD(仕様駆動開発)とは:他を"包み込む器"
ここまで来ると SDD が自然に理解できます。
背景:Vibe Coding の反動
2025年頃に流行した Vibe Coding(AIと対話しながら即興で作るスタイル)は、素早い試作には向く一方、「何を作るか曖昧なまま実装を始める」ため、本番開発では意図の取り違えや手戻りが起きやすいことが分かってきました。
その反動として注目されているのが SDD(Spec-Driven Development) です。まず仕様(spec)を書き、それを「信頼できる唯一の基準(Single Source of Truth)」として、AIエージェントにコードやテストを生成・検証させます。
SDD の一周
SDD の流れはこうです。そして重要なのは、この一周の中に TDD・BDD・DDD が部品として組み込めることです。
ここで、2章で張った伏線が回収されます。
- DDD → 実装コードの構造・命名を業務の言葉に揃える(使う場合。複雑なドメインで効く)
- BDD → spec の受け入れ基準を Gherkin で具体例に固定する
- TDD → 出来上がったものが仕様どおりか検証する
DDD は必須ではありません。単純なシステムなら DDD を省き、spec → Gherkin → 実装 → テスト だけでも SDD は回ります。「あるものを束ねる」のが SDD なので、現場の状況に応じて部品を足し引きできるのが強みです。
SDD は TDD/BDD/DDD を否定しません。むしろ、それらを「仕様を中心に束ねる器」です。
5. なぜ AI駆動だと SDD なのか
人間だけで開発していた時代、仕様の明確さは「あると望ましい」程度でした。命名が雑でも、人間が背景知識で補完できたからです。AI が加わると、これが前提条件に格上げされます。理由は3つです。
① AIは「文脈」ではなく「言葉」から推論する
人間は updateStatus(1) という曖昧な関数名でも「たぶん注文の確定だな」と補完できます。AI にはその場の暗黙知がありません。コードに書かれた言葉そのものが頼りです。仕様(ユビキタス言語)が明確なほど、AI は意図を正しく汲み取れます。
② 振る舞いが「AIへの指示書」になる
Given / When / Then は、人間が読める仕様であると同時に、AIへの精密な指示になります。曖昧な日本語で頼むより、振る舞いを具体例で固定して渡すほうが、生成結果がブレません。
③ 振る舞いが「検証の番人」になる
AI は平気で間違えます。だから「速く生成して、速く検証して、間違いを弾く」体制が要ります。Gherkin に対応するテストがあれば、AI の生成物が仕様どおりかを機械的に検証できます。
つまり SDD は、「人間は仕様(何を・なぜ)を握り、実装はAIに任せ、振る舞いで検証する」という分業を成立させます。これが「AIならSDD」の正体です。
6. よくある誤解:Gherkin はテストツールなのか?
最後に、初学者が必ず混乱するポイントを整理します。「Gherkin を書いたら、それがそのままテストになるの?」という疑問です。実は、ここには2つの流派があります。
流派A:Gherkin をそのまま実行する(behave / Cucumber 方式)
.feature に加えて「ステップ定義」という接着剤を書き、behave などのツールで Gherkin 自体を実行可能テストとして走らせます。
流派B:Gherkin は設計・指示に使い、テストは pytest で書く
.feature は「何を作るか」を人間とAIが理解するための仕様・指示書として使い、実際のテストは pytest で普通に書きます。両者は機械的には繋がっておらず、「同じ振る舞いを満たすように対応させる」のは人間とAIの責任です。
# 流派B:接着剤なしで、pytestを直接書く
def test_対応外はデフォルト英語():
assert greet(99) == "Hello, World!"
AI駆動開発では、流派B が主流です。
理由はシンプルで、流派Aの「ステップ定義」という接着剤が純粋に保守の重荷になるからです。pytest ならテストを直接書け、AI にも生成させやすい。Gherkin はコードとテストを書くための"入力"であって、テスト実行エンジンそのものではない —— この感覚を持っておくと、SDD の構成がスッと理解できます。
7. まとめ:比較一覧と、AIならSDDの結論
最後に全体を一覧表で整理します。
| 手法 | 何を起点にするか | 主に書くもの | SDDの中での役割 | 単独でAI駆動に十分か |
|---|---|---|---|---|
| TDD | テスト | テストコード | 実装の正しさを固める | △ 仕様の曖昧さは埋まらない |
| DDD | ドメイン | モデル・命名 | 実装コードを業務の言葉に揃える(複雑なドメイン向け) | △ 検証の仕組みがない |
| BDD | 振る舞い | Gherkin | 受け入れ基準を業務語で固定 | △ 設計全体は導けない |
| SDD | 仕様 | spec.md(+上記すべて) | 全部を束ねる器 | ⭕️ |
「単独でAI駆動に十分か」の列を見ると、TDD・BDD・DDD はそれぞれ一部しかカバーしていないことが分かります。どれも優れた手法ですが、単独では「仕様の明確化」「業務語彙」「振る舞いの固定」「検証」のどれかが欠ける。
**SDD は、これらを否定するのではなく、仕様を中心に束ねます。**だからこそ、AI に安全に実装を任せるための器として機能する —— これが「AIを使うなら SDD」の結論です。
- 仕様(spec) で「何を・なぜ」を握る(人間の仕事)
- 振る舞い(Gherkin) で具体例に固定し、AIへの指示&検証の番人にする
- 実装 は AI に任せる
- テスト(pytest) で仕様どおりか検証する
この型が腹落ちすると、AI駆動開発の景色がガラッと変わります。
次回:実践編
概念が分かったら、次は手を動かす番です。実践編では、この Hello world を題材に、BE(Flask API)と FE(画面)を分けたモノレポを実際に作り、pytest と Playwright で「仕様 → 実装 → 検証」を一周させます。「番人」が実際にバグを捕まえる様子も体感できます。
実践編へのリンクはこちら
【実践編】SDDを手で動かす:BE/FE分離のモノレポを仕様→実装→検証で一周する #Python - Qiita
この記事は、私が理解を深めた過程を再構成したものです。誤りや補足があれば、コメントで指摘いただけると嬉しいです。