概要
Given-When-Then 受け入れ基準
「ちゃんと動くこと」という主観的な受け入れ基準を、前提(Given)・操作(When)・結果(Then)で書けるユーザーストーリー単位に分解する。誰が読んでも同じテスト観点を導ける状態にする。
非機能要件 × エッジケースの先出し
冪等性・タイムゾーン・可用性SLAといった非機能要件と、月末課金・解約時返金・カード失効リトライなどのエッジケースを実装前に洗い出し、優先度(Must/Should)を付ける。
PERT三点見積もり(P50 / P90)
「5人日でできます」という根拠のない一言を、楽観・最頻値・悲観の3値からPERT公式で期待値(P50)とリスクを織り込んだP90を算出する二重見積もりに置き換える。
依存関係マッピング × フェーズドロールアウト
決済ゲートウェイ・クーポン・在庫管理という上流依存を洗い出し、Feature Flagによる社内→1%→10%→100%の段階公開とロールバック基準を事前設計する。
問題
ECサイト MOps チームのシニアエンジニアとして、後輩PdM見習いが作成した「定期購入(サブスクリプション)機能」の要件定義書ドラフトをレビューし、来週の経営会議での着手承認判断に使えるレベルへ再設計することになった。以下の Bad 要件定義書には 7つの問題点が潜んでいる。問題点を全て洗い出し、Good 要件定義書へ再設計してください。
制約・前提条件
- 対象: 既存EC会員向けの「同一商品を毎月/隔月で自動購入」機能
- 決済は既存のクレジットカード決済ゲートウェイ(定期課金APIの提供有無は要確認)を利用する想定
- 既存のクーポンシステム・在庫管理システムとの連携が発生しうる
- エンジニア単価: 80万円/月(20営業日 = 4万円/人日)
- タスク分解済みの3点見積もり(楽観値・最頻値・悲観値、単位: 人日)は以下の通り
| タスク | 楽観値 | 最頻値 | 悲観値 |
|---|---|---|---|
| バックエンド実装(契約作成・課金バッチ・状態管理) | 2 | 5 | 12 |
| フロントエンド実装(登録/解約UI・マイページ表示) | 1.5 | 3 | 6 |
| QA・エッジケーステスト設計 | 1 | 2 | 5 |
| 決済ゲートウェイの定期課金対応可否の調査(外部依存) | 0.5 | 1 | 3 |
悪い要件定義書 (Before)
件名: 定期購入機能 要件定義書(ドラフト)
背景: 競合他社がサブスク機能を出しているので、うちも追加したい。
← 問題④: 6W3Hが欠落(Why はあるがWho/Whichがない)
機能概要:
・ユーザーが定期的に同じ商品を自動購入できるようにする
・支払いは既存のクレジットカード決済を使う
・解約もできるようにする
← 問題②③: 非機能要件・エッジケースが一切書かれていない
← 問題⑥: 決済ゲートウェイ等の依存関係の記載がない
受け入れ基準: ちゃんと動くこと。エラーが出ないこと。
← 問題①: 検証不能な主観的表現のみ
見積もり: バックエンド3人日、フロントエンド2人日、合計5人日でできます。
← 問題⑤: 根拠のない一言見積もり(不確実性が反映されていない)
← 問題⑦: リリース計画・ロールバック手順が皆無
以上、来週の経営会議で承認をお願いします。
ヒント(段階的開示)
ヒント1 — 方向性
ヒント2 — アプローチ
- 問題①: 「ちゃんと動くこと」→ Given-When-Then形式でテスト可能な受け入れ基準に分解する
- 問題②: 非機能要件(冪等性・タイムゾーン・可用性SLA・監査ログ・性能)を表形式で明示する
- 問題③: エッジケース(月末課金日調整・解約時返金・クーポン重複・カード失効リトライ・在庫切れ・タイムゾーン)を列挙し、Must/Shouldで優先度を付ける
- 問題④: 6W3Hで整理し、検討した代替案(Which: 内製 vs 決済ゲートウェイのサブスクAPI活用)も明記する
- 問題⑤: 「3人日でできます」という当てずっぽうではなく、タスク分解 + PERT三点見積もり(楽観・最頻値・悲観)で期待値(P50)とリスクを織り込んだP90を算出する
- 問題⑥: 決済ゲートウェイ・クーポンシステム・在庫管理システムなど、着手前に確認すべき依存関係を洗い出す
- 問題⑦: 一斉公開ではなく、Feature Flagによる段階的ロールアウトとロールバック手順を設計する
ヒント3 — 誘導
【PERT三点見積もり】
期待値(P50) = (楽観 + 4×最頻値 + 悲観) / 6
標準偏差 = (悲観 - 楽観) / 6
タスクごとに算出し、期待値は単純合算。
複数タスクが独立と仮定した場合の合成標準偏差 = sqrt(Σ 各タスクの分散)
【P90見積もり(経営向けコミット値)】
P90 = 期待値(P50) + z(90%,片側) × 合成標準偏差
z ≈ 1.2816
【過小見積もりのコスト差】
Bad予算 = 5人日 × 4万円
P50実コスト = 期待値人日 × 4万円
P90コミット = P90人日 × 4万円
問題点分析(7点)
| # | 問題点 | 分類 | 改善方法 |
|---|---|---|---|
| 1 | 受け入れ基準が主観的でテスト不能 | 検証可能性 | Given-When-Thenでユーザーストーリー単位に分解 |
| 2 | 非機能要件が皆無 | 品質要件 | 冪等性/タイムゾーン/可用性/監査ログ/性能を表で明示 |
| 3 | エッジケースが未列挙 | 品質要件 | 優先度(Must/Should)付きで6件を洗い出す |
| 4 | 6W3Hが欠落 | 意思決定 | Who/Which等を含め整理し代替案検討の跡を残す |
| 5 | 見積もりが根拠のない一言 | 見積もり | PERT三点見積もりでP50(期待値)/P90(コミット値)を算出 |
| 6 | 依存関係・前提システムの記載がない | 依存関係 | 決済ゲートウェイ/クーポン/在庫システムをマッピング |
| 7 | リリース計画・ロールバック手順がない | リリース設計 | Feature Flagによる段階的ロールアウト計画 |
見積もり乖離と依存関係・ロールアウトの可視化
模範解答
# 修正①: Given-When-Thenでユーザーストーリー単位に受け入れ基準を分解
## Story 1: 定期購入の登録
Given: 会員がログイン済みで、対象商品の詳細ページを閲覧している
When: 「定期購入で購入」を選択し、頻度(毎月/隔月)を指定して確定する
Then: 定期購入契約が作成され、次回課金日がマイページに表示される
## Story 2: 定期課金の実行
Given: 定期購入契約が有効で、本日が次回課金日である
When: 課金バッチが実行される
Then: 登録済みカードに課金される。成功時は次回課金日が1ヶ月後
(または隔月後)に更新される。失敗時は冪等性キー付きで
最大3回、指数バックオフでリトライされ、二重課金は発生しない
# ← 修正②(冪等性)がここでテスト可能な基準として現れる
## Story 3: 解約
Given: 会員が有効な定期購入契約を保有している
When: マイページから「定期購入を解約」を選択し確認する
Then: 契約は次回課金日の前日までにキャンセルされ、以降の課金は
発生しない。既に課金済みの当月分は返金対象外である旨が
解約前に画面表示される
# ← 修正③(エッジケース②: 解約時返金)がここで基準化される
## Story 4: 課金失敗時のエスカレーション
Given: 定期課金が3回のリトライすべてに失敗した
When: 最終リトライが失敗する
Then: 契約は自動的に一時停止(pause)状態になり、会員にメール通知、
CSチームのダッシュボードにアラートが表示される
# ← 修正④(6W3H: Who=CSチーム→オンコール)がここで運用に接続する
修正②: 非機能要件表
| 項目 | 要件 |
|---|---|
| 可用性 | 定期課金バッチのSLA 99.9%(月次ローリング) |
| 冪等性 | 決済APIリクエストに Idempotency-Key を付与し、リトライ時の二重課金を防止 |
| タイムゾーン | 課金日時は内部でUTC基準管理、会員向け表示のみJSTにローカライズ |
| 監査ログ | 課金・解約・一時停止の全操作を「誰が/いつ/何を」で監査ログに記録 |
| 性能 | 月初の一斉課金バッチは対象契約数によらず2時間以内に完了すること |
修正③: エッジケース一覧(優先度付き)
| # | エッジケース | 優先度 |
|---|---|---|
| 1 | 契約日が31日で翌月に31日が存在しない場合の課金日調整(月末最終日に丸める) | Must |
| 2 | 解約タイミングと日割り返金・未使用分の扱い | Must |
| 3 | カード期限切れ・与信エラー時のリトライポリシーとユーザー通知 | Must |
| 4 | タイムゾーンをまたぐ課金時刻の一貫性(UTC統一) | Must |
| 5 | クーポン・割引の定期購入への重複適用可否 | Should |
| 6 | 対象商品が在庫切れ・販売終了になった場合の契約の扱い | Should |
| 項目 | 内容 |
|---|---|
| Who | 対象は既存EC会員。決済失敗時の一次対応はCSチーム、3回リトライ失敗後はエンジニアオンコールへエスカレーション |
| What | 定期購入(サブスクリプション)機能 |
| When | Q3中リリース。初回課金は登録翌月1日 |
| Where | 既存ECサイトのチェックアウトフロー拡張 + 決済ゲートウェイ連携部分 |
| Why | 競合対応 + リピート購入自動化によるLTV向上 |
| Which | 案A: 定期課金ロジックを内製 / 案B: 決済ゲートウェイが提供するサブスクリプションAPIを活用(採用: 案B。冪等性・リトライ制御を自前実装せず開発工数を圧縮できるため) |
| How | Feature Flagによる段階的ロールアウト |
| How many | 初期対象は主力商品カテゴリ2つ、初期対象ユーザーは全会員の1%から開始 |
| How much | PERT三点見積もり参照(P50 12.5人日 / P90 15.1人日) |
# 修正⑤: PERT三点見積もり
# 期待値 = (楽観 + 4×最頻値 + 悲観) / 6 / 標準偏差 = (悲観 - 楽観) / 6
バックエンド実装:
期待値 = (2 + 4×5 + 12) / 6 = 34/6 ≈ 5.67人日
標準偏差 = (12-2)/6 ≈ 1.67
フロントエンド実装:
期待値 = (1.5 + 4×3 + 6) / 6 = 19.5/6 = 3.25人日
標準偏差 = (6-1.5)/6 = 0.75
QA・エッジケーステスト:
期待値 = (1 + 4×2 + 5) / 6 = 14/6 ≈ 2.33人日
標準偏差 = (5-1)/6 ≈ 0.67
決済ゲートウェイ調査(外部依存):
期待値 = (0.5 + 4×1 + 3) / 6 = 7.5/6 = 1.25人日
標準偏差 = (3-0.5)/6 ≈ 0.42
合計期待値(P50) = 5.67 + 3.25 + 2.33 + 1.25 = 12.5人日
→ Bad見積もり5人日の 2.5倍
合成標準偏差(独立仮定) = sqrt(1.67² + 0.75² + 0.67² + 0.42²)
= sqrt(2.78 + 0.56 + 0.44 + 0.17)
= sqrt(3.96) ≈ 1.99
P90見積もり(経営向けコミット値、z=1.2816)
= 12.5 + 1.2816 × 1.99 ≈ 12.5 + 2.55 ≈ 15.1人日
→ Bad見積もり5人日の 約3.0倍
【コスト差】
Bad予算 = 5人日 × 4万円/人日 = 20万円
P50実コスト予測 = 12.5人日 × 4万円/人日 = 50万円(差分 +30万円、+150%)
P90コミット値 = 15.1人日 × 4万円/人日 ≈ 60.4万円(差分 +40.4万円、+202%)
# 修正⑥: 依存関係マッピング
決済ゲートウェイAPI(定期課金対応可否・冪等性キー対応要確認)
↓
バックエンド実装(契約作成・課金バッチ・状態管理)
↓
クーポンシステム(重複適用ロジックの改修要否)
↓
在庫管理システム(定期購入時の在庫引当ロジック)
↓
CSチーム向けFAQ・エスカレーションフロー整備
# 決済ゲートウェイの定期課金API対応可否は最上流の前提条件。
# 対応不可であれば内製実装(案A)に切り替わり見積もりが大きく変わるため、
# 着手前に必ず調査タスクを先行させる。
修正⑦: フェーズドロールアウト計画
| フェーズ | 対象 | 期間 | ロールバック基準 |
|---|---|---|---|
| 1 | 社内テスト(Feature Flag OFF/ON切替) | 1週目 | 課金成功率 95%未満で即停止 |
| 2 | 全会員の1% | 2週目 | 課金失敗率が通常決済の2倍を超えたら即ロールバック |
| 3 | 全会員の10% | 3週目 | 同上 + CS問い合わせ件数を監視 |
| 4 | 全会員の100% | 4週目 | 同上 |
ポイント解説
実務への応用
MOpsチームでは新規機能の要件定義を後輩PdMやジュニアエンジニアが最初のドラフトを書く機会が多い。本問題の型(Given-When-Then受け入れ基準 → 非機能要件表 → エッジケース一覧 → 6W3H → PERT三点見積もり → 依存関係マッピング → フェーズドロールアウト)をテンプレート化しておくことで、「見積もりが後から2〜3倍に膨らむ」という頻出事故を要件定義の段階で防止できる。
今日のまとめ
次のステップ
- 発展問題: 今回はタスクが4つで独立と仮定して合成標準偏差を計算したが、実際には「決済ゲートウェイ調査」の結果次第で「バックエンド実装」の工数が変わる(タスク間の相関)。タスク間に相関がある場合のモンテカルロシミュレーションによる見積もり手法を設計し、PERT法との使い分け基準を整理せよ。
- 参考: Given-When-Then(振る舞い駆動開発)/ PERT三点見積もり / P50・P90見積もり / INVEST原則(ユーザーストーリーの良し悪し)/ Feature Flagによるフェーズドロールアウト / 6W3Hフレームワーク