Levelwise
English
Senior skills

Estimation and planning

An estimate is a forecast with a range, not a promise. Break the work into small pieces, count the hidden work, and do a short investigation first for the unknown part. Give the number with a range, assumptions and risks, and update the estimate whenever you learn something new.

Not reviewedWritten with AI helpReading time: 13 minExample of a discount code feature in the shopC# code on .NET 10

Author: bezzad

The problem: “just three days”

The product manager of our online shop asks in the hallway: “How long will the discount code take?” The developer thinks for a moment and says: “Three days.”

The manager tells this number to the marketing team. Marketing plans the campaign for next week.

The work takes three weeks. Why?

  1. The payment gateway had a separate API for discounts that nobody knew.
  2. An admin panel was needed so the marketing team could create codes themselves. Nobody had thought about it.
  3. Review, testing and deployment were not counted in those “three days”.
  4. In the middle of the work, two urgent bugs came from another team.

The developer did not do bad work. The problem was that a quick guess was heard as a promise.

Estimate, target and commitment

People often mix up these three words. But they are three separate things:

EstimateEstimate"Most likely between8 and 14 working days"A forecast with a rangeTargetTarget"Must be ready beforethe Nowruz campaign"What the business wantsCommitmentCommitment"We deliver a simpleversion by 20 Esfand"A promise, after comparing bothIf the target does not match the estimate, cut the scope, not the estimate
Do not change the estimate to reach the target. If they do not match, talk about the scope of the work.
  1. Estimate (Estimate). An honest forecast. “Most likely between 8 and 14 days.”
  2. Target (Target). What the business needs. “It must be ready before the Nowruz campaign.”
  3. Commitment (Commitment). The promise we give after comparing the estimate and the target. “We will deliver the simple version by that day.”

If the target is earlier than the estimate, making the estimate number smaller does not help. The work takes just as long. The right way is to change the scope of the work: “For the campaign, only percentage codes. Fixed-amount codes and the full admin panel come later.”

Why do we usually underestimate?

  1. We think of the best case. In our mind, the work moves forward without any problem.
  2. We forget the hidden work. We only count “writing code”. Not review, testing, database changes, deployment and meetings.
  3. A workday is not full. Meetings, helping a colleague and urgent bugs take part of every day.
  4. We do not see the unknowns. An unfamiliar API, or old code that nobody knows.
  5. Pressure for a small number. When someone is waiting in front of us, it is easier to say a smaller number.

The cone of uncertainty

At the start of the work, we do not know many things. So our estimate has a wide range. The further we go and the more we learn, the narrower the range gets. We call this shape the “cone of uncertainty” (Cone of Uncertainty).

First ideaNeeds are clearDesign is readyDeliveryMaybe much moreMaybe much lessActualThe further we go, the narrower the range. So estimate again

This shape has two lessons:

  1. An estimate at the start has a wide range. If someone wants an exact number in the first meeting, the most honest answer is a wide range.
  2. Repeat the estimate. When the requirements are clear, when the design is ready, and when part of the work is done. Each time, the range gets narrower.
Important point: The cone does not get narrower by itself. It only gets narrower when the team really answers the questions and investigates the risks.

Breaking down the work

You cannot estimate a big task well. You can estimate a small one. So we break the discount code into a few pieces:

Discount code featureModel and table1 to 2 daysRules and tests2 to 3 daysCheckout page1 to 3 daysPayment gatewayUnknownFirst a short spikeAdmin panel1 to 2 daysHidden work that people usually forgetCode reviewDB changesLogs and alertsManual testsDeploymentMeetings
Each piece is one or two days. The unknown part is separated. The hidden work is also visible.

A few simple rules for breaking down work:

  1. Each piece should be small. If a piece is more than a few days, we do not understand it yet. Break it again.
  2. Each piece should have a visible result. “Table and model ready and tested”, not “work on the backend”.
  3. Write down the hidden work. Count it separately so it is not forgotten.
  4. Separate the unknown part. For the payment gateway, first do a short, time-boxed investigation (Spike). For example, “We spend one day to try the gateway API.” Then estimate that part.
A short investigation has a fixed time. If the answer is still not clear after one day, that is an important result by itself. It means the risk is big and the manager must be told.

Three-point estimation

