
I get frustrated a lot with the software I write. Typically, it starts to get so complex that any small, local change could potentially effect some other part of the code. And it gets so complex and unmanageable that I usually start fantasizing about rewriting it. But there's something I've learned the hard way. Writing your tests first can really help remove the stress of a complex piece of software. Test Driven Development (TDD). It's not the panacea that the hype and buzzword mongers want you to believe, but as a discipline it does relieve some issues when developing large systems.
One of the mainstays of Test Driven Development is to develop your tests first, before you write the code that the test will check. I would like to share with you some of the advantages that the discipline of TDD can impart on your code.
As a programmer, I love tinkering with code. I love to experiment with some new way to structure my objects, or a different dispatch strategy, or any number of things. It makes me feel clever to come up with a solution that can deal with way more cases than just the few I know I need now. But all too often, those meandering experiments waste time. Usually, ten simple lines of code will do precisely what I want, and I let my imagination run wild with Rube Goldberg algorithms.

When you write your test first, you know exactly what your software needs to do. You write a test and watch it fail. Then you write the simplest code that makes the test pass. And that's key, you make the simplest change to the code that makes it pass. Not the most ingenious, not the most modular, not the most general. All those things just mean complex. The discipline of writing the simplest code possible and nothing more will help you save time.
Related to preventing imagination overrun is knowing when to stop writing code. Let's face it: even each class can suffer from feature creep. You want to make it handle the more general case. Or someone thinks you should use the Observer Pattern. These kinds of feature creep are just a waste of time.

Most software systems I've worked on required so much work that you really did need to know when to stop work on one piece and move on to something more important. A test defines when a feature is "good enough". The discipline has a built-in check for completion. If you pass all of your tests and there are no more tests to write, it works well enough. So why waste your time on it when there's more important things you could be doing? If you stop coding when your tests pass, you will use your time more effectively.
Code starts to get complex after you've been working on it. And especially after you've not worked on it for a few weeks. When you start to make changes to the code, how do you know you haven't broken something? Maybe you can keep it all in your head. But maybe you can't. Nobody can keep it all in their head. So maybe you do a few manual tests to try it out. But then you make some more changes, and you start to wonder again: "Did this break something?"
And eventually, your test reveals that somewhere in the 300 lines of code you've written or modified you introduced a bug. But where was it? When was the last time you ran your tedious manual tests?
When you develop your automated tests first, you know that pretty much anything important that needs to happen in your program will happen, or if it doesn't, at least it will tell you. And your tests are so easy to run (usually a button press or an expression entered at the REPL) that you do them repeatedly. Hopefully after every tiny, atomic change. That way, you can know which change breaks the tests and fix it. Developing the discipline to run your tests often, almost compulsively, will save countless hours of frustratedly hunting down bugs.
When I do Test Drive Development, I'm often surprised by how clean the design turns out to be. I'll often see what are referred to as standard design patterns emerge, fully formed, completely unintentionally. I like to think of that as evidence of the hidden power of this discipline: that in testing the interface of a module (Unit testing) you are forcing the interface to be well designed.
Instead of asking yourself what should this module be able to do, the Unit test forces you to ask "how will I or other code use this" though in an indirect way. It is akin to a product designer creating something to be used by people. He/she asks what the user will need to do to the object (push a button, turn a knob), how to let the user know how to do that (making the button and knob highly visible, perhaps textured), and how to let the user know what the effect of the action is (beeping or changing the volume).

Right! It works the same for a software module. When writing the unit test, you ask "what will do I do to the object?" (what you are testing), "what function do I call?" (the interface), and finally the essence of the test: "how do I know it did what it should?". Writing good unit tests will help you design better software.
Have you ever wanted to reorganize some code, maybe break larger functions down into smaller ones? Move some methods to another class? But then you thought twice about it because you were afraid to break the code. When I don't write tests I sure do. But when I have lots of tests, I usually feel pretty safe. Those corner cases are covered by the tests, so if I break something, I can always find it. Refactoring my code is actually fun, because I'm not afraid of breaking anything.
Also, since I write the simplest possible thing to make the test pass, my code is usually pretty neat anyway. So there's less housework to do.
And writing code can be such a chore when you're facing the task of writing a gigantic system. Breaking your development down into small bits, each with a defined goal, makes the whole process much more pleasant. You get a little reward after each iteration (seeing all your tests pass) and you are never daunted by the apparently treacherous path to the end of the project. It lets your mind concentrate on the current step in the process instead of worrying about the big picture. Writing tests first gives you peace of mind.