EY-Office ブログ

遅ればせながらSpec Driven Developmentに入門してみた (2)

先週の遅ればせながらSpec Driven Developmentに入門してみた (1)続きです。

先週は、AI(Claude + cc-sdd)を使ってみた記録と感想でした。しかも作成された仕様等はそのまま実行しましたが今回は自分の思うように仕様を変更してどうなるかを見てみました。

SpecDrivenDevelopment Bing Image Creatorが生成した画像を使っています

まずはcc-sddのお勉強

やはりツールやフレームワークを使うには、そのツール・フレームワークの設計思想や原理を知っておいた方が良いと思います。今後のブログではcc-sddの動作原理等に付いて調べて書きたいと思いますが、今回は AWSの強力なエージェント型IDE “Kiro”のしくみを詳しく解説する(翻訳) という良い記事を発見したので読んでみました。

cc-sddKiroにインスパイアされたソフトウェアでKiroの仕様書も使えるのでKiroの知識は使えるはずです。

この記事は、やや長めですがcc-sddを使う人は絶対に読んだ方が良い記事です。目次を掲載しておきます。

  • 要点
  • パラダイムシフト: 「命令型開発」から「意図駆動開発」へ
  • Kiroのシステムアーキテクチャ
    • 意図層: ユーザー入力を解析する
    • 知識層: 意思決定に必要なコンテキストを提供する
      • Spec(構造化された意図)
      • Vibeコーディングやターミナル入力(構造化されていない意図)
    • 知識層: 意思決定に必要なコンテキストを提供する
      • コードベースのインデックス作成(短期記憶、プロジェクト内部の知識)
      • ステアリング(長期記憶、プロジェクトのガイダンス原則)
    • 実行層: 意図を操作に変換する
      • オートパイロット(自律的なタスクエクゼキュータ)
      • フック(イベントでトリガーされるエクゼキュータ)
    • 監視層: 人間とマシンがコラボするためのインターフェイス

・・・以下省略・・・

今回の作成記録

先週と同じくワイン販売のECサイトを作ります。

$ mkdir cc-sdd-trial-2
$ cd cc-sdd-trial-2
$ npx npx cc-sdd@latest --claude --lang ja
$ claude

要件定義

プロジェクト作成、要件定義は同じです。

❯ /kiro:spec-init ワイン販売のECサイト
  ....
> /kiro:spec-requirements wine-ec-site

出来た要件定義は以下でした。

- 商品カタログ閲覧: ワイン一覧の表示、検索、フィルタリング(種類・産地・価格帯・品種)、ソート、商品詳細ページの表示
- ショッピングカート: カートへの追加・数量変更・削除、合計金額の計算、在庫不足時のエラー表示
- ユーザー認証・アカウント管理: 新規登録、ログイン/ログアウト、マイページ(注文履歴・配送先)、パスワードリセット
- 注文・決済処理: チェックアウトフロー、決済処理、注文確認メール、エラーハンドリング、重複送信防止
- 年齢確認 初回アクセス時の年齢確認、20歳未満のアクセス拒否、同意状態の保持(酒類販売法令遵守)
- 在庫管理: 在庫数のリアルタイム管理、注文時の自動減算、品切れ時のカート追加無効化
- 管理画面: ダッシュボード(売上・注文・在庫アラート)、商品登録、注文ステータス管理・メール通知
- レスポンシブデザイン・アクセシビリティ: マルチデバイス対応、主要ブラウザ対応、WCAG 2.1 AA準拠

先週の要件には在庫管理や管理画面などが無かったので、今回追加してみようと思っていたのですが、先回りされました! 😲
同じ入力に対して同じ結果を返すとは限らないがAIですね。

そこで、開発を順調に進めるため画像を含む100件程度のテストデータの準備を要件に追加してください と指示しました。

requirements.mdには以下が追加されました。

### Requirement 9: テストデータの準備
**Objective:** As a 開発者, I want 画像を含む約100件のワイン商品テストデータを用意したい, so that 開発・テスト・デモ時に実際の利用状況に近い環境で動作確認ができる

#### Acceptance Criteria
1. The シードスクリプト shall 約100件のワイン商品テストデータを一括投入する機能を提供する
2. The テストデータ shall 各商品に対して商品名・価格・説明・産地・ブドウ品種・ヴィンテージ・容量・アルコール度数・在庫数・商品画像を含む
3. The テストデータ shall ワインの種類(赤・白・ロゼ・スパークリング)および複数の産地(フランス・イタリア・日本・チリ・オーストラリア等)にわたる多様なデータを含む
4. The テストデータ shall 各商品に1枚以上の商品画像(プレースホルダまたはサンプル画像)を関連付ける
5. The テストデータ shall 価格帯が幅広く分布し(1,000円〜50,000円程度)、フィルタ・ソート機能の検証に適した構成とする
6. When シードスクリプトを実行した時, the シードスクリプト shall 冪等に動作し、既存データを重複なく再投入できる

