From a developer’s point of view, the project manager is often the person in the back seat of the car asking, “are we there yet?” Only there are no roads where the developer is driving, and there’s a huge mountain sitting between point A and B.
If there was a road, or even a tunnel - then it might only take a few hours. But since the developer has no idea how to get to point B, it’s difficult to predict how long it might take to get there. So they pad a best case scenario “guess-timate” based on their past experience flying a plane through similar terrain. After all, that’s the closest thing they have to go off. They tell the project manager an arrival date, but as they start driving they begin to realize that the mountain is much further away than they originally thought, cars are much slower than planes, and they basically need to drive back to point A and pick a new path.
Estimating tasks is hard. Development is both a logical and a creative process, which often ventures into uncharted territory. And sometimes we make mistakes. If we’re using a new framework or technology stack chances are that we are probably going to do it wrong the first time. We might even have to refactor or rewrite.
Despite often feeling at odds with one another (and sounding like the start of a joke), the developer, the project manager, and the client are all working towards the same end goal. But, oddly enough, clients tend to want to know how much money and how much time something is going to take. We wish we could have unlimited time and budget and code to our heart’s content, but alas, estimates are an inevitable, if unfortunate, part of being a developer.
Research & prototype
In an ideal world, every project would have a discovery phase that includes time for developers to test out the software stack, or figure out the best architecture for a complex feature. Prototyping a quick “does-it-work” application could save a ton of time down the road. It allows the developer to figure out which path may be best, find pitfalls early on, and mitigate confusion on user requirements. It helps make the road a little bit less unknown.
If a project already exists, giving a developer time to explore the code base, or having someone walk through the existing pitfalls and any architecture decisions would be monumentally helpful. Project documentation is always helpful, but you never really know what you’re getting into until you’re knee-deep in the weeds of it all.
Expecting a developer to be immediately effective on a project that they have never seen before is an unrealistic expectation. So why expect them to give an estimate on new features on that same project without seeing it beforehand? Give the team an opportunity to do research so that they have more confidence when providing an estimate.
Better requirements & done criteria
We don’t want this to be a waterfall process where we define everything at the start of the project and expect nothing to change - but we also need a clearer picture of what we are building. The more we break down our stories, the easier it is to arrive at an estimate. In doing this, we limit the scope of the feature and define necessary subtasks. An added bonus is that everyone’s expectations will be aligned when the feature is complete. One of the strategies we employ to get better requirements is through user story mapping.
During the development phase, we break these user stories into cards (tasks) that define explicit and clear criteria. Similar to when writing clear bug reports, acceptance or done criteria on a card should be specific, focused, and testable. For example, if we were creating a contact us page our acceptance criteria might be:
- Name and e-mail appear as required
- Form validation for name and e-mail
- On submit form sends email to email@example.com
- On submit displays thank you message to user
Following the definition of our acceptance criteria, we can go one step further and define our definition of done, or done criteria. This will further break down all the steps that would be necessary before the task could be considered complete. For example:
- Unit test was created
- Code was pushed to GitHub and deployed to the test environment
- Functionality was tested
Each of these items may seem obvious when building a contact form page, but until we break it down, we might not be thinking about the various components required to make a complete contact us page. By breaking it down, we can better estimate the smaller tasks that will make up the larger estimate. For example, we might now estimate each subtask at 1 hour, when we may have previously guess-timated that a contact us page would take less than a couple hours worth of development. Following that, we need to write tests and consider deployment time. Once we write it down it will be more apparent to include the additional testing and deployment time which will add to our estimate time.
Risks & assumptions
Assumptions and risks not only help define a story, but they also justify things when they go wrong. Our estimate only holds true so long as we are provided with all of the necessary details. If we expected something but it didn’t happen, we now need to adjust our process, and therefore adjust our original estimate. By clearly defining and agreeing on assumptions and risks, you can weed out early problems and define who is accountable for what.
If we continue our contact us page example, we might have the following assumptions and risks.
- E-mail to firstname.lastname@example.org is not styled
- User does not need an email with their responses
- Client will provide page content
- Will only work with modern browsers
- May be target for spam as we do not have spam protection eg. Captcha
- E-mail to email@example.com may go into spam folder
It’s now clear that the client is responsible for providing us with content. Should that be delayed or not provided, we now need to re-estimate based on now we are responsible for writing the content, and the original due date of the feature needs to change.
The assumptions and risks won’t capture everything, but it will help define and shape a story. The clearer the tasks, the easier it is to estimate.
We like to meet with our clients often; and it’s in these meetings where we can go through and agree upon the acceptance criteria and the risks and assumptions. It’s also where we talk about the pitfalls, or where things are going wrong. The moment we are delayed or blocked by a risk or assumption, or we realize something has gone wrong (the mountain is much farther away than it appears), or we have more clarification on something, then we need to let our project manager know so that they can adjust the project plan and talk to the client.
Re-estimation is not ideal, but clear and honest communication with your project manager and client is the best way to build trust and allow for an adjustment in the plan before it’s too late. You have provided the best estimate with your initial information, and with new information comes a new estimate. The more information you provide, the easier you’ll make it for your project manager to adjust the plan. Clients are actually pretty understanding when you explain what the technical limitations are and propose solutions to work around it.
Estimates will never be perfect, but that’s all they are - estimates. Being good at estimation is not an easy thing. Through experimenting with a prototype, exploring a code base, defining requirements, setting expectations through risks and assumptions, and clear communication we can put our best foot forward in an effort to make reasonable estimates and adjust when necessary.