Incredible how much have people been talking about TDD and problems with it over last few weeks. I thought it is mostly settled topic: it probably is not ideal, but it is pretty much best we can do for now in a long term. Yet many suddenly (or not so suddenly) decided that TDD sucks, is dead and creates more problems than it solves. One that I’ve stumbled upon and that made me write this post is: The pitfalls of test driven development (http://beust.com/weblog/2014/05/11/the-pitfalls-of-test-driven-development/).
I’ll just touch one point now: “TDD Promotes Microdesign over Macrodesign”. Go on, read that paragraph, I have time. OK, now that you read it – do you agree with it? I don’t. From the section title forward it seems to be based on very wrong idea about TDD – that TDD is the only approach you are using to write your application. Let’s clear this up. TDD is not a way (usually) to design your whole application from top to bottom. TDD is approach to write good, test covered code. TDD helps to design classes, components, maybe packages. But not applications or solutions to problem.
Imagine you have large business problem to solve. Would you really expect TDD follower to just jump in and start writing tests and code? Come on, no sane software engineer would do that. You think about the problem, you try to understand domain, all the details, all the caveats of this particular business problem. You are not thinking about the code at this moment at all. Maybe solution can be created without code at all? Are there other possible solutions to the problem? We don’t always need to write new programs, we need to solve problems.
Then you start imagining your application. What would you need, what big parts (modules) seem to be useful. Do you need distributed application to handle complex calculations? Will it be client-server solution? How much data will it process? How often? Those are all requirements you have to think before sitting down to code something.
Only after you have this broad idea of what you are doing, you can sit down and start writting code. And then TDD is what you follow. You write components and classes with tests to assert your invariants and to provide API for usage from other points in system. And you are better this way – TDD will help you create better, smaller classes, more practical solutions and so on. But on lower level. You’ve dealt with macrodesign before you even considered writting code in the first place. Now it is time for microdesign.
Yes, software writting is iterative process. That’s why having set of unit tests to cover your back is so useful. You will need to do some changes in your code. It’s better to have some tests that will assure you that all is working fine after changes. You can write them after you’ve created code or you can write it TDD style. Does not matter all that much. But don’t throw away TDD because of some missconceptions. TDD is not solution to all problems. It is solution to one specific problem – low level code testability. Not application high level design.