You're asking for the Holy Grail of software engineering, and no one has "the" answer to this question yet.
What is essential is that you track the types of errors that you're making and then do an analysis of those errors to determine if there is a common trend. Root cause analysis is the formal name for this type of introspection, and there is plenty of material on the web regarding it.
Professionals use a bug tracking system so that they can (1) know what needs to be fixed, but also (2) analyze what had to be fixed after-the-fact. You don't need to be so formal -- just keeping a tally in a notebook may be fine for you.
Design Stage Defects
If you find that most of your errors come from a misunderstanding of the problem statement, or if you keep finding you've chosen the wrong algorithm or path to follow in solving your problems, you have problems in the design stage.
It would behoove you to take more time at the beginning of the project and write out exactly what needs to be done and how it should do it. Review this work carefully and revisit the original problem and determine if you really are tackling it in the right way. An extra hour or three at the start may save you many hours down the road.
Coding Errors
If your design is solid, but you're constantly fighting the language that you're coding with, get yourself some tools which will analyze your code for you and warn you early and often that you're making mistakes.
If you're programming in C, turn on all compiler warnings, use a semantic checker like lint
, and use a tool like valgrind
to catch common dynamic-memory related issues.
If you're programming Perl, turn on strict
and warnings
and heed what it says.
No matter which language you're using, there probably exist many tools out there to help catch common mistakes long before you reach the debugging stage.
Integration Stage Defects
As you develop your code following good modularity practices, you have to begin gluing the separate pieces together. For example, different sections of your code may have to do with user input, database interaction, data display, algorithms/logic, and each of these are built relatively independent of one another (that is, you tend to concentrate on the section at hand rather than worrying about integration with everything else).
Here is where test driven development (TDD) comes in very handy. Each module of your code can have tests which verify that they work according to how they were designed. These tests should either be written first or very early in the process so that you can have a set of "helpers" to keep you honest. When you begin making everything work together, and you find that you're having to change how this or that is implemented or interacts with another sub-system, you can fall back on your tests to make sure that what you've done to make it all work together doesn't break the correctness of the code.
And So On...
Pick up some books on software engineering and practical coding techniques, and you'll learn many different ways of making development less chaotic and more reliable. You'll also find that just plain old experience -- earn a degree from the school of hard knocks -- will get you into shape as well.
What almost everything boils down to is that a little time and work upfront pays off in huge dividends later in the development/release process.
The fact that you've noticed these issues so early in your career speaks well for your future, and I wish you the best of luck.