I used to be a bad employee, I'm still not a perfect employee by any means, but I used to be afraid to write code and when I wrote code it was never good code.
My code is still far from perfect, but now I'm not nearly as afraid to code, even if I end up throwing away the project or not showing it to anyone...
In my free time I've always worked on side projects to become more competent. But a lot of the sites I made were bad, or I never finished. But despite these failures I like to think I've gotten better at it, as failures are an important part of learning.
It's like when little kids play with Legos and make their first rocket ship, chances are it isn't going to win any awards or be picture perfect. But once they complete it, and promptly destroy or dissemble it they realize what they could've done better (sometimes before even finishing it)
And the next time they create a rocket ship they learned from the previous exercise and the new rocket ship is slightly better
It's all about being iterative and trying new projects and reevaluating what went well, and what didn't go well, and figuring out how to improve it for next time
One of my favorite projects I like to make for learning a new tech stack is to make a Tinder clone that shows gifs from giphy's trending api and have the swipe right save the gif to their favorites and left dismissing the gif for the next one.
It's a great project because you can easily keep adding to it (just like your lego rocket ship) and add more features that you might've not realized were important on the first go around (such as pagination, searching, user authentication, etc.)
Let's go back to the rocket ship example. Say you told a kid to make a rocket ship and they made one. Great, now you tell them that the rocket ship needs a cargo bay and an external booster. Chances are the rocket ship they made won't be best suited for these expansions and they'll start taking it apart to reorient the design / architecture of the rocket ship to accomplish these new specs, but if you told them that they couldn't take the rocket ship apart that's when these analogy becomes the reality with software development
A lot of the 'legacy' systems and the problems associated with them that we run into are issues with a phase 1 design rocket ship being given new requirements without giving the developers the ability to re-architecture the rocket ship design to be better suited for the current needs of the rocket ship.
The reason I feel one should redo projects more than once is that one will begin to realize when one architecture works and fails (essentially how far you can go with one rocket ship design before you need to add your multi stage booster design, cargo bays, docking latches, etc) as well as how you should've implemented each of these features / architectures if you had to do it again.
You begin to realize from experience the merits of different technologies / frameworks / architectures by using them in practice.
A lot of the tutorials and sample projects don't take you far enough to learn the merits (and this is criminal)
I feel a lot of people (just like kids who built their legos) are proud and attached to their work (as they should be (I think this is even more so if that rocket ship is making money for the company hah)) and don't always take constructive criticism on how they could improve the design if they made dramatic changes to it.
A lot of the time, I think it's just a matter that they haven't built or seen that kind of rocket ship before and they can't understand why 'that' alternative could be better if they already know their version so well.
You might've noticed that iterating over a rocket design, adding features, evaluating what went well, what didn't go well... sounds slightly familiar. It is, it's very much the agile method. Just not in a formal definition of two week sprints with a retro / planning ceremonies.*
*You can actually apply the agile method to things besides work or learning. And use the agile method for other things such as cooking, exercise, or even running errands. (might be the topic of a future post, but its just some food for thought right now.)
In conclusion I think one should come up with a personal project that they like to re-implement in different frameworks and tech stacks so that they can begin to learn the differences and strengths between them. I think this exercise also gets people to become better at dividing work up into phases (mvp, phase 2, etc) and realizing when one needs to redesign something to make it scale (or what have you.)
Because once you get into this habit, and make the analogies and connections between them you begin to realize that playing with code is a lot like building with legos and who wouldn't like a fun project/goal such as a rocket ship to learn how to play with code?