Today I was geeking out, following a long list of articles and papers by computer scientists sparked by Michael Fogus on papers every programmer should read. I ended up checking out Leslie Lamport's (a distributed systems guru) website and downloading his book on Specifying Systems. In its introduction he writes,
A specification is a written description of what a system is supposed to do. Specifying a system helps us understand it. It's a good idea to understand a system before building it, so it's a good idea to write a specification of a system before implementing it.
He also includes the quote:
Writing is nature's way of letting you know how sloppy your thinking is.
This reminds me of the value I've found in writing tests for non-trivial programming modules before implementing them whenever it's not clear to me exactly how the system should work or what it is supposed to do, a topic I wrote about early in my career as a software engineer:
[tests are] a specification for behavior. In essence, you're forced to think in a very concrete way, what is this code supposed to do? What exactly are it's input, outputs, error conditions, etc? And when you have finished writing the tests, you look at your code, it is amazingly simple.
I wouldn't go so far as to say it always makes your program "amazingly simple", bit It does tend to make it simpler than it might have been were it not written only to satisfy the requirements you really need. And most importantly, to get back to what Lamport was saying, it helps you make sure you have really thought through the problem you are trying to solve before you starting writing a system to solve it.