AIシリーズ面接16:良いSpec Codingとはどのようなものか?
良い Spec Coding(仕様駆動プログラミング)の核心は、「曖昧なアイデア」を「正確で、検証可能で、実行可能な契約」に変えることです。単なるドキュメント作成ではなく、人とAI(または人と人)の間の曖昧さのないコミュニケーション言語を確立することです。以下では、仕様の内容構成、記述原則、AIとの協働フロー、品質検証の4つの観点から、良いSpecのあり方を示します。
一、仕様ドキュメントの標準構造(機能モジュールを例に)
| セクション | 必須項目 | 例 |
|---|---|---|
| 1. 目的と範囲 | 何をするかを一文で記述し、何をしないかを明確にする | 「ユーザー登録APIを実装するが、メール検証は含まない」 |
| 2. 入出力契約 | データ構造、型、必須/オプションフィールド、サンプル値 | POST /register リクエストボディ {email: string, password: string}、レスポンス 201 または 400(エラーコード含む) |
| 3. 振る舞いとロジック | ビジネスルール、境界条件、状態遷移 | 「パスワード長は8〜20文字で、少なくとも1つの数字を含むこと。メールアドレスが既に存在する場合は 409 を返す」 |
| 4. エラーハンドリング | 全ての異常シナリオと対応するエラーコード/メッセージ | 「データベース接続失敗 → 503 を返し、スタックトレースを公開しない」 |
| 5. 非機能要件 | パフォーマンス(応答時間 < 200ms)、セキュリティ(パラメータ化クエリ)、ログ、可観測性 | 「全てのSQLはプリコンパイルを使用すること。email はログに記録するが password は記録しない」 |
| 6. テストケース(重要) | 少なくとも3つの代表的な入力 + 2つの境界/異常入力、期待出力を明記 | 下記表参照 |
| 7. 依存関係と制約 | 使用するライブラリ、バージョン、環境変数 | 「Python 3.10+、FastAPI、環境変数 DB_URL」 |
テストケースの例(specに内包)
| シナリオ | 入力 | 期待出力 |
|---|---|---|
| 正常登録 | email: a@b.com, pwd: Pass1234 |
201、user_id を返す |
| パスワード短すぎ | pwd: Ab1 |
400、エラーコード WEAK_PASSWORD |
| メールアドレス既存 | 同上 email | 409、エラーコード EMAIL_EXISTS |
良いSpecはまずテストケースを書くべきです。なぜなら、AIがそれらから直接ユニットテストを生成し、完了後に自動検証できるからです。
二、Spec記述の核心原則(SMART変種)
| 原則 | 説明 | 悪い例 |
|---|---|---|
| 正確(Precise) | 具体的な数値、型、ブール条件を使用し、「できるだけ」「通常」を避ける | ❌ 「パスワードは十分に安全であること」→ ✅ 「パスワードは最低8文字で、大文字、小文字、数字を含むこと」 |
| 検証可能(Verifiable) | 各要件が自動テストまたは手動チェックで合格/不合格を判定できること | ❌ 「コードはエレガントであること」→ ✅ 「関数の循環的複雑度 ≤ 10、重複コードブロックなし」 |
| 曖昧さなし(Unambiguous) | 同じ用語をドキュメント全体で一貫して使用し、必要に応じて用語集を提供する | ❌ 「ユーザーが存在しない場合、エラーを返す」→ ✅ 「ユーザーが存在しない → 404 と {code: 'USER_NOT_FOUND'} を返す」 |
| 完全(Complete) | ハッピーパス、全ての異常パス、非機能要件をカバーする | ❌ 成功シナリオのみ記述 → ✅ データベースタイムアウト、権限不足などを含める |
| アトミック(Atomic) | 1つのspecは、独立してデリバリー可能な1つの機能を記述する(AIが一度で完了しやすいように) | ❌ 1つのspecで「決済システム全体」を書く → ✅ 「支払いオーダー生成」「コールバック署名検証」「返金」に分割 |
三、AIとの協働におけるSpec Codingフロー
- 人間がspecを書く(上記の構造、特にテストケースと関数シグネチャをしっかり書く)。
- specを一度にAIに与える(対話的な要件追加は避け、ゆらぎ汚染を防ぐ)。
- AIがコード+ユニットテストを出力する(AIはspec中のテストケースに従って実行可能なテストを生成する必要がある)。
- テストを実行する:全て合格なら次のステップへ。不合格ならspecを修正するか、直接コードを修正する(この場合、小さなループに入るが、変更は記録する)。
- 人間によるレビュー:spec外の機能が導入されていないか(スコープクリープ)、セキュリティ/パフォーマンスを確認する。
- 固定化:specドキュメントと最終コードを一緒にリポジトリにコミットし、永続的なドキュメントとする。
重要な実践:Specのコード化——
spec.md+test_spec.pyを使用し、テストファイルはspecのサンプルから直接生成する。これにより、後でコードを変更する際にテストを実行するだけでspecが破壊されていないか検証できる。
四、良いSpecがもたらす効果(受け入れ基準として)
- 決定性:同じspecを異なるAI(または異なる人)に与えても、類似した実装が得られる。
- テスト容易性:コードを書き終えたらすぐに90%の正当性を自動検証できる。
- 保守性:半年後に誰がspecを見ても、当初の設計意図を理解できる。
- 低コミュニケーションコスト:チームの議論はspecについてのみ行い、具体的なコード行については議論しない。
- セキュリティ/品質の組み込み:セキュリティ要件(例:パラメータ化クエリ)や境界条件がspecに明記され、AIが遵守しなければならない。
五、良いSpecの例(最小版)
# Spec: ユーザー登録API
## 範囲
- email, password を受け付ける
- 確認メールは送信せず、メールアドレスの実在性は確認しない
## 契約
POST /register
Content-Type: application/json
Request: { "email": string, "password": string }
Response 201: { "user_id": string }
Response 400: { "code": "INVALID_PASSWORD" | "INVALID_EMAIL" }
Response 409: { "code": "EMAIL_ALREADY_EXISTS" }
## 振る舞い
- email はRFC 5322基本フォーマット(a@b.c)に準拠すること
- password: 長さ8〜20文字、少なくとも1つの数字と1つの大文字を含む
- bcryptを使用してハッシュ化保存、ソルトコスト10
- データベース保存前にemailの重複を確認 → 重複していれば409
## テストケース(入力 -> 期待ステータスコード+レスポンスフィールド)
| 入力 email | password | 期待 |
|------------|----------|------|
| test@x.com | Pass1234 | 201, user_id が存在 |
| test@x.com | pass | 400, INVALID_PASSWORD |
| bad | Pass1234 | 400, INVALID_EMAIL |
| (既存のメール) | Pass1234 | 409, EMAIL_ALREADY_EXISTS |
## 非機能
- SQLはパラメータ化クエリを使用すること(インジェクション対策)
- ログに登録元IPを記録し、パスワードは記録しない
- 応答時間 95%リクエスト < 100ms (bcrypt除く)
## 依存関係
- Python 3.10+, FastAPI, bcrypt, asyncpg
良いSpec Coding = 人間の「設計判断」を、機械の「テストケース+型シグネチャ+振る舞い制約」として書き下し、AIには実装の充填だけを任せ、人間が常に品質と方向性をコントロールすることです。
评论
暂无已展示的评论。
发表评论(匿名)