科学进度估计:从 PERT 到 Monte Carlo

发布: (2026年1月2日 GMT+8 22:21)
5 min read
原文: Dev.to

Source: Dev.to

(请提供您希望翻译的正文内容,我将保持原有的 Markdown 格式、代码块和链接不变,仅将文本翻译为简体中文。)

PERT(项目评估与审查技术)

PERT 是在 1950 年代由美国海军为 Polaris 导弹项目开发的,这一机密项目将开发周期缩短了两年。

def pert_estimation(optimistic, realistic, pessimistic):
    """
    O: Optimistic (when everything is perfect)
    R: Realistic (normal case)
    P: Pessimistic (when everything goes wrong)
    """
    # PERT formula
    expected = (optimistic + 4 * realistic + pessimistic) / 6

    # Standard deviation (uncertainty)
    std_dev = (pessimistic - optimistic) / 6

    return {
        "expected": expected,
        "std_dev": std_dev,
        "range_68%": (expected - std_dev, expected + std_dev),
        "range_95%": (expected - 2 * std_dev, expected + 2 * std_dev)
    }

# Real example: Login API development
result = pert_estimation(
    optimistic=4,   # Best: 4 hours
    realistic=8,   # Reality: 8 hours
    pessimistic=16 # Worst: 16 hours
)

print(f"Expected: {result['expected']:.1f} hours")          # 8.7 hours
print(f"68% probability: {result['range_68%']}")           # (6.7, 10.7)
print(f"95% probability: {result['range_95%']}")           # (4.7, 12.7)

为什么要乘以 4?
该因子在类似正态分布中为最可能(众数)估计赋予更大的权重,这对敏捷团队非常有用。

计划扑克

一种快速的全团队共识技术:

  1. 每个人准备卡片(1、 2、 3、 5、 8、 13、 21、 34…)。
  2. 同时翻开卡片。
  3. 如果估算差异很大,讨论原因。
  4. 达成共识估算。
fibonacci = [1, 2, 3, 5, 8, 13, 21, 34]

心理效应: 对较大数字使用更宽的区间,以防止过度精确。

蒙特卡罗模拟

蒙特卡罗使用随机抽样来对项目完成时间进行建模。

import random
import numpy as np

def monte_carlo_simulation(tasks, iterations=1000):
    """Simulate project completion time."""
    results = []

    for _ in range(iterations):
        total_time = 0
        for task in tasks:
            # Randomly select actual time for each task
            actual = random.triangular(
                task['min'],
                task['max'],
                task['likely']
            )
            total_time += actual
        results.append(total_time)

    return {
        "mean": np.mean(results),
        "p50": np.percentile(results, 50),  # Median
        "p90": np.percentile(results, 90),  # 90 % probability
        "p95": np.percentile(results, 95)   # 95 % probability
    }

# Project tasks
tasks = [
    {"name": "Design",      "min": 2, "likely": 3, "max": 5},
    {"name": "Development", "min": 5, "likely": 8, "max": 15},
    {"name": "Testing",     "min": 2, "likely": 3, "max": 6}
]

result = monte_carlo_simulation(tasks)
print(f"50% probability: complete within {result['p50']:.1f} days")
print(f"90% probability: complete within {result['p90']:.1f} days")

基于速度的估算

利用历史冲刺速度来预测未来工作。

class VelocityEstimator:
    def __init__(self, past_sprints):
        self.velocities = past_sprints

    def estimate(self, total_points):
        avg_velocity = np.mean(self.velocities)
        std_velocity = np.std(self.velocities)

        sprints_needed = total_points / avg_velocity

        return {
            "expected_sprints": sprints_needed,
            "optimistic": total_points / (avg_velocity + std_velocity),
            "pessimistic": total_points / (avg_velocity - std_velocity)
        }

# Past 10 sprint velocities
past_velocities = [23, 28, 25, 30, 22, 27, 26, 24, 29, 26]

estimator = VelocityEstimator(past_velocities)
result = estimator.estimate(total_points=150)

print(f"Expected: {result['expected_sprints']:.1f} sprints")
print(f"Range: {result['optimistic']:.1f} ~ {result['pessimistic']:.1f}")

专家共识(宽带德尔菲)

一个结构化的、多轮估算过程:

  1. 第 1 轮 – 匿名提交

    • Dev A:10 天
    • Dev B:5 天
    • Dev C:15 天
  2. 第 2 轮 – 分享理由并重新估算

    • A:“考虑到数据库迁移……”
    • B:“哦,我漏掉了。”
    • C:“是否包括测试自动化?”

    新估算:8 天,9 天,10 天。

  3. 第 3 轮 – 共识

    • 最终估算:9 天

推荐

方法何时使用
Planning Poker快速、简便的团队共识
PERT + Velocity平衡的准确性与实用性
Monte Carlo + Wideband Delphi需要风险分析的高精度项目

使用相似的过去项目调整估算

similar_projects = [
    {"name": "Login System A", "estimated": 20, "actual": 35},
    {"name": "Login System B", "estimated": 15, "actual": 28},
    {"name": "Login System C", "estimated": 25, "actual": 40}
]

adjustment_factor = np.mean([p["actual"] / p["estimated"] for p in similar_projects])
# adjustment_factor ≈ 1.73

# Apply to a new raw estimate
new_estimate = raw_estimate * adjustment_factor

冲刺估算回顾

任务预估实际差异原因
API 开发8 h12 h+4 hAuth 复杂性
UI 实现6 h5 h–1 h模板复用
测试4 h8 h+4 h边缘情况

经验教训:Auth 和测试阶段大约需要 1.5× 的缓冲时间。

结束语

“直觉”估算的时代已经结束。使用科学技术:

  • 使用 PERT 计算不确定性。
  • 将估算视为 范围,而不是单一数字。
  • 利用 过去的数据(速度、类似项目)。
  • 让整个团队参与(Planning Poker、Wideband Delphi)。
  • 持续改进你的估算过程。

准确的估算建立信任并让项目保持在正轨上。

需要科学的估算和项目管理吗?请查看 Plexo。

Back to Blog

相关文章

阅读更多 »

Agile 相对于 Waterfall 的虚假承诺

Waterfall 与 Agile 的神话 二十年来,我们一直相信这样一种说法:Waterfall 是一种过时的遗物——僵硬、官僚、根本破碎。与此同时……

敏捷简约的空洞承诺

敏捷简化的问题 > “敏捷一句话:检查并适应。” > 或者 “提前且频繁交付价值。” 每位顾问都有一个电梯演讲…