Often I think it is quite similar to the situation where some people can not conceive of doing endurance sports. They view it simply as pain, or at the very best boring repetition. Others thrive on it. But if you want to learn how to enjoy endurance sports, it's probably a good idea to acknowledge that there will be times where you will be uncomfortable (possibly intensely so).
I'm not OP and my interpretation is probably not what he meant, but when I saw that line, I wasn't seeing learning as pain, but more so as living the pain that justify the better practice.
> Project-driven learning seems more effective when the project is something that excites the learner.
I agree completely on that, but we can easily screw up that part by going too technical too quick. It transform a quick and fun project, into something much bigger (learning take a long time) with much less direct result. Fibonacci is a great example I think because it's so quick to achieve, there's so much potential to improve it in multiple ways, and it doesn't require much technical knowledge of the development environment.
When I tried learning React, I was going for a fun quick project, but then I thought, well if I'm going to do that, I'll go with some database to store my data, an authentication layer seems also an obvious requirement, all deployed in dockers, with some server rendering, etc... Which individually all could be quite simple to add in crude ways, but theses decisions all stemmed from the fact that I wanted to reach perfection from the beginning, which make all theses individual feature now become something much bigger and much more complex to reach. If instead I just do the same project, no database, just a big array that I modify, stored in a cookie, no authentication, no dockers, no server rendering, I can build it much quicker, and thus learn what I need to improve much quicker too. Afterward I can add a database if that's what I want to go for, and then authentication, maybe some server rendering afterward and maybe, a docker to deploy it easily.
For example, nobody is forcing me to use Docker from the start. I don't have to use it until I decide the development or deployment pain is big enough that I will learn how to use Docker. Similarly, why do server side rendering when you can have a perfectly working project without it. Add server side rendering later, when you project actually has real features. Not from day one. The temptation to use cool tech from the start is difficult to ignore at first, but after a few attempts to do a side project, only to give up before you've even started, it gets easier to appreciate stack simplicity :)
Trying to keep code as simple as possible from the start is more difficult, i.e. you might be structuring your code too naively and regret it later when you try to refactor. But as we know, abstracting too early creates similar if not worse problems.
If you write internal tools for a company then it is SO powerful to write a front-end without a back-end.
Ultimately this gets into a method of Extreme Programming (viz. waiting on features until the absolute last minute) married to the philosophy of Domain-Driven Design.
In DDD you want to establish Bounded Contexts for language, then within that context you want every programmer to speak in terms that clients could understand. Being able to change your data model cheaply is deeply powerful here as you can just give someone an interface saying “it won’t save your changes yet, just try it and see how you would do your day-to-day work with it and tell me what doesn't make sense.” And then they will say (assuming an accounting app) “what do you do with purchases that don't belong to a contract, how do I input them?” and you say “what do you mean, I thought we were tracking purchases for contracts?” And they will be like “A pitch is different than a contract, but we still purchase things for pitches but we don't need all of these details for it.” And you're like “if I were to show you a list of both pitches and contracts, like what would that be a list of?” and they reply “that would be a list of projects!” and then you build a list of all projects into your app.
And then when you build the back-end, you have one database representing the bounded context, and it has a projects table (UUID id [PK], string name, UUID pitch_id [nullable], UUID contract_id [nullable]), a constraint to make sure that exactly one of those IDs is NOT NULL, and a purchase table that foreign keys to a project. the key point is not that this is a clever database structure, but that it was molded to the hands of the people who use it, by delaying the binding of that data structure into a concrete relational form as late as possible.
That's not the case though - why would I reinvent the wheel when I have finite time to get something done? I love to suss out solutions to all sorts of things on my own time, but if I have to left pad a field, I've already got lodash, I'm using that.
In addition, when someone goes back to read the code "_.padStart" just makes sense to read.
I'm not saying that understanding doesn't lead in repetition and effort, but I think you're wrong on why people use libraries. It's not because people don't want to know, they gotta get whatever it is they are working on done.
Might as well shortcut all that and see if there is something in standard library or in an existing package...