Estimations are important, but they are just part of equation. We do our best to make them as accurate as possible, but they are not as important as planning and updating plan.
At first, client specifies a goal, like:
In order to reach given goal, we come up with a set of steps towards it. This set of steps is a plan. Plan always depends on context - set of people in your team, available tools, etc. Estimations just tell us how much time each step will take.
Now there's one thing about estimations - they are never 100% accurate. There's always some tasks that take more time then expected (by the way, it's far more rare case that task takes less time, so it's not Gaussian distribution). There's similar thing about context and goal - something always changes. Developer might get sick, client might want to ask for completely different set of features based on meeting with investors and so on.
When something goes wrong, there's just one thing you can do: update your plan given new situation. The worst possible thing to do wold be to continue doing what you were doing hoping that it will figure it out itself.
Workflows we are using are built to optimize two things:
When initial plan is made, we split project into features. Those are functionality pieces that can be deployed and seen by client. Each feature is estimated in t-shirt size (XS - XXL). We have a reference scale that allows to assign sizes pretty quickly. Using our statistics from past projects, we can convert sizes to hour ranges. This approach works surprisingly well for initial estimations and allows to see if we meet business requirements early in the process. Range as a result is also a good thing - there's some place for maneuver in case features change a little.
Each developer receives couple features at the beginning of the sprint. By this time we have detailed spec and feature can be split into smaller steps. Each step is estimated in hours, up to 4 hours each in our case. It's simple to catch possible problems at this stage:
We use our statistics engine to adjust tasks estimations at this point, which makes things even more predictable.
Our approach allows to make readjustments at such points:
As feature is discussed in details, it's easy to observe if feature size is different from initially assigned one. It's very cheap to replace or adjust feature itself at this stage.
When individual tasks don't fit into feature range - we can come up with different implementation approach, rearrange other tasks in sprint and of course adjust feature. Feature update is not as cheap as in previous step, but still is much simpler than when feature is almost done.
Overtime on individual task is not often, but still happens from time to time. Usually it's enough just to review implementation approach and still meet feature estimation. When different approach doesn't help and more time is required - we're still in good shape: at this point we still have time allocated for this specific feature and we have time left for sprint, so it's easy to avoid last minute panic before deadline.