A reader asks:
My boss knows about TDD but won’t allow us to use it because he thinks that it is just a passing hype that everyone talks about but no serious, big projects actually use it on daily basis. How could I convince him that it is not so?
This is an excellent question that takes me a bit by surprise, as I can’t imagine my boss dictating how I write code. I don’t have an answer, but here is what I think I would do if I were in this situation. (I would also like to encourage other readers to share their thoughts on this topic and offer suggestions in the comments.)
Arguments don’t work
There is no magical argument I can make to convince someone that TDD is a good idea: logic may not be persuasive here, but experience is. I am not arguing here that 1 + 1 is 2, but rather that if you follow these practices, the result is subjectively better. Since there is so much subjectivity in this, people need to experience TDD to understand its benefits. It is very hard to learn TDD by someone trying to learn it from a book. Learning TDD is more like learning to ride a bike: You can read books on how to do it and you can have silly arguments with theorists on how you can’t ride a two-wheeled contraption because it is inherently unstable, but nothing makes you a believer more than actually riding a bike. The first time you ride a bike it is a very clumsy experience, and I would argue that it takes hours of falling and uncertainty until you are better at it than walking: don’t expect TDD to be any different. It is a skill that takes hours of practice to master. Don’t argue with someone over your experience; instead, make him live through the same experience.
Make sure you know what you are talking about
To me, nothing is worse than someone trying to sell something that he doesn’t fully understand. Make sure you are reasonably good at TDD and have built a reasonably sized application before you try to show someone else how to do it. Imagine someone who has only seen others riding bikes trying to teach someone to ride a bike: my guess is that he will only frustrate the person learning. For this reason, build a small app with TDD in your free time. Your first tests will be the hardest, and at times you will think “this is way more trouble than it is worth,” but keep in mind that you struggling because you are learning a new skill. You have been developing code the old way for years: What makes you think that you can pick up TDD overnight? TDD makes you think about tests first, something that you have never done. It will not come easy, but in time it will become second nature to you. It took about one year before I felt that writing code test-first was the natural flow of things.
Create a small project to show your boss how helpful tests are in refactoring
I cannot overstate the importance of learning TDD on a brand new project without deadlines. Start something new in your free time and build it with TDD. Use it as a learning experience. You will: discover all kinds of things about how to best write code, get a feel for telling apart helpful tests from those that get in the way, learn how to think about the problem from a test-first perspective, realize the importance of not getting ahead of your tests, and discover that your code looks nothing like what you envisioned. Code with tests looks different. Try to refactor code written test-first and you will see that some tests are helpful while others get in the way. You first have to live through this experience to become familiar with the kinds of tests that get in the way of refactoring, and to know how to turn them into the kinds of tests that help you refactor. To know both one and the other you have to first build something with TDD.
Since you will be struggling a lot at the beginning, trying to bring TDD to an existing project may only fuel your boss’s feeling that TDD is not useful. Again, TDD is a skill and takes a while to develop.
Tests help design
We all believe that good code is reusable code. For this reason most of us add all kinds of interfaces and abstraction in the name of reusability. But what percent of the code you have written have you actually reused? I would say a tiny fraction, very close to zero. One reason for this is that your code isn’t reusable, even though you believe it to be. Tests help ensure that your code is in fact reusable, because they force you to write classes that can be used both in production and in a test scenario. If you can’t write a test, you don’t have reusable code. If you write test-first, then it is very likely that the code is reusable: after all, you just used it in tests and in production. This is the single reason why test-first produces better design. On the other hand, if you write code as you always have, you will most likely end up with hard to reuse code. If you write tests afterward, then at best the tests are an afterthought hacked on top of the production code; such tests are very unlikely to help us when you are refactoring, since they are likely to produce false negatives.
Hardware folks have figured this out
Did you know that average chip can have as much as 50% of its silicon dedicated to testing? Why is it that every discipline out there takes testing seriously except software? I believe it is because of the presumed inexpensive nature of fixing bugs. A new rev of silicon is extremely expensive. As a result, most companies can only afford to rev it about 5 times. Can you imagine writing code such that you are only allowed to run the production 5 times? Yet hardware folks can’t imagine designing chips any other way. The cost of another software rev seems close to zero, and this is where people get into trouble: We believe that another build costs us (almost) nothing, and this belief becomes our death by a thousand cuts. The more complicated the project, the more likely it is that a fix in one location will cause a bug elsewhere: the project is forced into an endless cycle of regressions. Tests help here, but again, this needs to be experienced.
If you get stuck, spike
Sometimes you just have no idea how to write code test-first; there are a lot of reasons for this. Instead, you revert to good old fashion hacking. That isn’t a problem as long as, after you first code by hacking, you go back and write tests, or preferably, completely re-write the code test-first. you call this “spike”; I do this quite a lot when faced with new technology or environment. Just don’t let this become the way you develop software.
Vote with your feet
If your boss is micro-managing how you do things and you have tried everything to explain your position, you always have the right to vote with your feet. Last time I checked, we software engineers are in high demand, so there is no reason to work for people who are being counterproductive.
What do you think?
What do the readers think about how they could influence others to develop software test-first? Please leave your comments so that we all can learn from each other