Day 48 and 49: The Force Is Strong With TDD
Even though I’ve been spending this week over at the UX & Design team, trying to blend in there as much as possible, attend their meetings and watch what they do - I tried my best not to let that interfere with my study plans. I’ve been doing a lot of reading recently, and as rewarding as it can be, I honestly missed doing other stuff. My shoulder has been giving me trouble for weeks, but in these past few days I finally felt well enough to use both of my hands again (at least for a couple of hours every day) and do some coding at last.
Now, a funny thing happened on Day 1. Yes, I found myself starting with a test. Didn’t even think about it; it just came to me naturally. Well, that’s new! I thought to myself. The feeling was rather weird, but oh-so-good at the same time. I guess I can say I felt like I was doing things right this time. Now I see where katas have brought me. Repetition IS the mother of learning, after all. That Red, Green, Refactor cycle got so hardcoded in my brain, that I started repeating it unconciously, like a reflex.
Then on Day 2 I decided to do a small experiment: do the challenge without TDD. I had my experience from the day before that I wished to compare with my old way of doing things, which was jumping straight into coding. Did I still find that approach easier and faster? I was really curious to find out the answer.
I was very inspired that day, so I threw ideas all over the place and my code grew so fast, that it was hard to keep track of it. Eventually, I finished the challenge - or at least I thought I did. Everything seamed right, and I was pretty sure that it would work.
Alas, of course it didn’t.
Something somewhere broke and my hopes turned to dust. But what broke, and where? I had to write a test to find out. It was a tiring and frustrating process, but in the end the tests helped and my code worked. I paused for a second to think. So I had to write all of these tests anyways. Why didn’t I write them first, then? Contrary to what I thought before, it would have saved me so much time. And I wouldn’t get so stressed in the process. Yes, TDD would have been a way better choice!
I suddenly felt my love for TDD grow exponentially, so I dug through my numerous files and found the book TDD By Example by Kent Beck. I thought it would be nice to get a few tips from the man himself (Kent Beck was the one who invented TDD!). The book was a nice and quick read; the author didn’t try to suffocate his readers with boring theory, but rather walk us through an example, and offer some practical tips in the end. So here comes the summary of what I learned.
The biggest struggle I had relating to TDD was having to think small. Sometimes, when the problem was simple, I found it a waste of time to do teeny tiny steps, when I could have just done one huge leap and get to where I wanted to be. So I felt really constrained; I guess that’s the only thing that kind of put me off TDD. However, the book tore down this notion, or rather: it refrased it in a way that was perfectly acceptable to me. Namely, you don’t have to do small steps. Large leaps are perfectly fine, if you feel confident enough that you’ll be able to land safely. TDD does not require the steps to be small, nor big. In fact, you should be able to do both - and alternate between them if necessary - depending on the circumstances. Nevertheless, the more you do TDD, the smaller your steps will get. There’s no need to force it - it will come to you naturally.
So, in summary, here’s how you can go about the problem at hand:
- Obvious Implementation (the leap of faith) - If the solution seems too obvious to you, go ahead and implement it.
- Fake It ‘Til You Make It (normal steps) - Return a constant to make the test pass. Then, gradually transform the constant into an expression using variables.
- Triangulate (baby steps) - Only abstract when you have two or more examples. There’s also this golden rule:
“Once Is Chance, Twice is Coincidence, Third Time Is A Pattern.”
Furthermore, here are some more tips from the book that I found useful:
- Isolate your tests from each other. The execution of one test should NOT affect another test in any way. (Note: I actually made this mistake yesterday, and spent two hours thinking why my code was wrong. It wasn’t - but one test accidentally changed the global state which made the other tests fail.)
- Keep track of what you want to test. Before starting, write a list of things you want to test - sort of like a TO-DO list. (Note: We have been practicing this at the katas this week, and it has proven to be quite helpful.)
- Use test data that is easy to read and follow. Your tests are also your documentation. Think about the people that will be reading your code in the future. Or at least, think about your future self that will be equally as confused when some time passes.
To conclude, I wanted to answer that everlasting question: Why do TDD? I thought the book was pretty good at explaining it, so I’ll just borrow the author’s words: TDD is a way of managing fear during development. This fear is a completely normal thing to feel when faced with a hard problem, whose solution is not in plain sight. TDD helps you regain control. It keeps you focused on one single step that you need to take next, and gives you a sense of accomplishment with each passed test. What is there not to like?
So have a nice weekend, everybody! And remember: Red, Green, Refactor :)