Article

Webシステム開発の見積もりはどう決まる?工数算出の考え方

高田晃太郎
Webシステム開発の見積もりはどう決まる?工数算出の考え方

統計的には、McKinsey & Companyとオックスフォード大学の共同研究が大規模ITプロジェクトのコスト超過は平均で約45%、スケジュール超過は約7%と報告しています¹。Standish GroupのCHAOSレポートでも、フルスコープ・オンタイム・オンバジェットで完了する案件は少数派です²。数字は厳しい現実を示しますが、同時に改善余地の大きさも示します。見積もりは占いではなく、観測可能な変数と仮説、そして不確実性の扱い方の設計です。私はWebシステム開発の見積もりを、スコープの量、生産性の係数、リスクの吸収という三つの歯車で回す工学問題として捉えています。要するに、工数(開発に要する時間や人の投下量)は「決まり方」を設計できる。この記事では、そのための具体的な考え方と、実務で使える式とコードをまとめます。

見積もりは何で決まるか:3つの歯車

まずスコープです。要件定義の文章は見積もりの材料にはなりますが、そのままでは量に変換できません。画面単位、API単位、業務イベント、ユースケース、ドメイン機能など、チームが再現性を持って数えられる単位に正規化します。Scrumの文脈であればストーリーポイント(機能規模の相対評価単位)、古典的手法であればファンクションポイント(外部入出力や内部ファイルを基に算出する機能規模指標)、コード寄りならモジュールやエンドポイント数でも構いません。重要なのは単位の定義がチーム内で一意に理解され、過去実績と紐づけられることです³。

次に生産性です。ここでは「1ポイントあたりの実工数」や「1スプリントあたりの完了ポイント(ベロシティ)」といった係数が主役になります。過去のバーンダウンやDoneの履歴を使い、アウトライヤーを除去した上で中央値や分位点で表現すると、季節性や人員変動の影響を受けにくくなります。平均ではなく中央値やP50/P80(全体の50%/80%が下回る点)を使うと、経営判断に耐える頑健な数字になります。

最後にリスクです。不確実性は誤差として放置せず、項目化して吸収します。未知技術、外部APIのSLA(サービス品質合意)、データ移行の品質、法令対応の変更可能性、負荷要件など、影響と確率を見積もり、リスクバッファとして工数に折り込みます。私はしばしば、ベース工数に補正係数を掛け、さらに管理・品質・移行の固定的な付帯作業を加え、最後に確率加重したリスクバッファを積み上げます。式で書くと、工数 = ベース × 補正 × 品質・管理係数 + 付帯作業 + リスクエクスポージャ、という形です。補正には非機能要件の厳しさや統合複雑度、ドメイン難度を反映します。実務でも、計画超過の主要因には不完全な情報や生産性・コミュニケーションの問題などが挙げられることが報告されています⁶。

ベース工数の作り方:粒度と相対化

相対見積もりは人間の判断バイアスを抑えるのに有効です。既存の完成済みストーリーを基準サンプルにして、新規ストーリーを相対で当てはめます。同じチームで維持すれば校正は徐々に安定します。ウォーターフォールでも概念は同じで、画面タイプ、CRUDのパターン、バリデーション密度、入出力の数を基準化して、標準タイプごとの代表工数を用意しておくと揺れが小さくなります。ここでの失敗パターンは粒度がバラつくことです。レビューしないまま大粒と小粒が混在すると、以降の全ての係数が歪みます。粒度は「1〜3日のタスクに分割できるか」など、プロジェクトでの実作業単位に合わせます⁴。

補正とバッファ:暗黙知を明示知に

非機能要件を補正に落とすには、性能、可用性、セキュリティ、運用性といった品質特性の水準を予めレベル化しておくと便利です。例えばRPS(1秒あたりのリクエスト数)やp95レイテンシ(遅延の95パーセンタイル)、RTO/RPO(復旧目標時間/復旧時点目標)、脆弱性基準、運用監視のカバレッジをレベル1〜3で定義し、レベルが上がるほどレビュー、テスト、アーキテクチャ設計のコストが増えることを係数で表現します。リスクバッファは、各リスクの発生確率と影響工数を掛けた期待値の合計として算出すると、恣意性が減ります。

