I recently came across a post by Ayende where he talks about the need for tests to justify themselves and describes his approach to testing which doesn't involved TDDing all the code he writes.
While this approach clerly works well for Ayende I really like the following comment by Alex Simkin:
Anyway, this post should be marked MA (Mature Audience Only), so younger programmers wont use excuse to not write unit tests because Ayende doesn't do it.
This reminds me of a conversation I was having with a few colleagues a while ago where we were discussing whether we should look to test drive absolutely everything that we write or whether we should make that decision on a case by case basis.
Personally, I don't yet have the experience to be able to tell when it's appropriate not to drive code (excluding spiking) and pretty much every time that I've decided something was 'too easy' to test drive I've managed to make a mistake and not realised it until much later than would have been the case with a test driven approach.
I'm finding that this applies to more than just testing though and it seems that where an approach is known to reduce a lot of potential pain then it might be useful to favour that approach unless we find an intriguing reason not to.
Thinking along those lines I think it makes sense to follow some 'rules of thumb' and not break them unless we absolutely have to.
Some rules of thumb which I've come across are:
- Don't put anything into the session
- Don't put getters onto objects – make all code adhere to the tell don't ask principle
- Write production code test first
- Write classes which adhere to the single responsibility principle
- Favour composition over inheritance
- Favour constructor injection over setter injection
Given a situation where I want to reuse some code and I know that I could choose between doing it with composition or inheritance I wouldn't consider this a 50-50 choice but instead would look to use composition unless it became really difficult to do this and inheritance was clearly the answer in which case I would use that.
Obviously these 'rules of thumb' might be a bit restrictive for people at the higher levels of skill of the Dreyfus model and I imagine that even with people with less experience they could be quite dangerous if applied too literally.
I wonder whether being dogmatic about a few rules of thumb would be more or less dangerous than making decisions not to follow a useful practice because you mistakenly believe you have the ability to tell whether or not it applies in a given situation?
Corey Haines wrote a really good post where he talks about the misuse of the word 'pragmatic' which seems to address this area although he comes to a slightly different conclusion:
This is a common thing that I hear from software developers: they have a little bit of experience, think that they understand something to the point where they can make their own decisions on what it means to 'be pragmatic.' Often times, people use the term 'pragmatic' as a way to hide a lack of skill and experience. Or, sometimes, it is used in ignorance: someone doesn't realize that they don't understand something well enough. Usually, though, it is brought to play when someone is justifying cutting corners on something…this can come back later to bite you in the ass.
Think your 9 months of trying TDD makes you an expert, someone who can suddenly decide when it is 'pragmatic' to not design your system with TDD. Or, don't even worry about designing your system with TDD, just talk about automated testing.
Are you being 'pragmatic' about automated testing, skipping it things you don't know how to do or are hard?
Typically when people try to justify a shortcut this is exactly the way they will justify it. The irony is that quite often much suffering is gained from that decision so it wasn't really that pragmatic after all.
I realise that there aren't really any rules for software development that we can follow all the time and expect to gain success with but it does seem that some approaches have already been proven to be more effective than others so it might be useful to make use of them.