TDD is test driven development. If you don’t know what this is then please go here as a starting point and then read this book as an excellent starting point to get introduced to it if approaching it from scratch, you can also watch me doing some TDD here.
I’m going to tell you why for me TDD is dead, and why I think it is the most important thing for every developer to learn. I will rationalise with experience and sound pedagogical theory at the end.
TDD is an absolute must have for every developer. It is a process of writing code through doing tests first. Usually it is done by writing a really basic unit test and then writing the minimum amount of code to make that pass.
What’s so good about it?
TDD serves multiple purposes:
- It is a great tool for learning a language as it breaks down problems into small bitesize chunks
- It is a great tool for figuring out a complex piece of code by behaviour
- It is a fantastic guarantee of tested code when followed religiously
- It is a support blanket when facing new code as it allows you to assert certain behaviour and ensure you don’t destroy that
- It is brilliant at helping you build your competence with a language
- It is essential to helping you think about code in the right way
There is no doubt about it, TDD is an absolute must have, it’s brilliant and is something that any developer even remotely worth their day rate should know how to do. It is near impossible to over state the benefits that TDD brings…
But! And it’s a BIG BUT!
This is all well and good for junior and even professional developers, within the language that they are doing. However, for seasoned craftsmen (in this context this means man or woman) it is and must be a choice to do rather than a necessity. If you are not a seasoned craftsman in the language you are using, and you will know in your heart if you are or not, then I strongly encourage you to always do TDD. However as you become more of a seasoned craftsman you will start to see some of the issues it presents, you will start to find it fails you at the most critical point in time, you will understand the intention and ideas behind TDD sufficiently to achieve those in improved ways.
This isn’t an elitism thing, this is just how learning a new thing goes, as you become more experienced at something you build an intuition as to what you can and cannot do, you understand the intention. Whilst a strict formula is a great way to start, the formula’s purpose isn’t to be the be all and end all, it is merely a tool to build your understanding of the underlying principles. This is how it is with pretty much everything. The reason we don’t go for those more intuitive ways of working from the get go? We lack context and we lack experience of which signals to watch out for in order to change our way of working. There is no way to teach or learn this beyond time served.
The approaches I take when writing new code is to essentially use almost pseudo-code, but in the IDE, in the language I’m writing the software in. I write it in a meaningful way and I write it with all the correct abstractions that I think should be there. The code won’t compile at this point, and that’s absolutely fine, it’s not meant to. It’s a first draft, it’s quick, and it has two purposes:
- Capture the business flow I want in code
- Generate the first pass at abstraction layers and delegation layers
I will tweak this until I am happy with it and think that it is going to result in the cleanest code I can create. This psuedo-code is very much written like English, I want someone from the business to be able to read this code and for it to make absolute and complete sense to them. They may not understand the syntax, but the words that I’ve used should correctly and clearly capture the business function.
At this point I tend to build the implementation, creating whatever additional classes are required to handle the technical aspects but fundamentally keeping the business flow. It is at this point that I will start to put some unit tests in where I think is appropriate.
Another approach I take is to write the implementation doing TDD in my head, this lets me get the implementation down as fast as possible and then I go back and put in the unit tests that it needs. This can only be sustained for short bursts of about 45 minutes, but it’s incredibly valuable as it allows me to fully express the business functionality clearly without deviating to writing a load of tests and losing context.
The biggest problem TDD presents when writing code at this level is not that it slows you down, but that it breaks the thought flow, and breaking the thought flow is very costly as you have to continuously rebuild your context.
An alternative to TDD is BDD (Behaviour Driven Development). A good way of viewing the difference between TDD and BDD is that TDD tests the technical implementation whereas BDD tests the business requirement. Fundamentally, the tests created using BDD are significantly more valuable than those created with TDD, however they can be slow to execute and slow to write.
I hope here I have given a flavour of the reason why TDD is absolutely essential to every developer, and at the same time provided enough reasoning to establish the need to move beyond TDD into a more intuitive approach.
What do you think? What is your experience with TDD?