手法の実践:三点見積もり、COCOMO、実績回帰

私が現場で併用しているのは、三点見積もり、パラメトリックモデル、そして実績データに基づく回帰のハイブリッドです。三点見積もりは楽観・最頻・悲観の三つを出し、期待値と分散を得ます(PERT)。パラメトリックモデルはCOCOMO IIのように規模と各種係数で工数を出す考え方です⁵。実績回帰は「このチームがこの技術スタックでこの粒度のIssueを処理したときの速度」という固有の生産性を、履歴データから統計的に推定する方法です。三者は競合ではなく相互検証のための複線です。整合していれば自信を持って出せますし、乖離すれば前提の見直しポイントが見えます。

三点見積もりの式をコードにする

三点見積もりは式がシンプルで自動化に向きます。PERTの期待値と標準偏差をPythonで関数化しておくと、WBS(作業分解構成)の行単位で瞬時に集計できます。

from dataclasses import dataclass
from typing import Iterable, Tuple

@dataclass
class Task:
    name: str
    optimistic: float  # 人日
    most_likely: float # 人日
    pessimistic: float # 人日

def pert_estimate(tasks: Iterable[Task]) -> Tuple[float, float]:
    """合計期待値と標準偏差を返す。"""
    exp_total = 0.0
    var_total = 0.0
    for t in tasks:
        exp = (t.optimistic + 4*t.most_likely + t.pessimistic) / 6.0
        std = (t.pessimistic - t.optimistic) / 6.0
        exp_total += exp
        var_total += std ** 2
    return exp_total, var_total ** 0.5

# 例
wbs = [
    Task("会員登録API", 1.0, 2.0, 4.0),
    Task("OAuth連携", 1.5, 3.0, 6.0),
    Task("UI実装", 2.0, 3.0, 5.0),
]
exp, std = pert_estimate(wbs)
print({"exp": exp, "p50": exp, "p90": exp + 1.28*std})

このコードは行ごとの三点見積もりから合計のP50とP90相当を素早く算出します。確率で語れる見積もりは、経営の意思決定を助けます。

COCOMO的な補正を軽量に使う

COCOMO IIは本格導入には校正が必要ですが、考え方は軽量に取り入れられます。規模に対して指数的に伸びる係数、チームの経験やツール成熟度などのドライバを掛けるだけでも、単純な比例モデルの過小評価を避けられます⁵。

from typing import Dict

# 非公式の軽量版。A, B は組織内の履歴で校正する。
A, B = 2.5, 1.05  # ベース係数とスケール指数
DRIVERS: Dict[str, float] = {
    "platform_experience": 0.9,   # 経験豊富なら短縮
    "new_tech": 1.15,             # 新技術は延長
    "qa_rigour": 1.1,             # テスト厳格度
    "integration_complexity": 1.2 # 外部連携難度
}

def cocomo_like(size_kloc: float, drivers: Dict[str, float]) -> float:
    effort_nominal = A * (size_kloc ** B)
    for v in drivers.values():
        effort_nominal *= v
    return effort_nominal

print(cocomo_like(30, DRIVERS))  # 人月の目安

規模の指標はKLOC(千行のソースコード)に限らず、画面数やエンドポイント数をダミー変数化しても機能します。増加が非線形であるという発想自体が重要です。

実績回帰:自分たちの生産性を測る

JiraやLinearなどの課題管理ツールの履歴から、各イテレーションのスループット(単位期間あたりの完了量)とサイクルタイム(着手から完了までの時間)を抽出し、分位点で安定値を採ります。平均を使うとアウトライヤーに弱いため、p50やp80が適しています。次のSQLはIssueの着手から完了までのサイクルタイム分布を概観する例です。

