I believe projects complexity increase exponentially as it grow in size, anybody noticed that too?
I do. For me there is a directly opposite force to coding that I call "programming inertia". When I code for clients I'm aware of this problem and try to keep solutions as simple as possible (KISS), and well structured/documented to be friendly with clients/partners. But when I get into personal projects these are long-term developments that really push my limits, and the inertia feels really really strong. I actively experiment with techniques to avoid it, for example by taking ideas from experiences on low level languages like Assembly oriented to micro-controllers, and very high level languages like Javascript in a resource careless way.
In general I have shaped and keep improving my workflow having these aspects in mind:
Code visualization. There is an amount of the whole algorithm that you can visualize at once. As the code grows you will start forgetting parts, and then you will have to read it again. If you can't catch the algorithm while reading, you will have to study the code to find how it flows. This effort will make your mind drop other parts of the algorithm. Structure and documentation can help you to pick up those parts again, but then documentation also contributes to the inertia. Comments are part of your code as everything else, in the end these are algorithms written in natural language or as diagrams, which are simply translations of the algorithm. For that reason minimizing code as well as documentation reduces inertia. The code must be self explanatory. When it's not, comments are required but only to the minimum. Then if comments are not enough when studying the code, these must be enhanced with the missing information to pick up the algorithm quickly next time.
Typing vs. thinking. The easy part of programming is typing. You can write hundreds of lines per day, even more with code tools, but solving a difficult problem that requires a single line a of code might take several days. So you have to transform problem solving into typing, and solve the difficult problems when the inertia is low. Practice is what gives you a catalog of tools that you can plug into the code to solve a given issue, that's the way you convert thinking into typing. It also helps you foresee those difficult problems that you must prioritize, to avoid being hit the inertia shockwaves.
Procrastination by coding. This could be offensive to many programmers, but it seems that most languages have these programming features that only distract from actually hammering the problem. And there are these protocols/patterns that become problems in themselves. Even at some point programmers adopt practices in their workflows that have nothing to do with solving tasks, because decorating the code is fun, but all that is procrastinating with the art of coding. There is a minimal set of programming features that will allow you to create good software and is common between languages, but language creators add extra features to do things in different and interesting ways, because they need to attract more users. All of this only contributes to the programming inertia. Actually most language features focus on easing the typing and reading, but thinking and studying is still required, and so those are adding nothing really useful. The programmer must be smart enough to avoid these language traps, and keep with the minimal common language, that will also help him/her to quickly move from one programming language to another.
For me thinking on problems is the fun, having to learn new things to solve problems is fun, and how hard all of this is doesn't matter. But the programming inertia caused by these aspects and personal or external issues is what kills the fun. I think being a programmer is a way of living, probably a good reason to consider it an art. You have to apply problem solving to everything else before you can actually program.