I really like Test-Driven Development (TDD) and apply it almost always. The problem with TDD is that it focuses too much on working software.
"Make it work, make it right, make it fast." ~ Kent Beck
Don't get me wrong, code must work, but that just shouldn't be the number one priority.
It is more important for code to be changeable than that it work. Code that does not work, but that is easy to change, can be made to work with minimum effort. Code that works but that is hard to change will soon not work and be hard to get working again.— Uncle Bob Martin (@unclebobmartin) November 7, 2019
In TDD, design and refactoring towards a better architecture come first when the feature is already implemented and tests are green. Refactoring then often needs to rewrite and delete a lot of code, activity which not everyone likes to do, especially when the code has just been written.
Taking TDD dogmatically so often leads to a perfectly working code with a poor design.
I find more eligible to apply TDD first in the implementation phase. The process of development so looks like follows:
- Understand the problem.
- Design the API clearly without any implementation concerns.
- Implement requirements one by one applying TDD.
This approach ensures a well designed architecture with all benefits of TDD.
It's still necessary to keep "make it right" after "make it work" as it means optimization and polishing the code like removing duplicates, restructuring methods, renaming variables etc. The API should remain untouched and the tests ensure all is still working.
To paraphrase Kent:
Understand it, design it, make it work, make it right.