-- issues(started_at, done_at) を持つテーブルを想定
SELECT
  PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY EXTRACT(EPOCH FROM done_at - started_at)/86400.0) AS p50_days,
  PERCENTILE_CONT(0.8) WITHIN GROUP (ORDER BY EXTRACT(EPOCH FROM done_at - started_at)/86400.0) AS p80_days,
  COUNT(*) AS n
FROM issues
WHERE done_at BETWEEN DATE '2025-01-01' AND DATE '2025-03-31';

この結果を用い、ポイント換算の妥当性を検証します。さらにスプリントごとのベロシティの分布を作り、異常期間を除外して基準を作ると、見積もりの係数が現実と繋がります³。

import statistics as stats
from typing import List

velocities: List[int] = [28, 25, 31, 12, 29, 27, 30]  # 例。12は障害週で除外候補
trimmed = [v for v in velocities if v > 0.6 * stats.median(velocities)]
median_v = stats.median(trimmed)
p80_v = stats.quantiles(trimmed, n=100)[79]
print({"median": median_v, "p80": p80_v})

私はここから「1ポイントあたりの人日」ではなく、「スプリントあたりの完了ポイント」を主たる予測単位にすることが多く、チームに依存する生産性の変動をそのまま捉えられる利点があります。

確度を語る:モンテカルロとP50/P90

経営にとって重要なのは、いつまでに何をどの確度で届けられるかです。単一の期日だけを掲げても、リスク対話は生まれません。モンテカルロ(乱数を用いた反復計算)でスプリントごとのベロシティをサンプリングし、バックログの総ポイントが尽きるまでの反復を多数回シミュレーションすると、納期の分布が得られます。P50をコミット、P90を目標とするなどの運用にすると、追加要求やスコープ見直しの議論がしやすくなります。

import random
from datetime import date, timedelta
from typing import List

def forecast_finish(start: date, total_points: int, velocity_samples: List[int], iterations: int = 5000) -> List[date]:
    if not velocity_samples:
        raise ValueError("velocity_samples is empty")
    finishes = []
    for _ in range(iterations):
        remaining = total_points
        d = start
        while remaining > 0:
            v = random.choice(velocity_samples)
            remaining -= max(v, 1)
            d += timedelta(days=14)  # 2週間スプリント
        finishes.append(d)
    return sorted(finishes)

finishes = forecast_finish(date(2025, 9, 1), total_points=180, velocity_samples=[24,26,27,28,30,31,33])
idx50 = int(0.5 * len(finishes))
idx90 = int(0.9 * len(finishes))
print({"p50": finishes[idx50], "p90": finishes[idx90]})

この結果をガントやリリースバーンダウンに重ねると、スコープ変更の影響が即座に確率として見える化されます。新規要求が10ポイント増えたとき、P90が何週後ろに動くかを即答できれば、事業側の意思決定も迅速になります。

精度を上げ続ける運用:MAPEとカットオフ

予測は出して終わりではありません。スプリント完了ごとに、見積もりと実績の誤差をMAPE(Mean Absolute Percentage Error、平均絶対百分率誤差)やMdAPE(中央値版)で測り、係数を自動更新します。特に上流の不確実性が高い期間は、フォアキャストのカットオフを短めに設定し、P90ベースでコミットする運用に切り替えると、外乱の影響を受けにくくなります。スコープ凍結のマイルストーンも、曖昧な表現ではなく「P50が期日を超えるスコープ増を受け入れない」と定義しておくと、交渉が透明になります。

from typing import Tuple, List

def mape(forecast: List[float], actual: List[float]) -> float:
    if len(forecast) != len(actual) or not forecast:
        raise ValueError("length mismatch or empty")
    ape = [abs(f - a) / max(a, 1e-6) for f, a in zip(forecast, actual)]
    return 100.0 * sum(ape) / len(ape)

print(mape([10, 12, 9], [11, 11, 10]))  # 例:%

