The contant focus of developers on testing has caused more problems than it's solved, even though it *can* solve problems in the long run. People have learned to mangle their solutions to cater for testing - and unit testing is often the concept they shoot for as opposed to being able to solve actual requirements.This isn't to say that unit testing isn't important - but I think an architecture is more valuable, and TDD proponents tend to see architecture as "whatever enables testing" as opposed to "whatever enables fulfillment of requirements."Or so it seems to me.
I think, the problem is in the diverse and obscure definition (or - lack of it) of the notion of "Software Architecture", in the industry. Martin Fowler has an interesting article
about it, which you, most probabely, have already read.
According to him (and I can not help agreeing) Architecture in building construction and software engineering are two similiar but different things. What is different is that - in construction, it is almost impossible to change the architecture on a later date. Nothing is impossible in the software engineering, or even - hard, if approached the right way.
So, it is WRONG to over-emphasize the importance of the software architecture and position it as something holy, untouchable or eternal :)
Martin defines Software Architecture as a common understanding of the software project's design, as shared by the expert developers of the project. That common understanding can (and probabley, will) change as the project progresses and/or business requirements change. It is normal, the architecture to constantly change - one of the main principles of the iterative development and Agile processes.
Why do I like TDD?
1) by the nature of software engineering any code needs refactoring. Having code covered with unit-tests, gives me confidence during the refactoring. I do not know any other reliable way of having the same kind of confidence. Without the confidence, I would be afraid to do refactorings often, which would make the software product of lesser quality.
2) Due to the nature of unit-tests (emphasize: unit), it is impossible to test a "badly-smelling" code. In order to be able to unit-test your code, it has to be cleaner, and better designed: short, focused methods, writing to Interfaces, lously coupled etc.
So, by its nature, unit-tests require better code design, writing unit-tests affects and improvea the design.
I think, this might not have been something that was foreseen initially but discovered later. My guess is, initially, people just wanted to make computer do what it is best for - repetitive work (in this case - testing) and have code test the application, not humans. But as a "byproduct" they noticed that testing requires design improvement, too. When they discovered it, somebody smart-enough had an idea - if it is so, why not write tests first? Design is supposed to come before the implementation and if tests affect design, it makes sense to write them before the implementation, too.
And the TDD started...
I find this approach fair and useful. It, also, helps my inherent laziness. If I write code first, then I may be lazy to add unit-tests to it, later :-)