in reply to Developing larger applications.

  1. With source control, such as CVS (although there are alternatives.)
  2. With good design, which is a balance between abstraction (which has many different aspects and ways to describe it, such as "don't repeat yourself", "once and only once", "encapsulation", "abstraction", modularity, and "information hiding") and simplicity. Finding the right balance is a delicate matter of taste. Finding abstractions that allow you to achieve separation of concerns often requires considerable inspiration and experience; the Design Patterns movement is intended to make some of that experience teachable. Patterns won't give you the good taste to know when not to abstract, though.
  3. With automated tests. These can be even better if you write them before the code.
  4. Incrementally, using refactoring instead of rewriting whenever possible.
  5. With mentors. I find pair programming an especially effective method of mentoring, although it won't turn a bad mentor into a good one.
  6. With someone else carefully proofreading your code to find bugs that are too subtle for the automated tests.
  7. By building one to throw away --- perhaps not the whole system, but each piece you're uncertain of the design of. Hack together something quick to test each design possibility, see how it works, then toss it. When you've explored the design space, write the real thing.
  8. Spending as much time reading about how other people have solved problems similar to yours as you spend solving the problems themselves.
  9. With rapid feedback. Having your test fail one second after you write the bug is better than having your test fail ten seconds after you write the bug; ten seconds is better than a minute; a minute is better than ten minutes; ten minutes is better than an hour; an hour is better than a day; a day is better than a week; and so on without limit. Sometimes it's hard to get feedback on whether you've, say, broken your database schema, your web server config file, or your build scripts, within one second or even one hour. Try very hard to reduce that time.
  10. With reliable feedback. An automated test that gives you the right answer 100% of the time is worth a lot more than a test that gives you the right answer 50% of the time. A lot more than twice as much, in fact.
  11. With as much access to the people who will use the code as you can manage. It sucks to spend an hour or a day working on a feature that the actual end user could tell you is useless in less than a minute.
  12. With other people having as little access to you as you can manage.

I tried to put these in order of importance, but the precedence gets a little fuzzy around #6.