Do you remember the last time you were in the "zone", coding away like 5 people, and feeling good? I remember it very well. It was a few weeks ago, and it's the reason why I'm posting. In three hours, I've written 1500 LoC, and I got insights how to continue from here on, and if I would have gotten more sleep the day before, I would have probably continued hacking too long into the night.
But let's look at this "zone", also known as the "flow", which is a nebulous thing. There is a great diagram describing the conditions when the flow sets it. Basically, if you have high skills, and an appropriate challenge, then you are right in the sweet spot. There's one catch: First of all, most of the time you don't have the right skill level, and second, not every task is a high challenge.
I remember a famous quote of -- as far as I know -- a Russian coach, saying "talent is what allows us to survive the training". I think this also applies to programming, and getting into the zone is surely easier for people who have the programming talent than for the rest. But even if you are not gifted with it, there is one sure thing which helps me to get into the zone, and might help you also:
Stop thinking about your problem. Start coding.
I remember each time I start thinking through details, designing large pieces of code in my mind, thinking of many algorithms, I stop being productive. It's so simple. Most probably, the task is large, and if you start thinking through it in detail, you immediately see problems en masse. Which makes you think more, how to avoid these problems, making the whole task even more complicated. It's a vicious circle.
There is only one cure: Stop worrying. Start working on it, by writing code. Often enough, you'll be able to write some working solution, just to get going. This is of course not an excuse to start without any design at all: Think up front how to divide your task, even make an UML diagram, but don't try to solve all problems up front. Rather, after having some working code, iterate over it! You'll be impressed how much faster you get the work done if you either prototype something and rewrite, or simply try as good as you can, and refactor. After all, even the worst code can be rewritten or refactored, but it still requires at least some crappy code to start with.
The same applies to these stupid tasks which simply take time, and where you hesitate to start them because you know you'll have to do a lot of work. Point in case: In a large personal project, I've been replacing a STL class with a custom one. Well, I immediately estimated that I would have to touch a few hundred places, and it will take me one day at least. The same rules as for profiling apply here as well: Assume nothing, but measure! A quick search told me 150 locations have to be touched. At this moment, the task was no longer a mysterious beast, it's simply a marathon, and you can train yourself for it. Grinding through code requires just this, training, and a clear progress indicator. After less than half an hour, I was done with what I previously assumed would take me 16 times longer!
Learning by failing
A different aspect of our craft: How do you improve your skills? If you do as described above, you're using a very effective method -- you start working on problems which are too complicated, and often enough, you'll fail. This might sound counter-intuitive at first (how the hell does this make me better?), but the learning effect is much higher than in all other cases: First of all, in your first try, you probably attack the problem from a totally wrong side, and second, you understand why your particular approach is not good (side note: This post has been prewritten several weeks before it has been posted).
I probably use this approach too often, but so far, I'm still pleased with the results. Funnily enough, I guess I'm getting better at failing -- during this week, I think 3 algorithms I implemented turned out to be not sufficient, and required a lot of additional work. So if you're out to learn just like I do: The next time you hit a problem where you are about to look up the answer, just try on your own, and if you fail, come here and comment ;).