I used to advocate test-driven development (TDD), but now I advocate DDD – documentation-driven development. I don’t even know if it’s a “thing”, I just decided that’s how we should work.
Writing tests first ensures that your program jumps through some arbitrary set of developer-designed hoops. Worthwhile for sure, but may or may not represent things that are important to the user, and doesn’t help with the design process.
Writing documentation first ensures that your program *makes sense* from the point of view of the user of that program (or API or whatever). It’s too easy otherwise to design from our own point of view, and do something a particular way because it’s easier to code that way, or that’s the way the code happens to fall out that day, without adequately considering the user perspective.
Tests, being still written in code, keep you in the programmer’s mindset. Only by switching to English (or other human language) and writing the actual docs for the poor sod who’s going to use this, can you flip into the user’s mindset and see how actually it would make more sense if you do this, don’t do that, simplify this, make that optional, etc.
A handy side-effect is that you get good, accurate and up-to-date documentation – in fact, this is the *only* method I’ve ever found that results in that. If you do documentation last, it doesn’t get done, or gets out of sync with the code. You could use a tool to auto-generate docs from code but those are hardly docs in any menaingful sense at all.
DDD is also implementation-agnostic. Tests tend to be implementation-specific, which means they need to be rewritten if you change the backend language.
So, write documentation first, then write tests for the key parts of the documentation. Then, importantly, still write your code based on the documentation, not the tests. The tests simply confirm that you’ve done that right. If you code to the tests, you might code to *only* the tests, meaning that if there’s something in the docs that you don’t have a test for, you might miss it or get it wrong in your code. Just like the current problem in the education system – a heavy reliance on testing, and the results of those tests having implications for the school’s funding, means that teachers “teach to the test” rather than teaching what kids actually need to learn. Don’t do that with your code – code to the docs, not the tests.
Since I came up with DDD, BDD (behaviour-driven development) has become popular… this seems to me like it’s just a variant of TDD – still quite “code-ish” even if written in pseudo-English, but possibly useful for requirements capture, or to help with translating docs into tests, and to ensure that your tests have good coverage of what’s in the documentation. But it’s not something I’ve used thus far.