Estimating, like anything in software development, is a skill. And it’s a HARD one.
No one begins their coding career already amazing at estimating. After years of experience, most of us end up merely mediocre at it. But we should strive for improvement because informed estimates are incredibly valuable.
I once had a boss who would say, “Estimates are lies.” Many developers hate estimating because they share a similar (albeit less extreme) sentiment.
But here’s the thing. ESTIMATES ARE NOT LIES.
My hope is that this post will show you the value of estimates — AND help you feel more comfortable with the process.
But before we dive in, why would you listen to me after I just said most devs are mediocre (at best) at this skill?
During my 10 years of consulting, I’ve had to estimate and sell most of my projects as well as track my time in 15-minute increments for billing. As a result, I’ve become adept at forming accurate estimates.
Many of the examples in this post focus on project-level estimates. But the information and tips below can also help with estimating at the sprint and task levels.
What’s an estimate? Let’s define it!
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.
An educated guess
An estimate is not a shot in the dark. We make estimates with the information available.
If we don’t have much information, we’ll make an estimate with high variance. Or we’ll make the estimate higher to account for the unknowns.
Based on past patterns
We lean on our past experience to inform future estimates.
For example, we can use the amount of time taken on a similar task to estimate how much effort a new task will take. And we can add time for parts we’ve never done before.
Let’s say you’ve submitted a form with a text field to an API before. You can use that point of reference to estimate how long it’d take to submit a form with a date field to the same API. In which case, add time for any date parsing you’d need to do.
Another past pattern we can draw from is our stakeholder’s behavior. If we know a particular stakeholder tends to increase the scope, we can add time to our estimates for them specifically.
How do we measure effort?
An estimate doesn’t necessarily have to be related to time. We can estimate with story points, rating 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 (or people-hours), which is the number of hours taken for a task. However, person-time and calendar time don’t always line up. A prime example is pair programming — just because two people are coding together doesn’t mean they go twice as fast.
I tend to calculate sprint estimates based on effort. But for project and SOW (statement of work) estimates, I usually go by person-time. (As an aside, product companies are able to lean on effort estimates more heavily than consulting companies.)
Defining the desired scope of work
Finally, when creating an estimate, we have to consider everything that must be completed to achieve the desired outcome. Said another way, remember to account for the “plumbing.”
For example, include all the work needed to show the button on the screen, not just the hours to put a button in the markup.
Know the purpose of estimations
Why do we estimate? There are three main purposes:
- Informs timeline, budget and staffing for project/task planning
- Sets realistic expectations between stakeholders and delivery team
- Promises to the stakeholders that the delivery team will communicate before the project goes off the rails
And that’s why estimates are not lies — they’re extremely useful for project planning.
If we know a project requires 12 weeks of work from two people but the client has a deadline nine weeks from now, we can choose to staff it with four people instead. This way we gain that extra few weeks of efficiency. (And notice that the delivery time isn’t cut in half even though we doubled the size of the team. 🙃)
Most important, estimates are an agreement between our team and our stakeholders. It helps us communicate expectations. And if we slip away from the original timeline, we’ll notice and won’t leave the stakeholder in the dark.
If they’ve added scope (scope creep!) or our assumptions were wrong, we may need a change order. Or we might reprioritize work. Regardless, we’re promising that we’ll have those conversations with stakeholders so they’ll always be in the know.
The reason for low/high estimates
You may have seen an estimate given as a range. Why?
Estimates will never be 100% accurate. After all, no one can predict the future. Range or low/high estimates can help set better expectations. They show what would happen in a perfect world versus the worst case scenario.
Ideally, the diff between the low and high should be <= 20%. The larger the diff, the more we need to learn for a better estimate.
Break the project down into smaller pieces
Whether we are estimating in story points or in person-time, how do we find “the number” to assign a task?
I like to think about the code we need to write in terms of layers. In fact, there are multiple 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 have to go into finer detail.
The data layer is your models and database. The application layer is the business logic that occurs in controllers and service classes. And the presentation layer refers to the UI stuff, both styling and user interactions.
View > Controller > Model
If the layering concept doesn’t work for you, you can 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. The model is the application and data models.
Backend > Frontend
If we’re doing even smaller estimates like sprint or task estimates, a three-tiered approach might be too heavy-handed. It may be enough to think just in backend and frontend layers.
Data > Persistence > Business > Service > Presentation
But if we’re working with a big, complex system, we might go even deeper. We can add a few more layers between our presentation and data layer.
I rarely have projects that require this level of detail. But projects that exceed 12 months might be good candidates (hopefully you don’t have to estimate too many of these 😬).
Let’s review an example
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 that my team worked on.
We had already built a UI that displayed images in a gallery. The stakeholder wanted users to be able to click on an icon overlaid on each image to add to or remove from a “Favorites” list.
We can break down this story into the following smaller tasks (remember, layers!):
Data
- Create a FavoriteImages table
- Implement ability to create a FavoriteImage for the current user and provided image id
- Implement ability to delete the FavoriteImage for the current user and provided image id
Application
- Create an API action that accepts the image id
- Toggle the “favorite”
- Return the favorite status to the frontend
Presentation
- 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
If we’re estimating in person-time, we gauge the hours for each one of these smaller tasks and add them up. If we’re estimating in effort, listing out all the smaller tasks ensures that we don’t oversimplify the story or forget anything.
Remember to account for often-overlooked tasks
In my experience, the most common estimation flaw is to leave out chunks of work and underestimate. Here’s a list of some areas you may tend to forget when estimating …
Discovery time
When estimating, we should be sure to account for discovery time. We almost always underestimate how long it will take us to get a solid understanding of systems, stakeholders and code.
For projects, this is at least one sprint. And for personal tasks, it may be one hour. Of course, discovery time depends on the scope, but we should always account for it.
Project set-up time
Account for the time you need to set up existing repos as well source control and project management tools. Consider the time to create new repos, configure the CI/CD pipeline and put in place any necessary infrastructure (such as databases, caching, error monitoring, etc.).
Browser support and responsive requirements
We need to add time if we’re supporting browsers besides the latest Chrome/Firefox versions. If you’re going to support legacy browsers, plan to multiply frontend estimates by 1.5 or 2.
Consider the responsive requirements as well. What devices and screen resolutions do the users primarily 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. This caused some UAT issues for a while. Then we made the app minimally responsive to account for the stakeholders’ needs.
Styling with CSS
CSS is not quick and easy like we tend to think.
How flashy are the designs? Writing fancy UI interactions or animations often takes longer than we expect. Always account for that in your estimates.
Greenfield versus post-production
If the project is greenfield, it’s important to add more time to cover all of the plumbing. Every little thing will be net new. Include the time to build all of the base components such as buttons, inputs, authed controllers, etc.
For post-production (legacy or maintenance) projects, we don’t need the extra time for setup. However, we should add more time for each task since we’ll be working within code that we didn’t write. And we don’t know whether the patterns already established will be especially suitable for refactoring and quick changes.
If we’re taking a post-production project, we should try to do a code review before we do an estimate so we have more information to draw from.
Bug fixes
Many of us forget to include time spent at the end of the project on final fixes.
If we’re estimating a project, we should leave at least 1 sprint for bug fixes. And if it’s a personal task, we should always plan for a bug or edge case that needs to be resolved before we can merge and deploy our PR.
Packaging the estimate
When we’re estimating stories in a sprint, we don’t need to worry about packaging our estimate for others’ eyes. We can add the story point estimate to the project management ticket and that’s it. But if we are estimating a project for a stakeholder (whether internal or external), we’ll want to provide more context for them to understand how we made our calculations.
This is especially helpful for non-technical audiences who tend to think that we are superheroes and can work much faster than we actually can. 🙂
Consider dependencies
If we are creating an estimate for anything larger than our task for the day, there is usually a dependency (or dependencies) for our work. We may be relying on something else to be finished and working correctly. Or something downstream is depending on our work to be finished on time.
Sometimes these dependencies will not change our person-hours estimate, but they could affect priority or scheduling. If two tasks are dependent on each other and need to be completed simultaneously, we may have to increase our estimate to account for extra coordination time.
In the cases where dependencies increase our estimate, we can give the stakeholder this context.
Document assumptions
When creating an estimate, we should always document any assumptions we are 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.
If something changes or we learn that we can’t reuse that functionality, we have something to point to. That way, the stakeholder can understand why we need a change order. Or why something is going to take more (or less) time than expected.
Document risks
Related to documenting our assumptions, don’t forget to document any risks.
For example, if our estimate is dependent on the stakeholder providing us resources in a timely fashion, we need to document that as a risk. Because if they don’t end up meeting expectations, the timeline may be delayed.
Itemize tasks
Like we did with our image-favoriting example, split the estimate into bite-size chunks and supply the stakeholder with that documentation.
You can break down one story into half-hour or hour-size chunks and document that. If you’re thinking bigger, estimate the stories in a sprint or divide the project into epics.
Even when I’m estimating six-month projects, I tend to estimate by the half-week increment and never estimate more than six weeks at a time.
Use this checklist to make estimating easier
Factors to consider
◻️ 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
◻️ Discovery
◻️ Project set-up
◻️ Itemized tasks/features/epics
◻️ Cleanup time
◻️ Bug fixes, performance optimizations, enhancements, timeboxed refactors
Remember to document!
◻️ Assumptions
◻️ Risks
◻️ Dependencies and scheduling implications
Now it’s up to you! Keep sharpening your estimation skills
An estimate will never be perfect. But it’s a useful tool for setting expectations and providing a framework to know when to course-correct.
And estimating is a skill that you can hone like any other. Remember, estimates are not lies! 🤗