Why TDD is hard to use?
I love TDD now, but when I started practicing I thought this was not for me, the majority of people who hate TDD think as I thought at the beginning o
I started practicing TDD because the company where I was working hired a Tech Coach. The person who hired him left the company the same day he started, so he didn’t know what to do.
So I knew him and we started working together, it was just luck for me, I was in the correct place at the correct moment.
I remembered him pushing me to write tests firsts and to write code later to pass the tests, at the beginning I thought he was crazy.
It was really hard to think first on a test to demonstrate that my code would do what we wanted to do.
TDD was moving me from my comfort zone, I didn't like it because:
My ego, I know how to solve it, why do I need to write a test to guide me?.
I usually broke a lot of things and make them work later, I loved the feeling of the Eureka effect!!.
It’s harder to write the tests than to write the code.
I don’t know what means to solve the whole problem, I can understand it better while I’m writing it, breaking things.
My ego
Big Upfront Design is what 90% of people in the industry think software design means.
I have been taught to think deeply in to solve big problems at once, without writing any code. In some sense, I saw myself as a genius, one that can solve big problems no one else can solve.
I loved that feeling of creating a perfect design in my mind, but there was a problem, as you know, everything written on paper compiles.
Reality is another thing, it doesn’t matter if I could control all the variables there was one I couldn’t, time, I don’t know what will happen in the future, if one of my assumptions changes, my design sucks. And this happens 99.9% of times.
I learned that it doesn’t matter what can I do, I cannot control what will happen tomorrow, so my design needs to be simple and needs to change. That was the only way to minimize the impact of making one of my decision wrong.
Breaking things
Before my TDD days I usually broke the code to introduce a new feature, then I was hours debugging and doing small changes to validate manually that things were working.
So my code was broken for days, this is like food for bugs.
When everything was working I created a test per each class that was really coupled to the current implementation, usually one test per each public method, perhaps two but nothing else.
This approach had several problems, it is really easy to introduce bugs because I was not checking a good set of cases, just some of them. My tests make all my code hard to change because they were very coupled to the implementation.
And I was really slow solving the problem because the real tests were manual tests, a lot of times my code was rejected by QA’s (or even worse by customers in production) because we were not covering some edge cases, so I started again in the cycle, rework was the norm.
But this approach has an addictive component, when I thought the code worked I felt the Eureka effect. I was a genius solving that edge case, patching my initial design.
The next day, another edge case was there to break my code and move me from the God's Paradise to my office desk. This was stressful, I felt that I was not able to advance.
So this guy was telling me, it is possible to write code, so you don’t need to care about what is going to happen tomorrow because it will preserve the characteristics you are interested in today. He was telling me that I was lasting my time, how in the hell I can believe him?
Complicated tests
I wanted to write a test to solve the whole problem at once, this is really hard to do, because as I said I don’t know what means to solve the whole thing.
This is one of the hardest part of TDD, I found myself trying to write a test with a database, an HTTP controller and a lot of logic to make it pass.
I wanted to do upfront design, I tried to mimic what I was doing when I wrote the tests after. Difficult to do this, it is required even more upfront design that the one I usually did.
This is why I thought, this is not for me, I need to stop doing this.
But I have a defect, I cannot leave a problem out if I know it can be fixed, I have to fix it. Some people love TDD and think it’s the best thing it happened to them, why I cannot use it?.
Nobody calls me chicken.
What is the problem to solve?
I thought TDD cannot work if you don’t know what you need, how in the hell are you going to write a test if you don’t know what should be the result?
The point is if you don’t know what you need why are you writing code, is it because you are trying to experiment, then you know what you want.
The problem is that you want to change it later, take that into account.
All of these questions are there to make you understand that when you do TDD you need to change the way you write software, and this is why TDD is great because to make it work you have to answer those questions, you have to improve as a developer:
Big upfront design: evolutionary design
Breaking things, debugging write tests: tdd vs debugging
Big tests: a lot of tiny steps
how to discover what problem to solve iteratively: what is the next test to write?
If you want to start doing TDD perhaps this helps: