Advanced test-driven development with Uncle Bob
At the beginning of April, a few of the Java team here at Manifesto headed off to a two-day course to study Advanced Test-Driven Development (TDD) with the internet’s favourite uncle – Uncle Bob, aka Robert C. Martin (pictured above, centre, with, from left to right, Enrique, Marta, Matt and Adriana).
Everyone here on team Java at Manifesto are big fans of Uncle Bob’s Clean Code video series (and the book on which it is based), watching them regularly in our Friday afternoon learning sessions as introductions to topics. They’re great jumping-off points for discussing and breaking down complex, and sometimes abstract, software development concepts.
For those that have not caught one of these videos, they really are something to behold. Uncle Bob’s presentation style always keeps viewers on their toes, and seeing him teach this course over the two days was no different. Its not everyday you can go from the heat death of the sun to a breakdown of the history of C++ in the same hour, and have it be interesting, but Uncle Bob manages it in a way that had the whole classroom hooked.
“Software is killing people”
That was the sobering message that Uncle Bob delivered early on the first day of the course. As more and more parts of our life become powered by software – as software developers, it’s easy to think of all the times that code we have written has bugs, or behaved in an unexpected manor. Now consider that someone’s code is powering the drive computer in your car, or controlling the air traffic control system responsible for the plane you are about to travel on. Would you feel comfortable getting into that car or plane, knowing that, somewhere, a fellow software engineer wrote that code?
Uncle Bob posited this not to denigrate developers or to scare us. Rather, he’s pointing out the importance of ensuring quality in the code we deliver, and the need to regulate ourselves as an industry before governments start mandating standards to us.
They are really more like ‘Guidelines’
After talking about the scale of the challenge and the problems we as an industry face, Uncle Bob outlined one of the solutions, which would be our focus for the next two days – Test Driven Development. TDD can be broken down to three simple laws:
1. You are not allowed to write any production code unless it is to make a failing unit test pass.
2. You are not allowed to write any more of a unit test than is sufficient to fail; and compilation failures are failures.
3. You are not allowed to write any more production code than is sufficient to pass the one failing unit test.
Anyone who has spent any time developing will know that these rules are totally counter-intuitive. How can you write tests before you have written any code? What is there to test? Uncle Bob acknowledges how bizarre this way of working can appear at first glance. But he posited that if everyone in an organisation was following the tenets of TDD, you could be certain that in the last few minutes, every single line of their code passed its unit tests.
To demonstrate the cycle of test, code, refactor, Uncle Bob walked through a simple prime factors Kata, which he first completed to help his son with some homework. When first faced with the problem, he designed a solution in his head, utilising various sorting algorithms, before deciding to use this as an opportunity to practise TDD. Watching Uncle Bob run through the TDD process is fascinating, as he walks the class through all the decision points.
At first the process seems as counter-productive as it looks on paper – he writes the most basic test the class can suggest, which of course fails, as there is 0 lines of production code to test. He then writes the code to make that test pass, which involves hard coding whatever value he is looking for, making the test pass.
Then he moves onto another test that fails at first run, due to the previously hard coded value. This leads him to create a simple method to replace the previously hard coded value with something more useful and dynamic. It’s a slow process, at least at first – and what is produced is far from a useful final solution to the problem. However, over time, something fascinating happens.
Through the TDD cycle, the software gradually starts taking shape, and by focusing on small incremental fixes, the output was incredibly lean. By the end, the solution produced didn’t require writing complex sorting algorithms at all. By using TDD, the time spent designing a solution wasn’t required, as the tests drove the solution and the design. Uncle Bob characterised the general flow of this process – “As the tests become specific, production code becomes generic”.
Feel the freedom
One of the most interesting elements of TDD is the by-product you get at the end. Code developed using TDD should have close to 100% code coverage – with tests you know cover your business logic. So, safe in the knowledge that you have a rock solid suite of tests, you have the freedom to refactor and make changes to your code base at will. After making a change, if all your tests still pass, you can have certainty that your refactor has not altered any of your logic.
This safety net also allows other developers to come into your code base and make changes or enhancements at will, without needing to worry about breaking preexisting functionality. Being able to refactor any code base at will also prevents code becoming stale – and stale code becomes something no one wants to deal with: legacy code.
TDD and legacy code
Legacy code was one of the topics people were very interested in learning about in relation to TDD. After all, it’s all well and good doing TDD when you start from scratch, but what about trying to implement it in a potentially large and unwieldy code base, where you don’t have the freedom of a comprehensive set of tests?
Uncle Bob outlined several strategies for dealing with TDD in a legacy code base – but the underlying philosophy he imparted for this problem is that there is no quick fix. Don’t try and fix a legacy code base all at once. Instead take the campsite approach and simply try and leave any part of a code base you come into contact with in a better condition than when you found it.
Uncle Bob – a sight to see
The two days covered much more than I can outline here, such as the testing pyramid, how to sell the idea of using TDD to managers, and structuring your application to enable an easier approach to TDD. Uncle Bob is a fascinating presenter who allows the material to evolve naturally over the course. If you get the opportunity to see him in person I would strongly recommend it, especially if you are looking for an opportunity to pick up some enhanced TDD strategies.