When TDD Goes Bad #2
I've been debating whether to post another entry on this for the last couple of weeks due to another bad smell I've spotted around Agile practices. However, it's my blog, and I think it's worth saying. But first, the bad smell...
Zealotry. Many advocates of Agile practices have had to fight their corner hard against supporters of traditional methodologies. Having had several such confrontations myself, it does become tiring, and you do beging to expect fairly incongruent arguments against it. There is a danger, though, that the habit of dealing with arguments against Agile that don't stack up will lead to a blinkered view where it's assumed that any negative statement about the principles and approach should be dismissed. No methodology is perfect - different circumstances call for different approaches, etc. Also, just because a methodology when applied correctly is appropriate and should result in success, it doesn't mean that it will be applied correctly and appropriately. People can, and will, get things wrong - especially when lacking experience.
So, TDD Gone Bad #2... Mock oriented development. Mocks are a good thing where you really want to extract a dependency and ensure you're testing the right thing. But there are a couple of issues that can arise:
- Poor integration tests, as everything is being tested in isolation - we can end up with a system where the constituent parts are clean, isolated, well tested, and known to be correct. But how they fit together is a greyer (or even blacker) area unless mocking is accompanied with a complement of integration tests. Dave describes this well in his blog, so there's no need for me to go on about it here: http://www.twelve71.org/blogs/dave/archives/000616.html
- Mock oriented design. Whilst mocking is good at removing dependencies, their introduction regularly alters the design of the system. I've seen numerous occasions where the introduction of mocks has added a large amount of complexity to an otherwise simple design. This complexity leads to higher implementation costs, a higher cognitive load on the developers working on the system, and higher maintenance costs (as there's more code to maintain). All of which go against the principle of "the simplest thing". The irony is that the introduction of mocking can, sometimes, make completing a system far more time consuming due to the different levels of granularity, and the additional code required to implement interfaces, etc. Again, that's not to say mocks aren't very useful things, just that they're a tool to be used where appropriate, not a pattern to base the foundations of your entire implementation on...
Whenever mocking is used, the value that the mock gives versus the cost it will introduce over the lifetime of the system should be measured (or at least estimated/considered)