One of the very best coding/testing techniques I've ever come across, is taken from Extreme Programming (http://www.extremeprogramming.org/). It's not a magic bullet - nothing is, and while it won't prevent all bugs, it's the best way I've seen yet to reduce their number before the code is released into the wild. The technique is simple - Write the tests before you write the feature.
The way it works is this:
Consider the functionality of the code you want to write. Decide what you want it to do, and what you don't want it to do.
Pick one thing you either want, or don't want your code to do, and code a test around it. The test must be fully automated - able to tell by itself whether it was successful or not.
Write enough code for your application in order that the test will compile. If after doing this, all your tests succeed, including the new one, return to step one. If the test fails, continue.
Write enough code that the new test succeeds. Ensure also that all previous tests still succeed.
Return to step one.
The advantages of this system are legion.
Testing first means more testable code.
Writing tests for previously written code can be a total nightmare. Often, it's impossible to write an automated test for something vital, because the code you're testing isn't built so that it can be tested. By writing the test first, you ensure that everything you need to test can be tested, easily and automatically. Those parts of a system that are really difficult to test automatically(GUI for example) are more likely to be properly separated from things that can be tested.
Often, you will find this leading to cleaner design of your code overall.
Testing first can prevent over-engineering
You know that you have finished programming when you run out of things to test. Because at each step, you have only done what was necessary in order to cause the test you wrote to succeed, this means that you haven't coded anything into your application that is not necessary.
Note that when programming incrementally like this, you must always take time to refactor your code, in order to make sure you don't end up with an unreadable mass of spaghetti.
Testing first leads to more maintainable code
When you make a modification to something you haven't looked at for half a year, you still have all the tests that convinced you then that it was working six months ago. If they still run, that means that you are as convinced now that the code works as you were before. You have a complete set of regression tests as an integral part of the coding process, not as some tacked-on-as-an-afterthought test suite.
This means that you can allow more people to modify more of your program, provided that they also follow the "test-first" rule, and that they make sure that all tests are green before they check any code in.
Testing first can help you program
Often, by the time you've finished writing the test, you've already worked out the best way to code the feature. Because you've already thought of what could go wrong, and written code to test it, when it comes to write the feature, you've already thought through how you are going to implement it, and what pitfalls you might have to avoid.
Try it some time. If you're stuck how to code something, change your mindset, and try to think of how you'd automate a test to see if it was successful. You'll find that when you do that, you'll have solved your problem indirectly.
Testing first forces programmers to think defensively:
Because the way that you determine when you've finished coding is "can I think of anything more that needs testing?", programmers are forced to continually ask themselves, "What could I do to break this?" These questions are asked right at the time the programmer is closest to the code in question, not some time later during quality control or security audit sessions. You're much more likely to notice an unchecked buffer or too-trusted input in this state.
You also find yourself more likely to think in the middle of the night, "Oh! There's something I didn't test!".
Bugs immediately become part of the testing system
When someone finds a bug in your code, write a test to reproduce the error. If the test inspires you to think of other things that could go wrong, then write more tests. Writing the tests will often show you how the bug can be fixed. These tests then become part of your regression suite, and you are protected in the future.