Have you ever tried to solve a Rubik’s cube and been unable to complete it? I once tried several times during a long bus trip and felt pretty bummed after failing every time. Then I learned that there are kids out there that can do it in seconds! How is that even possible?
Update: Mia Li was kind enough to offer a Chinese translation of this post here.
When you, as a programmer, start a new project, you will often not know full well how to do it, for many reasons. But you are a professional, and you’ve completed similar tasks in the past, so you either try to figure it out, or find someone who can, and ask them how, or just google it.
Very often, you do not know you’ve found yourself in this dilemma until it’s right in front of you.
Here are some examples:
- You have to re-implement something using a new framework or library
- A library you’re trying to use doesn’t like the other library that you’ve been using
- The API you’ve been integrating doesn’t do something you thought it should do
- The framework you’re using doesn’t like unit tests and the ones it has are actually integration tests
- You thought a model in this new framework was a singleton like in the other one but it’s not
Estimating unexpected complexity
“Can you estimate these new tasks for me?”, asks your boss. Remember that Rubik’s cube you couldn’t solve? How many hours do you think it would take you if you gave it another shot?
“What? Two days?”, “But our previous developer could do that in a couple of hours! No way it will take you that long.”
There is actually an algorithm you can learn that, with practice, will help you solve a Rubik’s cube very quickly. But you don’t know that right now, and there is no way to know that you are going to find that, and that it won’t really take you two days to figure it out.
Complexity is cumulative
There more tasks a project has, the more likely that you will run into this kind of situation, so if you do not severely overshoot your estimation, there is really no way to be sure that you’ll deliver on time.
Let’s do some crude napkin math to visualize this a bit better. Say that you are an experienced programmer, and you only run into unexpectedly complexity about 5% of the time. If you are starting a new project and split it up into 10 tasks…
1 - (1 - 0.05) ^ 10 = 0.40
Or: there’s a 40% chance that you will run into a complex task, and blow your estimations for this project.
“Why are projects always behind schedule?” backs this up with more math and with actual project metrics over 70,000 hours of work, so check that out if you’re interested.
Creative vs mechanical tasks
“The creation of genuinely new software has far more in common with developing a new theory of physics than it does with producing cars or watches on an assembly line.” – T. Bollinger
The problem comes down to the difference between tasks which require a lot of thinking, and routine tasks which you already have some practice with.
In “Software has diseconomies of scale“, there’s an interesting argument being made about what this difference has on productivity. For creative tasks, the more of them you have, the more time each one will take, whereas mechanical tasks have the opposite effect, they can often be automated to some extent.
It doesn’t seem possible to estimate these creative tasks with reasonable accuracy at all, and not even proficiency or experience can help you here. Think about it, would it really have made sense to ask Einstein how long he would take to find a unified theory of physics?
The best you can do is estimate based on historical metrics which, in software as in the stock market, is not worth very much.