10xbuilds.com

Estimating Software Projects Without Fooling Yourself

6 min read

Software estimates slip for reasons that are well documented, and several of them live in the estimator's head rather than in the code. Trying harder to guess right does not fix it. Changing the method does: estimate in ranges, check the number against how similar work actually went, make the buffer visible, and re-estimate as you learn.

Why estimates slip

Psychologists have a name for it: the planning fallacy, a term Daniel Kahneman and Amos Tversky coined in 1979. In Bent Flyvbjerg's summary of the research, people underestimate the costs, completion times and risks of planned actions while overestimating their benefits, largely because they take an "inside view": they focus on the details of the plan in front of them rather than on how similar efforts have turned out.

One clear demonstration is a 1994 study by Roger Buehler, Dale Griffin and Michael Ross, published in the Journal of Personality and Social Psychology. Psychology students in their final semester at the University of Waterloo were asked when they would finish their honors theses. Their average best estimate was 33.9 days. The average actual time was 55.5 days, and only 29.7% finished by their own best estimate.

The detail that matters most for estimators came from a second question. The students were also asked how long the thesis would take "if everything went as poorly as it possibly could." That worst-case estimate averaged 48.6 days, still short of the actual average, and fewer than half the students (48.7%) finished by their own worst-case date.

The same paper points at the cause. People built their predictions from plans for the future rather than from past experience, and they explained away earlier misses as caused by outside, one-time events. When participants in a later study were told to connect their prediction to relevant past experiences, the optimistic bias disappeared. Observers predicting other people's completion times did the opposite of the students: they leaned on past experience and overestimated.

A second bias makes this worse in team settings: the first number said out loud tends to stick. In an experiment with 410 professional developers, Martin Shepperd, Carolyn Mair and Magne Jørgensen found that a low or high "anchor" value shown before estimating had a substantial effect on the estimates. A workshop on cognitive biases reduced the effect but did not remove it.

Give ranges, not points

A single number hides the uncertainty that everyone in the room already feels. A range states it. "Three to six weeks" tells a stakeholder something that "four weeks" does not: the work has real unknowns, and planning around the early end is a bet.

Two habits make ranges useful:

  • Attach a confidence level. "I expect this to land between three and six weeks, and I'd be surprised if it went outside that range more than one time in five." That gives you something you can check later.
  • Make the high end uncomfortable. The thesis students' worst cases were missed more often than they were hit. If your high number feels safe, it is probably too low.

Then track calibration. For every estimate, record the range and the actual. If you say "80% confident" and only half your actuals land inside your ranges, your ranges are too narrow, and you now have the data to widen them.

Check your number against a reference class

The inside view builds an estimate from the parts of this project. The outside view asks how long projects like this one have actually taken. Flyvbjerg describes reference class forecasting in three steps:

  1. Identify a reference class of past, similar projects: broad enough to be meaningful, narrow enough to be comparable.
  2. Establish the distribution of outcomes for that class from real data.
  3. Compare your project with that distribution to find the most likely outcome.

Dan Lovallo and Daniel Kahneman, writing in Harvard Business Review in 2003, describe the same move for business decisions: set aside the details, look at a class of similar projects, lay out a rough distribution of their outcomes, and position the current project within it.

A small team does not need an industry database. Its best reference class is its own history. Keep a plain log with four columns: the work item, the first estimate, the actual time, and a note on what surprised you. After a few dozen entries, you can see your typical ratio of actual to estimated time. If the log shows your features tend to take 1.3 to 1.8 times the first estimate (example figures, not a benchmark), that ratio belongs in the next estimate. It is the same fix the Buehler paper found: tie the prediction to past experience, on purpose.

Break the work down, and know what that fixes

Breaking a feature into tasks helps you find forgotten work. It does not, by itself, cure optimism, because each small estimate is still an inside-view guess. Here is an example breakdown for a CSV import feature, in working days:

TaskLowHigh
Upload and parse the file12
Column mapping screen24
Validation and error report25
Duplicate handling13
Tests, review and deploy13
Total717

The sum of the lows is not a realistic low. Hitting it requires every task to go well at once. As a hypothetical, if each of the five tasks had a one-in-four chance of landing at its low, the chance of all five doing so would be under one in a thousand. Present the total as a range, with most of your planning weight toward the upper half.

Breakdowns also expose the work people skip when they estimate from memory. Check each estimate against a list like this: environment setup, data migration, empty and error states, permissions, notification emails, analytics events, automated tests, code review, QA, deployment, documentation, and fixing the bugs that turn up in the first week after launch.

Put buffers in the open

Padding every task quietly feels safe, but it hides where the uncertainty actually sits, and slack nobody can see is easy to spend without anyone noticing. A better pattern is one visible buffer for the whole project.

Using the CSV example: the midpoints of the task ranges add up to 12 days. If your log says actuals run about 1.4 times your midpoint estimates (again, an example), plan for roughly 17 days and show the extra 5 days as a named project buffer, owned by the project rather than by any one person.

Then watch how fast the buffer is being used compared with how much work is done. If half the buffer is gone when a quarter of the work is finished, that is your early warning, and it arrives while there is still time to act.

When the date is fixed, scope becomes the buffer. Agree in advance, in writing, which items get cut, and in what order, if the buffer runs out.

Re-estimate as you learn

An estimate made before design is settled carries more uncertainty than one made after a working spike. Treat estimates as something you revise at planned points, not a promise frozen on day one:

  • after any technical spike or prototype answers an open question,
  • once the design is settled,
  • at each milestone, using the actual pace so far.

When an estimate moves, say so right away and say why: "The payment provider's API does not support partial refunds, which adds three to five days." Early, specific updates keep trust. Late surprises spend it.

Keep three words separate when you talk to stakeholders. An estimate is your best prediction. A target is what the business would like. A commitment is what you promise. Do not let an estimate be quietly converted into a commitment.

The most useful step is also the smallest: start the estimate log this week. Every row you add makes the next estimate less of a guess and more of a lookup.

More from 10xbuilds.com