The scariest place to be as a programmer is when you look back at what you did 6 months ago and still think to yourself that its pretty good. A little regret is a good, good thing.
Five years ago, I would add a new feature and 50% of the time it would be a fair bit harder than I expected, then maybe 30% of the time I would find it easier than I expected, as I had designed the code well, and it was set up for extending / reuse.
Nowadays, I am getting better. If I don't understand a bit of code I wrote a few months back, then I use it as an opportunity to look at it freshly. Why is this code crap? Why is it making what I want to do difficult? How could it be better? That's a good place to start refactoring from.
In addition to this, reading and being able to understand other people's code will provide great returns. You learn about styling, coding standards, architecture, patterns, etc that you might have never stumbled upon if you attempted to code everything yourself.
That must depend o having decent code to work on in the first place. Seeing some of the comments in the code bases I have worked on, I am not sure I was going to learn anything there.
To rephrase: write more code. months later, look back at your early code, see if it still makes any sense to you today ;-) rinse, repeat in different languages, situations or version numbers.
It amazes me that despite all the efforts made to improve programming languages, the debugging tools we're using are so clunky. I really wish more effort was made to improve them.