設計

設計 /kiro:spec-design wine-ec-siteを行うと先週と同様にNext.jsのReact Server Functionを使うアーキテクチャで設計しました。

今回は以下の指示を行いました。フロントエンドはReact、バックエンドはFastAPI(Python)にしました。

Architecture, Technology Stackですが以下に変更してください

- FrontendはReact
  - ビルドツールはViteを使用
  - ルーティングはTanStack Routerを使用
  - バックエンドとの通信はTanStack Queryを使用
- BackendはPython FastAPI
  - ORMはSQLAlchemy ORMを使用
  - 開発環境はDockerを使用
- データベースはPostgreSQLを使用
  - 開発環境はDockerを使用

Technology Stack
LayerChoice / VersionRole in FeatureNotes
FrontendReact 19 + Vite 6SPA UI 描画・ビルドHMR による高速開発
RoutingTanStack Router v1型安全なファイルベースルーティング自動コード分割、ローダー API
Data FetchingTanStack Query v5サーバー状態管理・キャッシュuseQuery / useMutation
UIshadcn/ui + Tailwind CSS v4UIコンポーネント + スタイリングRadix UI 統合パッケージ (2026-02)
BackendPython 3.12 + FastAPIREST API・ビジネスロジックPydantic v2 バリデーション、自動 OpenAPI 生成
ORMSQLAlchemy 2.0 (async)非同期データアクセス・モデル定義asyncpg ドライバ
MigrationAlembicDB スキーママイグレーションasync 対応
DatabasePostgreSQL 16データ永続化Docker コンテナで実行
AuthenticationJWT (PyJWT + passlib)トークンベース認証アクセストークン + httpOnly Cookie リフレッシュトークン
PaymentStripe (stripe Python SDK + @stripe/stripe-js)決済処理Checkout Session + Webhook
ImageFastAPI StaticFiles + ローカルストレージ (初期)画像配信本番時にオブジェクトストレージ移行
Testingpytest + Playwrightバックエンドユニット + E2E テストStripe テストモード活用
Dev EnvironmentDocker Compose開発環境統一FastAPI + PostgreSQL + Vite dev server
RuntimeuvicornASGI サーバー—reload で開発時ホットリロード

指示通りのアーキテクチャになりました。

タスク分解

/kiro:spec-tasks wine-ec-site -yを実行すると以下のようなタスクが出来ました(タスクの3階層以とPhase4以降は2階層以下も省略しました)。

### Phase 1: プロジェクト基盤構築

- [ ] 1. プロジェクト基盤のセットアップ
- [ ] 1.1 (P) バックエンド開発環境の構築
- [ ] 1.2 (P) フロントエンド開発環境の構築
- [ ] 1.3 Docker Compose による統合開発環境の整備

## Phase 2: データモデルと認証基盤

- [ ] 2. データベーススキーマと認証システムの構築
- [ ] 2.1 データベースモデルの定義とマイグレーション
- [ ] 2.2 JWT 認証サービスの実装
- [ ] 2.3 パスワードリセット機能の実装

### Phase 3: 商品カタログ機能

- [ ] 3. 商品カタログシステムの構築
- [ ] 3.1 商品サービスの実装
- [ ] 3.2 (P) 商品一覧ページの実装
- [ ] 3.3 (P) 商品詳細ページの実装

### Phase 4: ショッピングカート機能
### Phase 5: 注文・決済機能
### Phase 6: 年齢確認機能
### Phase 7: 管理画面機能
### Phase 8: テストデータ準備
### Phase 9: フロントエンド認証統合
### Phase 10: 統合テストと最終調整

実装 Phase1

/kiro:spec-impl wine-ec-site 1Phase1: プロジェクト基盤構築を実行しました、Dockerを使った実行環境の構築です。

作成されるコンテナーは以下です。

  • db: PostgreSQLのデータベースサーバー
  • backend: バックエンド
    • Python言語
    • FastAPI APIサーバー
    • SQLAlchemy ORM
    • uvicorn 開発サーバー
  • frontend: フロントエンド
    • React フレームワーク
    • Vite 開発環境
    • Tanstack Router/Query ライブラリー
    • shadcn/ui, Tailwind CSS CSSライブラリー
  • mailhog: 開発用メールサーバー

