Engineering Estimation: From Guesswork to Forecasting

In complex software systems, estimation is the process of surfacing and resolving underlying assumptions. While traditional methods rely on single-point "expert" opinions, high-density practitioner environments utilize probabilistic models to manage uncertainty.

---

I. Relative Sizing: Planning Poker

Planning Poker mitigates **Anchoring Bias** by requiring simultaneous reveal of estimates using the Fibonacci sequence (1, 2, 3, 5, 8, 13, 21).

* **The Goal:** Not the number, but the **variance reduction** achieved through discussion of outliers.

* **The Rule:** If the team can't converge after 3 rounds, the story is too ambiguous and must be decomposed.

---

II. PERT: Three-Point Estimation

The **Program Evaluation and Review Technique (PERT)** uses a weighted average to account for the "long tail" of software risks.

A. The Math of PERT

For every task, gather three values:

1. **$O$(Optimistic):** Best case (everything goes right).

2. **$M$(Most Likely):** The consensus estimate.

3. **$P$(Pessimistic):** Worst case (everything goes wrong).

**Expected Value ($E$):**$$E = \frac{O + 4M + P}{6}$$**Standard Deviation ($\sigma$):**$$\sigma = \frac{P - O}{6}$$**Why it works:** Unlike a simple average, PERT weights the "Most Likely" case and recognizes that the risk ($P$) is often much further from$M$than the opportunity ($O$).

---

III. Monte Carlo Simulations for Forecasting

Monte Carlo simulations replace deterministic "deadlines" with a **probability distribution of completion dates**.

A. The Simulation Model

Instead of saying "The project will take 10 weeks," we run 10,000 simulations where each run samples from:

* **Backlog Size:**$N \pm \Delta N$(accounting for scope creep).

* **Velocity:** A distribution of historical team velocity (e.g.,$15 \pm 5$ points/sprint).

B. Example Python-like Logic

```python

def run_simulation(backlog_range, velocity_dist, runs=10000):

results = []

for _ in range(runs):

total_scope = random.sample(backlog_range)

current_velocity = random.sample(velocity_dist)

weeks_to_finish = total_scope / current_velocity

results.append(weeks_to_finish)

Analyze the 85th and 95th percentiles

p85 = percentile(results, 85)

p95 = percentile(results, 95)

return p85, p95

```

C. Interpreting the Result

* **P50:** 50% chance. (A coin flip; never commit to this).

* **P85:** 85% chance. (Standard "safe" commitment for internal stakeholders).

* **P95:** 95% chance. (The "high confidence" date for external release/marketing).

---

IV. The Estimation Template (JSON)

Use this schema to capture the raw inputs for a forecasting model.

```json

{

"milestone": "Identity_Provider_Migration",

"estimation_method": "PERT_Weighted",

"items": [

{

"task": "OAuth2_Schema_Design",

"optimistic": 3,

"most_likely": 5,

"pessimistic": 13,

"pert_e": 6.0,

"pert_std": 1.66

},

{

"task": "Legacy_Data_Cleanup",

"optimistic": 5,

"most_likely": 13,

"pessimistic": 40,

"pert_e": 16.1,

"pert_std": 5.83

}

],

"confidence_interval": "P85",

"projected_velocity_range": [20, 35]

}

```

---

V. Governance: The Estimation Ethics

1. **Never Average:** If one dev says 3 and another says 13, do not record 8. Discuss the gap. One of them knows something the other doesn't.

2. **Estimate Complexity, Not Time:** Time is a derivative of complexity and team capacity.

3. **Update Frequently:** Rerun Monte Carlo simulations after every sprint using actual velocity data to update the P85 date.