Both paths definitely work, so exploring them with trial and error is more important than finding the theoretically best one.
Personally, I found learning fundamentals more intuitive as I couldn’t reason about how the software worked at the beginning. I found computers unpredictable, and interacting with computers wasn’t fun at all. In contrast, I found the fundamentals reasonable and intriguing. Thus, I could spend years getting better at fundamentals with programming contests like ICPC or IOI. Even when I was reasonably good at programming contests, I was mostly clueless about how the software worked.
I still could use those experiences to get into good software companies, where I gradually learned tremendously and got better at software engineering. In various companies, I could see great engineers taking widely different paths from mine. Many enjoyed interacting with computers and learned to leverage the magical machine over time. Gradually, they realized the importance of fundamentals got better with trial and error.
In conclusion, software engineering is complex enough that multiple paths exist to reach expertise, but you need a long time to develop skills1. To avoid hitting a plateau, you need challenges that are hard enough to grow your skills but interesting enough not to give up (a.k.a., deliberate practice ). You need even more challenging tasks to sustain your growth trajectory as you get better. With this idea, a specific path you take isn’t relevant, but the biggest enemy of growing expertise is repeating the same thing over and over.
Teach Yourself Programming in Ten Years by Peter Norvig ↩︎