An engineer's guide to estimating software projects
Estimating software projects is hard. In my time spent building software, estimating when software projects will be done is probably the single hardest challenge I’ve encountered.
I’ve improved at estimating software projects over time, but sometimes it still seems impossible. Estimating software projects is such a hard problem that I’m not convinced that it’s not fundamentally impossible to be accurate. But...it’s definitely possible to be ‘less bad’ at it!
My thinking about software estimation changed a lot during a 3 year period when I ran my own business and clients would say: “I want you to build software X, how much would that cost?”. This placed the financial risk of the project running late onto me. Which forced me to take software estimation very seriously, and has changed how I’ve tackled it since.
Estimating is counterintuitive
There are many things about estimating when a project will be completed that are counter intuitive. Most people giving forecasts for the first time will fall into a number of traps and make forecasts which turn out to be very wrong.
This makes experience very helpful when estimating when a project will be done by. But there are some tips and tricks to help avoid common pitfalls.
Most software takes longer to build than people, including engineers, think. The time software takes to deliver is nearly always a normal distribution, skewed to the right, with a long tail.
“When will this be done?” is a reasonable question to ask
“When will this be done?” is a short, simple question, the answer to which is extremely difficult. This asymmetry irritates some engineers - it shouldn’t.
It’s a completely reasonable question! If you had a plumber visit your house you’d likely ask: “How long will this take and how much will it cost?” - if they said “Dunno...” and shrugged, you’d find that annoying. Having a forecast is helpful for people, even if it ultimately turns out to be wrong. If you were in their position, you’d be asking the same questions!
Refusing to give estimates or padding your estimates excessively isn’t a good response.
Giving forecasts is adversarial by nature
When you forecast when a project will be done, you usually present the forecast to a stakeholder e.g. a client, manager or another department.
Stakeholders typically want to believe that the project will take less time, rather than more time. This is because they want to do more projects this year, or deliver the software earlier. They also often tend to be overly optimistic.
It’s possible to keep your stakeholder happy in the short term by saying: “Sure, we can build that operating system in 2 months”. However, 2 months later when it becomes clear this was completely unrealistic, they’ll be understandably mad with you. So you’re really just deferring the pain and setting everyone up to fail.
If you go the other way and say: “I’m afraid generating that CSV file will take 5 years.” and pad your forecast too much, you’ll lose credibility with your stakeholder and it’s likely they’ll be mad at you for being unreasonable.
Imagine you were gifted with a super power. Rather than the power of flight, you had the ability to correctly forecast any software project you encountered. What a gift! Even with this perfect software estimation gift, I guarantee you’d run into many situations where your stakeholder would be very unhappy with your estimates, even though they’re perfect (you have the gift!). This is because stakeholders are naturally optimistic and software takes longer to build than stakeholders (and engineers!) intuit it will take.
This means you need to give a forecast and you’ll need to be able to justify your forecast. The gift of perfect software estimation is not enough on it’s own.
Build a model so you can forecast
When it comes to estimating projects, think of it like the weather forecast. Weather forecasters have a weather model, which like all models is imperfect, and sometimes they get the weather forecast wrong. Which is why it's called a forecast! To estimate when a software project will be done, you too need to build a model, so you can forecast when it might be finished. This model is uncertain and will have error bars attached to it.
Software estimation models have inputs which are put together in some sort of calculation to calculate the date a project will be done by.
The accuracy you want from a model depends on the situation. Sometimes it’s critical you’re accurate because there are serious consequences for being late, e.g. a regulatory deadline. Sometimes you and your stakeholder will have a high degree of trust, perhaps you’ve been working with them for 10 years, and have a track record of delivering on time (or likely, not being too late, this is software after-all!).
Coming up with a model which is more accurate takes a little longer and takes more effort.
Sometimes a fairly crude model will do. Spending half a day estimating some tasks and multiplying by 2, is crude. But if you pick the right multiplier for your team, probably won’t turn out that wrong (all models are wrong anyway). The problem with a model like this is that even if the model is quite right, to people who aren’t familiar with the skewed right nature of software development, this looks unreasonable, it looks like you’re padding your estimates.
A more accurate model helps you justify the output of the model. It switches the conversation from an adversarial negotiation to a conversation about what’s wrong with the model.
There is a tradeoff here: time spent estimating is time you could be spending building the software. This also works less well if you’re trying to estimate many months of work upfront, because time spent doing detailed planning might be wasted when the project plan inevitably changes later.
Deciding the scope of the software
Before you can estimate with any accuracy how long it will take to build some software, you need to understand well what that software needs to do.
If you asked a builder to estimate how long it would take to build a house, but just told him: “It’s a big house, with 8 windows, a front door and a back door”, they’d laugh at you. Software is no different.
If you don’t know what the software that needs to be built does, than you cannot accurately estimate how long it will take to build.
It’s your responsibility to define the scope, engineers are the only ones who know what is / isn’t relevant to the build time. I recommend asking as many questions as you like until you accurately understand what needs to be built, until the point where you could sit down and actually build it.
Your model will contain multiple inputs, here are some I recommend you add to your model
Let’s start with obvious things:
- How many engineers will work on this project?
- Are they working full time on this project (they don’t work on 2 projects at a time?)?
- Do they have vacation scheduled?
However, there is another input which often gets overlooked:
How many days of work does this engineer complete each day they come to work?
No engineer wakes up in the morning and spends 100% of their working day working on projects. They’ll check email, get coffee, attend meetings etc. .
So the input ‘how many days of work does this engineer complete each day they come to work’ will be somewhere between 0 and ~0.9.
The most reliable way to come up with this number is to look at past data. For example, if you have estimates of work and how long it took an engineer to complete it. Or you can guess based on intuition.
If you’re making an educated guess on this number. Think about if the engineers have other things they do, or suffer from frequent interruptions, which will drag this number down.
Skill will also factor in here. A more experienced engineer might get more ‘days of work’ work done in a day than a less experienced engineer.
What is the size of the work that needs to be done to complete the project
This is the part you likely think about when estimating a project. It’s tricky to forecast this accurately.
Why do people get estimation wrong
I’ve noticed a couple of places where I've gone wrong estimating tasks historically.
Let’s imagine you’re estimating a task and you break it down into a list of subtasks that need to be completed.
Estimates tend to be off because:
- 1) There’s an unforeseen problem with one of the subtasks
- 2) You forget entire subtasks from the list
1) Is annoying and can be hard to predict. But in my experience 2) is a much bigger problem.
If you forget some subtasks, this really adds up and blows out your estimate big time. And you’ll look back at your estimates and think: 'Well of course we couldn’t deliver the project without a task for: “Releasing to the App Store”'.
Most of the techniques I use to estimate are to help me spot instances of 2). You won’t catch them all, but in a few minutes of effort you’ll often find a bunch of work that ‘obviously’ you need to deliver to complete the project, but you overlooked when you estimated off-the-cuff.
Levels of estimation accuracy
Let’s look at some different ‘levels’ of estimating the work:
Ultra - Do the work
It’s extreme. But if you sat down for 1 month and did all the work and then proclaimed: “It will take 1 month, I know because I just did it!” This is 100% accurate, but this estimate is late since it was delivered with the work!
In practice this isn’t very useful, because it’s not an ‘estimate’ at all since you’ve done the work!
Very High - Do a pathfinder PR
Do the work like it’s a hackathon. Build a proof-of-concept that makes you confident you could sit and do it properly later. You’ll likely learn some things you hadn’t realized before, resulting in a very accurate estimate.
This takes effort and time, it also involves lots of context switching which can be inefficient. I usually use this technique on a piece of work which is particularly uncertain or has large tech risk.
High - Write a detailed list of subtasks required to complete the work
This is my favorite way of accurately estimating. I’ll write a very detailed list of tasks, no task in the list should take more than ~3 days. If a task is too big I’ll break it into sub tasks until no individual task is > 3 days. I imagine doing the work in detail, roughly what code I’ll write.
For me this is like a sort of simulated ‘Ultra’ from above. It’s not as accurate but it’ll take 20 mins instead of a month.
Medium - Write a high level list of things that need to be done to complete the work
Breaking the task into smaller subtasks but perhaps some of the tasks are weeks in length. You’re not simulating the work so much in your mind. This leaves you open to forgetting nitty gritty tasks that might take up time. It’s quite easy to be over optimistic.
Low - Educated guess and assign t-shirt size
This takes about 10 seconds: "Yep, that might take 3 weeks".
This is very low effort, and obviously the least accurate.
Sometimes ‘Low’ is fine. But if your stakeholder wants higher certainty estimates on a project for whatever reason and you’re estimating on ‘Low’, this is probably not a good idea!
I think a lot of engineers like estimating on ‘Low’ because they don’t like estimating, they like coding (me too!), and estimating doesn’t get the project done. Don’t fall into this trap though.
Representing estimation uncertainty
No matter what level of estimation you decide to use, they’re not certain, they’re an estimate.
Each one could be presented by a curve which is skewed to the right with a long tail. However until you’re presenting your estimates to a statistics professor, it’s probably better to represent this uncertainty as a range.
Personally I like the minimum (5th percentile), average (mean) and maximum (95th percentile) time the task will take.
A task you think is a (min: 1 day, average: 2 day, max: 3 day) is less risky than a (min: 1 day, average: 3 day, max: 7 day) task.
You’ll normally have a good idea for the tasks where the spread should be a little wider.
Some stakeholders don’t like this granularity and say: “Just give me a number / date” - , that’s fine, you can aggregate your numbers down to a single number if they can’t cope with seeing 3 numbers. This aggregation is really part of the model itself. I recommend picking a number between the average to max numbers.
Even after all the pessimistic assumptions so far, I still think at this point it’s a good idea to add some extra buffer.
The chances that part way through the project you realize: “Oh wait we totally don’t need to build this bit, this will save us loads of time!” is slim.
The chances that part way through the project you realize: “Oh %&$ we totally forgot about this extra work none of us had foreseen, that’s going to take a month to do!” is pretty large.
If you add 0 contingency, you’re making the assumption that absolutely no unforeseen work comes up over the length of the project. This is probably not a good assumption and is overly optimistic.
I recommend adding a contingency multiplier e.g. x1.3 to all the work you estimated. To assume you discover there actually an additional 30% of work you need to do to complete the project.
Communicating the model to your stakeholders
Now you’ve built your model, you need to present it to your stakeholders.
Depending on your relationship with the stakeholder you can look at the model together, they may disagree with the model's inputs, and that’s ok, it’s much easier to discuss individual inputs than:
your_gut_feel x 2.3!
Don’t be tempted to tweak the input parameters to try and match a date someone has in mind. Long term it’s easier to have a hard conversation now.
List the assumptions / problems with the model explicitly and put them with the date you commit to.
Depending on the stakeholder you might be asked to ‘commit’ to a single date. Projects take a long time and all the caveats and assumptions will quickly be forgotten. Try to keep the dates and the inputs / assumptions together. Summarize the inputs you think are dangerous right next to the date - so you can point back to it if things start to slip.
The advantage of using a detailed model is that you are explicitly making assumptions. And it’s hard for a reasonable stakeholder to argue against things like: “Engineers actually only do 80% programming from 9am-5pm” or “Adding no contingency to estimates means the project will be late if we find extra work”.
Handling timeline slips
Once the project gets underway you should carefully monitor whether any of your model inputs change. For example:
If you assumed 4 engineers are working on the project and one of them gets pulled into helping on another critical project.
Your model inputs have now changed. Rather than 4 engineers you have 3.3 engineers. You need to update the model, recalculate the date and communicate the date change to the stakeholder when it happens.
Don’t wait until later and say: “Remember when you pulled that engineer off the project 3 months ago, that’s why we’re late.”, this sounds like an excuse. Instead be proactive: “Michelle isn’t working on the project any more, so I’ve adjusted the model, here’s the new date”.
Input changes aren’t always obvious. You might be told: “Michelle is helping with another critical project for 3 months.” It’s implicit that Michelle won’t be doing 2x the amount of work, so she won’t be working on your project full time. Stay vigilant!
I think good engineers often feel personally responsible for slips and compensate by working harder. In reality you and your stakeholder have a joint responsibility. The engineering team has the responsibility to deliver the software on time. But if the stakeholder does (sometimes subtle) things that invalidate the model and make it impossible to deliver on time, you should make it clear to them the choices they’re making when they make them.
Examples of model input changes:
- Removing/switching engineers on the project
- Asking engineers on the project to work on bits of work not related to the project
- Adding scope (more work → more time!)
- An estimate you made turns out to be very wrong
In all cases you should point out things have changed as close as possible to when things change.
The stakeholders are often not acting in bad faith when this happens. They’re human and they have competing priorities. But there is a cognitive bias that happens which means that the committed date gets remembered, but the engineers working on other random requests gets forgotten. It’s your job to keep them honest!
Estimating further into the future is even harder
The longer the project the harder it is to estimate upfront (we in the biz call this: waterfall!). However it may still be a reasonable question for someone to ask.
It’s hard / suboptimal for a few reasons:
First, putting together estimates is work, it requires effort and takes time. Time that could be spent doing more useful work on the project. Also, things change, and planning work that will be done in 6 months time is a risky business. It risks wasting time estimating work which subsequently never gets done, or your estimates are somehow invalidated because the world changes.
Estimating far ahead can mean missing deadlines for multiple milestones. If you break your project into thirds, if the first third is late, the second and third chunks are now also late (even if they were estimated correctly!).
The best advice here is to try and change the game and not formally commit dates for anything more than a few months away. But in some scenarios, this may be impossible, in this case failure is probably just unavoidable.
Estimating software is hard, I think it’s probably the hardest part of being an engineer. But it is possible to be less wrong.
Cheatsheet for more accurate estimates:
- Remember engineers:
- Take days off
- Aren’t 100% efficient!
- Task estimates
- Should be estimated as a range
- Simulate doing the granular tasks in your mind to find tasks you missed
- Don’t be tempted to do ‘Low’ T-shirt sizing because it’s easier if your stakeholder wants accurate estimates
- No contingency means no unexpected work that was ‘forgotten’ / unexpected
- Try to only estimate / commit a few months ahead if you can