Learning Unit Testing II – TDD vs. Traditional Design

As you can see, I’ve only done a small amount of Test-Driven Development so far. I notice that for small classes – so far, there’s only a very simple turn tracker – it’s easy to write a test first when there’s only very little code and no interaction with other classes. When things get a little more complex, will it still be so easy?

I am wondering how people use TDD when they have big projects (as this will invariably become). Is it possible to stick to just writing code to pass tests all the way through to the end? Surely, at some point, major refactoring will need to be done when something comes right out of nowhere. I can see one example I’ll run into at some point: in Necromunda, a model may go on ‘Overwatch’. This allows them to fire in their opponents turn, shooting at a target before it’s move, after it’s move or during it’s move. That’s probably going to require a major change to the Movement code (to account for the opponent taking an action), which could itself lead to a lot of refactoring. Should I try and design around this idea now, or wait until much, much later when I get to the Overwatch section to worry about it?

Whether or not there is a simple solution to that particular problem will depend on many things – not least, the movement and shooting code that is written before it. I would traditionally sit down and try to work out exactly how to architecture the whole thing, taking into account things like shooting, overwatch, etc before I sit down to code. TDD seems to suggest that I write the test, then the code, and then eventually get around to a new test that – had I known – would have influenced the code I wrote earlier. I can see that would have some benefits (for example, the Bowling Game Kata shows the change in design to a simpler one due to TDD) but I don’t know how likely it is that writing code just to pass the test will lead to a design path that isn’t optimal given later functionality requirements.

Maybe I am worrying about nothing, and the forced simplicity of design for TDD will ultimately lead to a good solution. Maybe I’m missing the point entirely, and there will be major refactoring down the road, and that’s a good thing. If that’s true, isn’t TDD going to end up taking a lot more time than is useful? Is there a secret, undocumented art to writing code following TDD where certain things are written first entirely to limit this sort of refactoring? If that’s the case, I may be handicapping myself by slavishly following the rulebook.

After reading the accepted answer on this StackOverflow question,  I’ve decided to push ahead with my TDD experiment. I need to understand the beast. I’ve got an idea of how certain things should be done, but we’ll see if it makes sense once I’ve laid the foundations using TDD. It’s going to be an interesting way to do the work!

This is a learning project I am documenting in order to teach myself TDD and unit testing – as I publish this, I have already written many parts in advance but I want to know what I’m doing wrong! If you see improvements or corrections, either to the code or the process, please leave a comment and let me know! Introduction to this project can be found here.

Leave a comment

Your email address will not be published. Required fields are marked *