MAPEが高止まりする場合は、粒度の揺れ、スコープの抜け、外部依存の不確実性が原因であることが多いものです。原因がデータに現れるよう、WBSの属性に「外部連携」「新規ドメイン」「性能レベル」などのタグを持たせ、誤差の寄与分析ができるようにしておくと、次の見積もりが強くなります。

ケースで考える:B2Cサイト刷新の見積もり

会員基盤を持つB2Cサイト刷新を仮想例に、数字の通り道を示します。要件をユースケースとAPIエンドポイントに分解すると、会員登録、認証、プロフィール編集、購買履歴、通知、管理画面、レポート、検索、外部支払い連携などで、合計でおよそ80ストーリーになりました。相対見積もりで合計160ポイント。非機能要件はp95のレスポンスタイム200ms、RTO4時間、OWASP ASVSレベル2相当、SLO(目標サービス稼働率)99.9%と定義されています。過去6スプリントのベロシティは中央値28、p80が31。P50で進めると、スプリント6〜7本で主要機能まで届く計算です。ここに支払い連携の不確実性とデータ移行の工数を、確率加重でそれぞれ10日と15日相当のバッファとして積み上げました。さらにQA強化と性能検証の係数を1.15とし、運用準備と監視設計の付帯作業として20日を追加します。結果として、ベースに対して約1.35倍の総工数になりました。モンテカルロでP50のリリースは14週後、P90は16週後という分布が得られ、事業側とはP50でMVP、P90で広告連携までという確度で段階化した合意を形成できました。実行後のMAPEは12%で収束し、次期の見積もり係数に反映しています。

ビジネス価値:精度10%改善のROI

見積もり精度が10%改善すると、直接原価の圧縮だけでなく、機会損失の回収可能性が上がります。P90での計画によりマーケティングの前倒し投資を抑制し、MVPの早期デプロイで学習速度を上げれば、キャッシュフローの谷を浅くできる。開発組織としては、期待値管理が適正化されることで離職を誘発するプレッシャーを下げ、生産性の実力値が上がる副次効果も見込めます。経営は不確実性を回避するのではなく、価格に織り込む。見積もりはその対話のための共通言語なのです。

実務Tips:標準化の最小セット

最後に、現場で効いた最小セットを紹介します。WBSの粒度ガイド、ポイントの参照サンプル集、非機能レベル表、スプリント速度の分位点ダッシュボード、そしてモンテカルロのスクリプト。この5点を整備し、月次で見直すだけで、見積もりは再現性を帯びます。重要なのは、数字の由来を説明できることと、乖離が出たときに係数を更新する運用習慣です。

まとめ:見積もりを“製品”として運用する

見積もりは一度作って終わる資料ではなく、プロジェクトの学習に合わせて改善される“製品”です。スコープを数えられる単位に整え、生産性の係数を自社データから校正し、リスクをバッファとして価格に織り込む。確度はP50とP90で語り、モンテカルロで事業と対話する。ここまでの一連を仕組みに落とし込めば、見積もりは恐れる対象ではなく、方針を決める武器になります。次のスプリントから、Done履歴の分位点を計算し、WBSに三点見積もりを付与し、簡単なシミュレーションを走らせてみてください。数字の通り道が見えた瞬間に、交渉力と実行力が同時に上がるはずです。まずは小さく始め、月に一度の校正を続けましょう。

