I sat down for about 15 minutes before I could even write this sentence.
You see, as human beings, we (usually) tend to think too much before we speak.
As programmers, we (usually) tend to think too much before we write our first line of code.
“But what if the programmer will send null?”
“What if the programmer will send string when I expect int? should I throw an exception?”
“Should I return int or maybe void will do?”
“Should I implement the feature in this class? maybe I should use some external object and implement it there?”
“Should I inherit from this class or encapsulate it?”
We tend to over-think stuff. That’s the way we are wired.
Tell me if you can relate to this monologue:
“ I’m putting a lot of effort in finding solutions to many problems before they appear. These effort makes me tired so a few “end-cases” still slips me by; This, of course, only makes me think more before I write my code. Little, not-more-than-1-day-max missions turn into “Projects”. The frustration when something breaks for unknown reason is sky-high as I spent 1-2 days just to think about how to avoid these bugs! I simply don’t have enough time. I’m working like hell but the day is just too short and I’ve got too many tasks to complete. “
I remember sitting with my last team leader, Pasha, in the office one evening(~3 years ago), after spending 12 hours in refactoring something that never actually worked; His words were: ” Oren, you fell in love with your code. You’re spending way too much time on things that… are not really important at the moment…. If you keep it up this way, you’ll never finish your task. “
I remember my response, his words were like a knife in my heart: ” Hey! I put my guts in this code, I’ve stayed the all week for more than 14 hours per day! I even sat at home during the weekend and worked on this task just to keep up with the deadline! you can’t tell me that this is not important! Someone can use this some day! And the design is so extendable! “Not really important…” (bad, bad, dirty thoughts) “.
He was right. I couldn’t make the deadline. It was a battle I couldn’t win; I had to much work and almost no time at this point.
I remember that day like it was a few hours ago. I couldn’t sleep the all night. I kept running scenarios in my head and analyzing his words. I thought about the way I worked until that point, about the times I managed to complete my tasks in time and those times I worked extra hours and still miss my deadlines. I could really see what he meant. I wasn’t able to think in small tasks. I connected every little piece of code with 1000 other usages “that could be used someday”. I thought that I could make it all work at once. I thought that I can prevent bugs from happening. The reality proved me otherwise.
I knew that I can get better, so I set my mind on “think less, do more”. I needed some basic rules to contain my need to over-think, so I use these simple rules to make my life easier:
- I refactor only when I see a tangible reason (2 places with the same code).
- I think in small “Contexts” (=tasks). No context should be bigger than 1-1.5 days of work.
- I’m trying to WIN *small* battles.
- I write some API usages, test that API with my programmers (to see if it’s comfortable enough) and only than starting to code it.
- I participate others when things get a little more complicated than they should be.
- I write my milestones on my white-board so I could look at them during the day.
This is the mantra behind TDD.
TDD is about letting things go. To Work in small tasks and most importantly:
Let the *code* prove you wrong, not your thoughts or fears.
I don’t have a bug until I can write a test that proves me otheriwse.
With this said, we can now start practicing TDD. Let’s write NameResolver class.
* As this post turned to be quite long, you can see the example here.
clarification: if it wasn’t obvious, the simpleminded is yours truly.