This post has been updated in more recent posts on the blog
Estimating, like anything in software development, is a skill. No one starts their coding career good at estimating and most of us end up only mediocre at it after years of experience. Estimating is HARD. But that doesn't mean we shouldn't strive to get better because informed estimates are incredibly valuable.
I once had a boss who loved to say "Estimates are lies." And I feel like some developers hate estimating because they share a similar (albeit less extreme) sentiment. I couldn't disagree more. I hope that after reading this post, you'll see the value in estimates and feel more comfortable estimating.
Before we dive in, why should you listen to me after I said most devs are mediocre (at best) at estimating? Estimating is something I feel extremely confident in. After 10 years of consulting; having to estimate and sell most of my projects; and tracking my time in 15-minute increments for billing; I've had the surprise benefit of getting really good at accurate estimates.
This post talks a lot about estimates in the abstract. A lot of the examples are going to be focused on project-level estimates but everything discussed should also apply to sprint and task level estimates.
What is an estimate?
In the broadest sense, an estimate is
An educated guess based on past patterns of the amount of effort required to complete the desired scope of work
We estimate with the information that we have available. It’s not a shot in the dark. If we don’t have a lot of information, we’re going to have an estimate with high variance. Or the estimate will be sky-high to account for the unknowns. Both of these cases are informative.
We lean on our past experience to inform future estimates.
For example, we can use how long a similar task has taken us to guess how much effort a new task will take. Then we can add time for the part(s) we've never done before. Let's say we've submitted a form with a text field to an API before. We can use that point of reference to estimate how long it would take to submit a form with a date field to the same API. Then we can add a little time for any date parsing we'd need to do.
Another past pattern we can draw from is our stakeholder's behavior. If a stakeholder always adds scope, we can start adding time to our estimates to make them more accurate for this particular person/group.
Amount of effort
Philosophically, an estimate doesn’t have to be related to time. We can estimate pure effort such as when we do story points. Story points rate the relative effort of work in a Fibonacci-like format: 0, 1, 2, 3, 5, 8, etc.
We can also do traditional person time estimates. Person time (or man-hours) is the full number of hours a task might take someone. But, person time and calendar time don’t always line up, particularly when we’re pairing. When 2 people are coding together, they don't go twice as fast.
I tend to use effort estimates for sprint estimates but person time for project and SOW (statement of work) estimates. Product companies can rely on effort estimates more than consulting companies. They have different revenue streams (which we can get into if you want but is a whole other topic).
Desired scope of work
Finally, we need to think about everything we need to do to get the desired outcome. We need to account for all the “plumbing” that needs to be in place to show the button on the screen. Not just the hours to put a button in the markup.
An estimate serves 3 main purposes.
- Informs timeline, budget, and staffing for project/task planning
- Sets realistic expectations between stakeholders and the delivery team
- Promises the stakeholders that the delivery team will communicate before the project goes off the rails
And this is why estimates are not lies.
Estimates are invaluable for us to project plan. For example, we know a project requires 12 weeks of work from 2 people. But the client has a deadline of 9 weeks from now. So we may choose to staff 4 people on it to gain that extra few weeks of efficiency. Notice this plan doesn't cut the delivery time in half even though we doubled the size of the team 🙃
Estimates also help set expectations with stakeholders. If we tell them the project will be done in 9 weeks, they won’t be wondering what’s taking so long at week 4.
Most importantly, estimates are an agreement between us and our stakeholders that we have an idea of how long something will take us. If we notice that we're slipping from that expectation, we will communicate with them. We won’t leave them in the dark.
We may need to get a change order if they’ve added scope (scope creep) or our assumptions were wrong. Or we may need to collaborate to reprioritize work to make sure the important stuff gets done in time. But we’re promising that those are conversations we’ll have with them and they’ll always know what’s happening.
You may have sometimes seen an estimate provided as a range. Why is that?
Estimates will never be 100% accurate. They are predictions and no one can predict the future. We use low/high or range estimates to set better expectations and account for perfect-world vs. worst-case-scenario. Ideally, the diff between these numbers should be <= 20%. The larger the diff indicates the more we need to learn before we can do an accurate estimate.
Creating an estimate
Whether we're estimating in story points or in-person time, how do we find "the number" to assign a task?
How do you make a cute fall outfit? Layers!
How do you make a cake even yummier? Layers!
Why is Shrek so lovable? Layers!
I find that thinking about the code you need to write in layers is super helpful when creating an estimate.
There are many ways to break down a project or feature into layers.
Data > Application > Presentation
My preferred layering strategy is Data > Application > Presentation. Most of my projects are small enough in scope (3-6 months) that I don't usually need to think in finer detail than that.
The data layer is your models and database.
The application layer is the business logic that occurs in controllers and service classes.
And presentation layer refers to the UI stuff, both styling and user interactions.
View > Controller > Model
If that layering concept doesn’t feel right for you, you could also think in MVC (model, view, controller). The view is the stuff in the frontend (and sometimes what’s returned by your API if you have one). The controller is exactly what it sounds like. And the model is the application models and data models.
Backend > Frontend
If we're doing even smaller estimates like sprint or task estimates, that 3-tiered approach might be too heavy-handed. Thinking in backend and frontend layers may be enough.
Data > Persistence > Business > Service > Presentation
And when we're working with a big, complex system, we might have to go even deeper. Adding a few layers between our presentation and data layer separates concerns even further. I rarely have projects that need this level of thinking. But projects that exceed 12 months might be good candidates. Hopefully, you don't have to estimate too many of these 😬
As a user, I want to "favorite" an image
Let's take a look at how we might break down an estimate for the above user story. This is a real story that my team had to work on. We had already built a UI that displayed images in a gallery for users. They wanted the ability to click on an icon overlaid on each image to add it to or remove it from a "Favorites" list.
We might break down this story into the following smaller tasks (remember: layers!)
- Create a FavoriteImages table
- Add ability to create a FavoriteImage for the current user and provided image id
- Add ability to delete the FavoriteImage for the current user and provided image id
- Create an API action that accepts the image id
- Toggle the “favorite”
- Return the favorite status to the frontend
- Add an overlaid icon
- On click, send the image id to the API
- On success, update the icon based on favorite status
- We’ll need 2 icons
- Read favorite status on page load to render the icon correctly
When estimating in person time, we can estimate the hours each one of these smaller tasks would need. Then add them up to get the initial estimate.
When estimating effort, listing out all the smaller tasks is still valuable. It helps make sure we're not oversimplifying the story or forgetting any necessary work.
When estimating, there are often chunks of work that get overlooked. This leads to serial underestimating, the most common estimation flaw in my experience.
We should be sure to account for discovery time. We tend to underestimate how long it will take us to understand the systems, stakeholders, and code. For projects, this is at least 1 sprint and for personal tasks, it may be 1 hour. It depends on the scope but we should always account for time to gain an understanding of the scope of the ask.
Project set up
We should account for time to set up existing repos or set up our source control tools.
- Creating new repos
- Configuring the CI/CD pipeline
- Setting up necessary infrastructure (databases, caching, error monitoring, etc)
- Project management tools, if needed
Browser support and responsive requirements
If we need to support legacy browsers, plan to multiply our frontend estimates by 1.5x or 2x. We forget that things don’t behave the same across different browsers. If we need to support something outside of the latest versions of Chrome/Firefox then add time for that.
What devices and screen resolutions do the users use? What about edge cases? If 2.5% of users have iPhone X, are we testing those screen sizes?
What devices and screen resolutions do our stakeholders use? I've had projects in the past where the project stakeholders had very different screen resolutions than the primary users. It caused UAT (user acceptance testing) issues until we realized that we should make the app minimally responsive to account for them. Even though their users used a very different screen resolution.
CSS is not quick and easy like we tend to think. How flashy are the designs? How flashy do we want them to be? Writing fancy UI interactions, animations, or any interesting design takes longer than we think. We need to always account for that in our estimates.
Greenfield vs post-production
If the project is greenfield, we’ll need to add more time for all the plumbing since every little thing will be net new. We need time to build all the base components (buttons, inputs, authed controllers, etc). But once things are set up, we save time later since we trust our team to build well-tested, well-architected, reusable code.
For projects that are post-production (legacy or maintenance), we don't need extra time for setup. But we need to add more time to each task since we’ll be working with code that we didn’t write. We don’t know if the established patterns lend themselves to refactoring and quick changes. We should do a code review before we do an estimate so we have more information to draw on.
We always forget to include time at the end of the project for final fixes. If we’re estimating a project, this should be at least 1 sprint, maybe more. If it’s a personal task, we should always plan time to resolve a bug or edge case before we can merge and deploy our PR.
Packaging the estimate
When we're making an estimate for a sprint story, we don't need to worry about packaging it for others' eyes. We can add the story point estimate to the project management ticket and that's it. But if we're estimating a project for a stakeholder (internal or external), we need to provide more context for them. We want them to understand how we calculated the estimate.
This is especially helpful for non-technical audiences. They tend to think that we're superheroes and can work much faster than we actually can 🙂
If we're creating an estimate for anything larger than our task for the day, there's usually a dependency (or dependencies) for our work. Either we're relying on other finished work to be behaving correctly. Or something downstream is depending on us to finish our work on time.
Sometimes these dependencies will not affect our person-hours estimate of how long something will take. But it could affect priority or scheduling. It's good to be aware of for our estimate.
If two things that are dependent on each other need to happen at the same time, that may increase our estimate by quite a bit. We need to account for the extra coordination time between the two workstreams.
Like we did with our example above, we should break down the estimate into bite-size chunks. The more we can chunk up a feature, the more accurate our estimate tends to be.
If you're starting to practice your estimation skills, break down 1 story into half-hour or hour-size chunks and document that. If you’re starting to think bigger, try to estimate the stories in a sprint. Or break a project into epics and estimate that. Even when I'm estimating 6-month projects, I tend to estimate by the half-week increment. I never estimate more than 6 weeks at a time.
When creating an estimate, we should always document any assumptions we're making. If we find ourselves thinking “oh that should only take a day because we’ll reuse this existing functionality from over here” then we should DOCUMENT THAT. Then we have something to point to for why we need a change order if the scope changes. If we learn that we can’t reuse functionality, we can explain why it's going to take longer than expected.
Related to documenting our assumptions, don’t forget to document any risks that we see. If our estimate is dependent on the stakeholder providing us resources in a timely fashion, we need to document that dependency as a risk. If they fail to meet expectations, it will push our timeline. This could cause us to be unable to deliver on our estimates. Documentation is risk mitigation 🙂
Things to consider to inform your estimate
- Greenfield vs post-production
- Server framework and language
- Team familiarity?
- Client framework and language
- Team familiarity?
- Required browser support
- Responsive requirements (devices and screen resolutions)
- CI/CD and infrastructure requirements
- Stakeholder education, training, hand-off
Items to estimate
- Project set up
- Itemized tasks/features/epics
- Cleanup time
- Bug fixes, performance optimizations, enhancements, timeboxed refactors
Don't forget to document!
- Dependencies and scheduling implications
An estimate will never be perfect. But it's a useful tool for setting expectations. And it provides a framework for us to know when to course-correct.
Estimating is a skill that you can build just like any other. Estimates are not lies 🤗