終了後 docker compose build; docker compose up を実行するとBackendのところでエラーが発生しました。ここで、すったもんだしました。😅

  1. エラーメッセージを教えてClaudeに対応してと依頼
    • Dockerfileを修正
  2. しかし、同じエラーが発生。
  3. 再度Claudeに依頼
    • 「Docker のビルドキャッシュが原因の可能性があります」と言われキャッシュクリア手順を表示
  4. しかし、同じエラーが発生
  5. 再度Claudeに依頼
    • pyproject.tomlを修正
  6. しかし、同じエラーが発生
  7. 再度Claudeに依頼
    • 「直接 backend ディレクトリでビルドを試してみてください」と言われる
  8. しかし、同じエラーが発生
  9. 再度Claudeに依頼
    • 「このコマンドの出力を教えてください」と言われる
  10. 実行し、出力(ログ)を教える
  11. Claudeが問題を解決しました
    • エラーが変わりました。今度は hatchling がパッケージの場所を見つけられない問題です。pyproject.toml にビルド設定を追加します

実は6., 8.でのエラー表示が変わっていた事に私が気づかず間違った指示をしていたようです。

PostgreSQLが正しく日本語ロケールが設定できるか確認し、データベースのDockerファイルをマニュアルで変更しました。 設計で以下のように指定するべきでしたね 😅

- データベースはPostgreSQLを使用
  - 開発環境はDockerを使用
  - 日本語が正しく使えるエンコーディング、ロケールを設定

実装 Phase2

データモデルと認証基盤が作られ、最後に指示の出ていた以下のマイグレーション実行を行いました。

$ docker compose exec backend alembic revision --autogenerate -m "Initial models" 
$ docker compose exec backend alembic upgrade head 

実装 Phase3, Phase 8

商品カタログ機能、テストデータ準備を実装してもらい、最後に指示の出ていた以下のシードスクリプトの実行を行いまました。

$ docker compose exec backend python -m app.seed

ここでエラーが発生したので、Claudeに指示すると簡単に解決しました。
原因: bcrypt のバージョン互換性の問題です。passlib が新しい bcrypt 4.1+ と互換性がありません。pyproject.toml で bcrypt のバージョンを固定します。

ここでブラウザーからフロントエンドをアクセスするとInternal Server Errorが発生しています。 コンソールには以下のエラーが表示されていました。

wine-ec-frontend  | 7:31:01 AM [vite] http proxy error: /api/v1/products/filters
wine-ec-frontend  | AggregateError [ECONNREFUSED]:
wine-ec-frontend  |     at internalConnectMultiple (node:net:1134:18)
wine-ec-frontend  |     at afterConnectMultiple (node:net:1715:7)

Claudeに指示すると、以下のようなコード修正を行ってくれましたが、解決しません!

const apiTarget = process.env.DOCKER_ENV === 'true'
  ? 'http://backend:8000'
  : 'http://localhost:8000'

export default defineConfig({
  server: {
    proxy: {
      '/api': { target: apiTarget, changeOrigin: true },
      '/static': { target: apiTarget, changeOrigin: true },
    },
  },
})

このコードを見ていてDOCKER_ENVなんてあるの?と疑問になり調べてみると無さそうです。docker-compse.yamlに追加するのかなと考えつつ、const apiTarget = NODE_ENV === 'development'に書き変え解決しました。

そしてトップ画面が表示されました。🎉

まとめ

cc-sddで生成された要件定義や設計書に対して変更や追加の依頼を行うと定義や設計が変更され、それに対応したコードが生成されるSDD(Spec-Driven Development)がちゃんと機能している事が判りました。素晴らしいですね❗

やはり環境構築は難しいですね。これは人間が行っても色々と問題が起きるのでしかたないのかもしれません・・・
その際に、AIにエラー等を伝えるのはログを人間が見て適当に指示するより、毎回コピペした方が良さそうです。

実装段階になってから、要件・設計段階の抜けに気が付いた場合どうしたら良いのかな? AIが実装はやってくれるので要件・設計段階に戻るのが良さそうだけど、Claude CodeをProプランで使っていると利用制限に直ぐに達しそうですね。😅

また、今回要件で依頼した画像を含む100件程度のテストデータの準備のうち画像が完全に無視されていました。後で要件定義の詳細にも画像に付いては全く書かれていませんでした。SDDでは要件・設計された仕様書の確認が重要ですね! これも人間が行うソフトウェア開発でも同じでしたね。

まだ続きます・・・

まだステアリングを使っていませんが、新規開発でも使った方が良いのではと思っています。今回の設計ではアーキテクチャの変更を指示で行いましたが、ステアリングに記述した方が良いかも知れません。

- about -

EY-Office代表取締役
・プログラマー
吉田裕美の
開発者向けブログ