2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

仕様駆動開発(SDD)が AI コーディングの品質を底上げする — OpenSpec で学ぶ3層モデル

2
Posted at

はじめに

最近の AI コーディングをやっていて、こんな感覚はないだろうか。

  • AI に「いい感じに作って」と言うと、技術的には正しいが意図とズレたコードが返ってくる
  • レビューで「いや、こうじゃなくて……」と差し戻し続ける
  • 同じプロジェクト内で、AI が出力するコードの方針が日によってブレる

これらの問題は、コード以前に「仕様」が言語化されていない ことに起因することが多い。

ここで効くのが、最近名前を聞くようになってきた 仕様駆動開発(Specification-Driven Development, SDD) だ。OpenSpec などのフレームワークも整理されてきており、AI コーディング時代の品質保証手法として定着しつつある。

本記事では、SDD を 3 層モデルで整理し、AI コーディングの現場で実装するときの設計原則を共有する。

SDD の3層モデル

SDD を実プロジェクトに導入するとき、以下の 3 層で仕様を分けて管理するのが扱いやすい。

┌─────────────────────────┐
│ Layer 3: 受け入れ仕様(Acceptance)   │ ← 検証可能・テストに変換できる
├─────────────────────────┤
│ Layer 2: 振る舞い仕様(Behavior)     │ ← Given/When/Then で書ける
├─────────────────────────┤
│ Layer 1: ドメイン語彙(Vocabulary)   │ ← 用語と概念の定義
└─────────────────────────┘

Layer 1: ドメイン語彙(Vocabulary)

最下層は 用語と概念の定義 だ。

例えば EC サイトを作るなら、こんな用語を定義する。

# domain.yml
vocabulary:
  product:
    description: 顧客が購入できる単一のアイテム
    states:
      - draft     # 編集中、購入不可
      - listed    # 公開中、購入可
      - archived  # 過去販売、購入不可
  order:
    description: 顧客が複数 product を1回でまとめて購入した単位
    states:
      - pending
      - paid
      - fulfilled
      - cancelled

ここを最初に固めておくと、AI に渡すコンテキストの「言葉」が揃う。

よくある失敗: productitemordercart を曖昧に使い分けてしまうと、AI が両方のパターンで出力してくる。気付いた頃には DB スキーマもコードもブレている。

Layer 2: 振る舞い仕様(Behavior)

中間層は Given / When / Then で書ける振る舞い

## US-021: 在庫切れ商品を購入できない

Given: 商品 X の在庫数が 0
When:  顧客が商品 X をカートに入れて購入ボタンを押す
Then:  「在庫切れです」エラーが返り、order は作成されない

この粒度の仕様を AI に渡すと、実装方針がぐっと安定する。AI は「在庫切れ判定はどのタイミングでやるか(カート追加時 / 購入確定時)」を勝手に決めなくて済むからだ。

Layer 3: 受け入れ仕様(Acceptance)

最上層は 検証可能な受け入れ条件

振る舞い仕様をそのまま e2e テスト or 結合テストに変換できる粒度にする。

// __tests__/order.acceptance.test.ts
describe("US-021: 在庫切れ商品を購入できない", () => {
  it("在庫0の商品をカートに追加→購入確定で OutOfStockError", async () => {
    const product = await fixture.createProduct({ stock: 0 });
    const customer = await fixture.createCustomer();
    await expect(
      placeOrder({ customer, items: [{ product, qty: 1 }] })
    ).rejects.toThrow(OutOfStockError);
  });
});

ここまで来ると、AI に対して「この受け入れテストを通すように実装して」という依頼が可能になる。

なぜ AI コーディング時代に SDD が効くのか

3 つの理由がある。

理由①: AI への入力の質が上がる

AI コーディングの精度は、入力プロンプトの質に強く依存 する。「いい感じに作って」では揺らぐが、Layer 2 の振る舞い仕様+ Layer 1 の語彙を渡すと、出力は劇的に安定する。

理由②: AI 出力の評価が機械化できる

Layer 3 の受け入れ仕様を最初に書いておくと、AI が出した実装が「合っているかどうか」をテスト実行で判定できる。レビューで毎回「これ動くんですか?」と聞かなくて済む。

理由③: 仕様の変更履歴が、AI が読めるドキュメントになる

仕様を Git で管理しておけば、AI に「過去にこういう経緯で archived 状態を追加した」というコンテキストを渡せる。複数ターンに渡る開発で、AI が過去の決定を忘れずに済む。

実装するときの設計原則

SDD を実プロジェクトに導入するとき、以下の 4 つを守ると失敗しにくい。

原則1: 3 層を1ファイルに混ぜない

ドメイン語彙・振る舞い仕様・受け入れ仕様は 別のファイル / 別のディレクトリ で管理する。

spec/
├── vocabulary/
│   ├── product.yml
│   └── order.yml
├── behaviors/
│   ├── US-001-product-listing.md
│   ├── US-021-out-of-stock.md
│   └── ...
└── acceptance/
    ├── product.acceptance.test.ts
    └── order.acceptance.test.ts

混ぜると、AI への入力で「どの層の話をしているか」がブレる。

原則2: 振る舞い仕様 1 つ = テスト 1 つ

US-021 のような 1 つの振る舞い仕様には、1 つ以上の受け入れテストを必ず紐付ける。「仕様はあるけどテストがない」状態は、SDD の最大のアンチパターン。

原則3: AI 用のコンテキスト集約ファイルを置く

AI(Claude Code など)に渡す統合コンテキストファイルを spec/CONTEXT.md のようなパスに置く。Layer 1 の語彙を要約しつつ、現在進行中の振る舞い仕様へのリンクを並べておくと、毎回 AI への説明コストが減る。

原則4: 仕様変更は PR で議論する

コード変更だけ PR で議論しがちだが、SDD では 仕様変更の PR が一級市民。spec/ ディレクトリの変更は、コード変更とは別 PR にして、レビュアーは仕様の妥当性を議論する。

どこから始めるか

既存プロジェクトに SDD を後付けするなら、こう進めるのがおすすめだ。

  1. まず Layer 1(語彙)を 1 ファイル書く。プロジェクト内で頻出する 10 個の名詞を定義するだけでOK
  2. 次に Layer 3(受け入れテスト)を 3 件書く。重要機能の e2e/結合テストでよい
  3. 最後に Layer 2(振る舞い仕様)を、新規機能から書き始める

上から書こうとすると挫折するので、「下から始めて 1〜2 ヶ月で 3 層揃える」が現実的だ。

まとめ

SDD は新しい概念ではないが、AI コーディング時代に再評価されるべき手法だ。

  • Layer 1(語彙)で AI の言葉を揃える
  • Layer 2(振る舞い仕様)で AI の判断を安定させる
  • Layer 3(受け入れテスト)で AI の出力を検証できる

この 3 層を揃えるだけで、AI コーディングの品質は底上げされる。


未経験者向けの講座を運営しています

未経験から Next.js + Supabase + Claude Code で Webアプリを公開するまで を、全20セッションで体系化した教材です。Claude Code を学習パートナーにする CLAUDE.md / Skills 設計までセットで含みます。

※ Qiita 読者の方には易しすぎる内容なので、初心者の知り合いへの紹介や社内研修の参考としてどうぞ。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?