参考文献

  1. McKinsey & Company; University of Oxford (2012). Delivering large-scale IT projects on time, on budget, and on value. https://www.mckinsey.com/capabilities/mckinsey-digital/our-insights/delivering-large-scale-it-projects-on-time-on-budget-and-on-value?ref=mercecom.ghost.io#:~:text=often%20do%20go%20wrong,1%7D%20%28Exhibit%201
  2. Standish Group. CHAOS Report findings (2015–2019 の要約). MLS Journals 経由のサマリー: https://www.mlsjournals.com/Project-Design-Management/article/download/1016/2637#:~:text=In%20its%202019%20report%2C%20Standish,Standish%20group%2C%202015
  3. Atlassian. アジャイル見積もり(ストーリーポイントとベロシティの活用). https://www.atlassian.com/ja/agile/project-management/estimation#:~:text=%E3%81%8C%E5%BF%85%E7%84%B6%E7%9A%84%E3%81%AB%E7%95%B0%E3%81%AA%E3%81%A3%E3%81%A6%E3%81%8D%E3%81%BE%E3%81%99%E3%80%82%E3%81%93%E3%81%AE%E3%81%9F%E3%82%81%E3%80%81%E9%80%9F%E5%BA%A6%E3%82%92%E6%AD%A6%E5%99%A8%E3%81%A8%E3%81%97%E3%81%A6%E4%BD%BF%E7%94%A8%E3%81%97%E3%81%A6%E7%AD%96%E3%82%92%E5%BC%84%E3%81%99%E3%82%8B%E3%81%93%E3%81%A8%E3%81%AF%E4%B8%8D%E5%8F%AF%E8%83%BD%E3%81%AB%E3%81%AA%E3%82%8A%E3%81%BE%E3%81%99%E3%80%82%20,%E3%82%92%E7%94%9F%E3%81%BF%E5%87%BA%E3%81%99%E3%81%93%E3%81%A8%E3%81%AB%E9%9B%86%E4%B8%AD%E3%81%A7%E3%81%8D%E3%81%BE%E3%81%99%E3%80%82
  4. Atlassian. 見積もりタスクの粒度(16時間超は分割の推奨). https://www.atlassian.com/ja/agile/project-management/estimation#:~:text=%E5%80%8B%E3%80%85%E3%81%AE%E3%82%BF%E3%82%B9%E3%82%AF%E3%81%AF%E3%80%81%E4%BD%9C%E6%A5%AD%E3%81%8C%2016%20%E6%99%82%E9%96%93%E3%82%92%E8%B6%85%E3%81%88%E3%81%AA%E3%81%84%E3%82%88%E3%81%86%E3%81%AB%E3%81%97%E3%81%A6%E3%81%8F%E3%81%A0%E3%81%95%E3%81%84%E3%80%82,%E3%81%BE%E3%81%9F%E3%81%AF%2020%20%E3%83%9D%E3%82%A4%E3%83%B3%E3%83%88%29%20%E3%81%AE%E9%96%BE%E5%80%A4%E3%82%92%E8%B6%85%E3%81%88%E3%82%8B%E8%A6%8B%E7%A9%8D%E3%82%82%E3%82%8A%E3%81%8C%E3%81%82%E3%82%8B%E5%A0%B4%E5%90%88%E3%80%81%E3%81%9D%E3%82%8C%E3%82%92%E3%81%95%E3%82%89%E3%81%AB%E7%B4%B0%E5%88%86%E5%8C%96%E3%81%97%E3%81%A6%E8%A6%8B%E7%A9%8D%E3%82%82%E3%82%8A%E3%82%92%E3%82%84%E3%82%8A%E7%9B%B4%E3%81%99%E5%BF%85%E8%A6%81%E3%81%8C%E3%81%82%E3%82%8B%E3%81%93%E3%81%A8%E3%82%92%E7%A4%BA%E3%81%97%E3%81%A6%E3%81%84%E3%81%BE%E3%81%99%E3%80%82
  5. NASA Software Engineering Handbook. SWE-015 — Cost Estimation (COCOMO and cost drivers). https://swehb.nasa.gov/display/SWEHBVC/SWE-015%2B-%2BCost%2BEstimation#:~:text=As%20an%20example%2C%20COCOMO,the%20factor%20can%20influence%20productivity
  6. Project Management Institute (PMI). Overruns: poor/incomplete information, productivity, communications. https://www.pmi.org/learning/library/overruns-poor-incomplete-information-prodcutivity-communications-8290#:~:text=1927%20and%201998%20found%20that,the%20Management%20of%20Engineering%20and