I’ve found that mandating someone write tests first ignores the realities of problem solving, and the realities of how TDD fanatics actually code. Every person I’ve seen who is a TDD fanatic claims they write their tests first, but then I’ll catch them doing a “spike”, no tests, just hacking the solution. When pressed on it they’ll claim that this doesn’t count because it’s not the real code, but it does count. They spent some time free-form coding without obsessing over the order of things. What means is the real TDD process is:
- Spike
- Test
- Code
- Repeat
Well, #1 is code first. It’s not a test, so saying people should or must start with tests only when the entire process actually starts with not-tests first is disingenuous to outsiders.
In fact, you find this lack of self-awareness in almost every single thing I’ve ever studied. In guitar you’ll see top guitarists like Steve Vai claim he always keeps his fingers parallel to the frets, and then you watch him demonstrate this and literally turn his hand 45 degrees to the frets. In painting you’ll hear painters say don’t blend and then watch a video and oh look at that, blending all the time.
So, what I tell people is, do what is the easiest path to solving the problem, just make sure you have automated tests since the entire point of being a programmer is to make computers do work for you and tests are totally something you should be automating. This frees people up to solve the problem with the best heuristic they can at the time. Do they have a good idea of the steps in a process but not how to implement it? Ok, tests first might be the way to go. Do they have an idea how the code should work but not really how it should be used? Alright, start the code and then use the tests to figure that out.
I also demonstrate to people who I actually do it so they can see what I’m really doing. I tend to actually bounce in a cycle between test and code so fast that there really isn’t a first or after. I tell people to not write mountains of either test or code before writing the other, and instead do it incrementally using both to check that things are working. This is a much better way to work and I find it matches how programmers, even TDD fanatics, actually work.
The other thing I tell people is that there is a difference between personal processes and team processes. How you write your code is a personal process. How that code is verified is a team process. If the team has the requirement of “must have automated tests”, then that’s as far as I think they should go. It’s then a personal process for the person to make that happen. The flaw in almost all Agile methods is they take personal processes, which should be left to the worker, and try to impose them on the entire team as if every person and every problem is the same. This is a manufacturing mindset which doesn’t fit into the creative field of programming.
However, I do throw in the fact that beginners have almost zero personal processes yet, so in the case of training a junior programmer or beginner, imposing a process on them is just fine. As long as the process is actually something that the pros use and not something they think they use that beginners should do.