A single number carries little information. For each piece, we give three numbers:

  1. The best case. If everything goes well.
  2. The most likely case. Our real guess.
  3. The worst case. If a few things go wrong together, but not a disaster.
Best4 daysMost likely6 daysAverageabout 7 daysWorst12 daysLong tail: sometimes work ends much laterbut it rarely ends much earlierThe "most likely" number is below the average
Work time has a long tail toward being late. That is why the average is higher than the most likely number.

A common formula to combine these three numbers is the PERT formula. It gives more weight to the most likely number, but it also counts the worst case:

public sealed record TaskEstimate(string Name, double Best, double Likely, double Worst)
{
    // PERT (three-point) expected value, in days
    public double Expected => (Best + 4 * Likely + Worst) / 6;
}

TaskEstimate[] tasks =
[
    new("Model and table", 1, 1.5, 2),
    new("Rules and tests", 2, 2.5, 4),
    new("Checkout page",   1, 2,   3),
    new("Admin panel",     1, 1.5, 2),
    new("Hidden work",     1, 2,   4),
];

var expected = tasks.Sum(t => t.Expected);
Console.WriteLine($"Expected: {expected:F1} days");                          // 9.8
Console.WriteLine($"Range: {tasks.Sum(t => t.Best)}-{tasks.Sum(t => t.Worst)} days"); // 6-15

What do these numbers tell us?

  1. The expected number is about ten days. Not three days, and not the sum of the most likely numbers, which is nine and a half days.
  2. The full range is from 6 to 15 days. But it is unlikely that all tasks reach their worst or best case together. So a more realistic range is narrower than this.
  3. The payment gateway is not counted yet. After the short investigation, we add it too.
What is a Story Point? Some teams estimate the relative size of work instead of days. “This task is twice as big as that one.” After a few sprints, they learn from the team’s real speed how many points get done in each sprint. The main idea is the same: small work, comparing with past work, and relying on real data.

How do we say the number?

A good estimate is not just a number. It has four parts: a range, confidence, assumptions and risks.

Bad

“Three days.”

  • It has no range.
  • It is not clear what is counted in it.
  • The listener hears it as a promise.

Good

“Most likely between 8 and 14 working days. This number includes testing, review and deployment. I assumed the admin panel can only create and disable codes. The biggest risk is the payment gateway. Tomorrow I will spend one day investigating it, and the day after I will give a more exact number.”

If someone in the hallway wants a number right away, say: “Right now I only have a very rough guess. By tomorrow I will give a proper estimate.” This one day is much cheaper than three weeks of lost trust.

During the work

An estimate is not said once and forgotten:

  1. Measure progress in small pieces. “Three of five pieces are done” is more exact than “seventy percent of the work is done”.
  2. Report delays early. If on day three you see the work will be late, say it that same day. Bad news early gives the business time to choose. Bad news late is only a surprise.
  3. Cut scope, not quality. If time is short, remove a part or move it later. Removing tests makes the work more expensive later.
  4. Compare the estimate with reality. After a few tasks, you may see that your work usually takes one and a half times your estimate. This number is very valuable for your next estimates.

Common mistakes

Mistake Result Right way
A single number, without a range The listener hears it as a promise. A range, assumptions and risks.
Estimating a big task as one piece Many things are not seen. Break it into pieces of one or two days.
Counting only coding time Testing, review and deployment are left out. Write down the hidden work separately.
Lowering the estimate to reach the target The work takes just as long, it only becomes clear later. Reduce the scope of the work.
Estimating the unknown part without investigating Most of the delay comes from this part. First a short, time-boxed investigation.
Hiding a delay until the last day Trust is lost, and nobody has time to react. Give bad news early.
Estimating work for the person who will do it The number does not match that person’s speed and knowledge. The person who does the work takes part in the estimate.

Summary in six lines

  1. An estimate is a forecast. A target is what the business wants. A commitment is the promise we give after comparing the two.
  2. At the start the range is wide. As the work moves forward, repeat the estimate.
  3. Break the work into small pieces and count the hidden work separately.
  4. For the unknown part, first do a short, time-boxed investigation.
  5. Estimate with three numbers and give the result with a range, assumptions and risks.
  6. Report delays early, and if time is short, cut scope, not quality.