Most people believe very strongly that the best way to learn is to learn by doing. Particularly in the field of programming.
I have a different perspective. I see learning as very dependency based. Ie. there are a bunch of concepts you have to know. Think of them as nodes. These nodes have dependencies. As in you have to know A, B and C before you can learn D.
And so I'm always thinking about how to most efficiently traverse this graph of nodes. The efficient way to do it is to learn things in the proper order. For example, if you try to learn D without first understanding, say A and C, you'll struggle. I think that it'd be more efficient to identify your what your holes are (A and C) and address them first before trying to learn D.
I don't think that the "dive into a project" approach leads to an efficient traversal of this concept graph. That's not to say that it doesn't have its advantages. Here are some:
- People tend to find the act of building something fun, and thus motivating (even if it has no* use other than as a means to the end of learning).
- It's often hard to construct a curriculum that is comprehensive enough. Doing real world projects often forces you to do things that are hard to otherwise address.
- It's often hard to construct a curriculum that is ordered properly. Doing real world projects often is a reasonably efficient way of traversing the graph of nodes.
Side Notes:
- Informal response: "C'mon, how many of the projects that you do as you're learning ever end up being used, let alone produce real utility for people?".
- More formal response: I really believe in the idea that productivity of programmers differs by orders of magnitude. Ie. someone who's 30% more knowledgeable might be 100x more productive (as in faster and able to solve more difficult problems). And so... if you want to be productive, you'd be better off investing in learning until you're really good, and then start to "cash in" by producing.
I mostly taught myself to program. Did an intro class freshman year of college. Five years later my adviser had me tackle a certain math problem using the computer and to do that, I had to learn a fair bit of programming. I had the distinct impression of being thrown into the deep end and told to figure out how to swim.
I noticed that there's a certain understanding that comes from actually applying a concept that I just didn't get from reading the book and working through the examples. I eventually picked up the habit of looking for a nontrivial application whenever I came across new programming concepts. Oftentimes the application I had in mind would require filling in gaps in my knowledge. Throughout I'd use a lot of things I didn't really understand (by modifying existing code) to get things done, and then when I'd come across that part of the theory everything would just seem to click.
I figure that most programming techniques were invented to deal with specific problems, and understanding those problems gives a lot of intuition about the techniques.
As Euclid once said, "there's no royal road to geometry". Practice means making mistakes, figuring out your misconceptions and gaps in understanding, then grappling with the material until it finally makes sense.