Randall Munroe (of XKCD) has a nice take on writing good code:
Of course, this is an over-simplification, but it is true that if you set out simply trying to write perfect code, you will never reach there. The achievable target is succeeding in meeting your requirements with a reasonable level of quality, which is defined as how much money and effort you are willing to spend.
Defining “good code” is tough. It is not enough to say “I will know when I see it.” Good code is a combination of so many things: Good architecture/design, adherence to coding standards, minimal code, proper error-handling, high performance, readability, maintainability and so on. Some of these can be mutually conflicting. Writing high-performance code can reduce maintainability and readability in some cases. For example: using hardware-specific code to gain extra performance, or using lower level data structures. Quicksort is less readable than Bubblesort, but on the average, offers higher performance.
Then there are differences of opinion, especially between warring camps of technology or language. Static vs dynamic languages. SQL vs noSQL. Take your pick. Even the same person with experience may change their opinion of what is good code. Which means that code considered good sometime ago may qualify as bad code today.
As the comic suggests, one significant problem is changing requirements. This is true even for tiny projects. I had a book reviews section on my personal website, that grew from a handful of reviews to hundreds of reviews. Over several years, I had to make literally hundreds of code revisions for the small code base (around 30K) to add functionality (searching, tags, Amazon / Gutenberg links, images). And I expect to do more changes in the future, even though I am reasonable happy with the current functionality.
And then there is new technology. Every time a new version of your language, platform or database comes up, it usually comes with features that reduce the code that has to be written. So your present code looks outdated. Take .NET, for example. How much less code could you have written if Linq was available in 2003 instead of 2007? Or in Java, if frameworks like Spring or Hibernate were available earlier? Or switching to Ruby on Rails from JSP or ASP?
So, perfect code is a mirage. That doesn’t mean that one should stop learning. Vehicle manufacturers have yet invented the perfect car, but they don’t stop trying to improve their existing cars. It is worthwhile to keep educating oneself and use better tools and techniques. But realize that good code should be a property, not a final goal of software development, which is to ship products with an acceptable (and expected) level of quality.