- Face the problem first, then look for solutions
- Choose a tech stack and stick with it
- How learning actually happens
- Build! It’s the only thing that matters
- It takes time
- Clone open source applications
- Join the community
All of this would not be possible without the help and guidance of the community.
Teaching yourself programming is tough, probably one of the toughest things I’ve done, so I wanted to give back and share a few lessons I learned during my journey that might be helpful to others and hopefully make someone’s journey a little easier and less painful.
Before I begin, a few disclaimers
- I wasn’t 100% new to programming; I have an Engineering degree and during my University time I had a couple of programming courses.
- As a Product Manager in tech, I’ve worked with Software Engineers most of my professional career, making it easier to grasp certain ideas.
- What worked for me might not work for you. Adjust it to your specific situation and pick the ideas that make sense to you.
- I’m not an expert, I haven’t even got my first Software Engineering job yet, so take everything with a grain of salt and challenge my ideas.
Without further ado, let’s begin
If you want to better understand how technologies, programming languages, libraries and frameworks fit together, don’t just learn them for the sake of learning or because someone said you have to.
Face the problem that the specific technology is solving before learning it.
By this I mean
- Don’t just learn CSS, learn HTML first. Eventually you will encounter the limitations of it, making it easier to understand what CSS is for and what problems it’s solving.
You get the idea. You want to understand the problem first, so you get why the specific technology is used to solve the problem and how it solves it.
There is just too much stuff to learn out there. There is no way you can learn everything there is, and no one is expecting you to do either, so relax and pick a technology stack that you can solve problems and have fun with.
You will get paid to solve problems, not just because you know a bunch of technologies and programming languages.
Programming is a mechanism for solving problems, from tiny everyday tasks like downloading a spreadsheet from the cloud to real-world problems like global warming and space exploration.
So at the beginning of your journey, it makes little sense to learn two programming languages, two front-end frameworks or two database models.
You should focus your efforts on how to solve problems and pick a strong technology stack that can help you accomplish that.
One of my biggest interests is on the science of learning, acquiring knowledge, and how learning actually happens.
I’ve studied and read about these topics for years and I could write an entire book about it so I will try to be as brief and to the point as possible. If you’re interested and want to know more about these topics, reach out to me and we can chat about it 😁.
Programming knowledge can’t be transferred from one person to another, it has to be built, and it’s built on top of what you already know (your mental models). Programming falls under what’s called tacit or implicit knowledge.
Think about Karate for a moment, Karate is impossible to teach through descriptions. You could watch 10.000 hours of Karate lessons and read 100 books about it, and you won’t be any better at Karate.
Another example is facial recognition. We know a person’s face, and can recognize it among a million other faces. Yet we cannot tell how we recognize a face we know, so we cannot put most of this into words. No one can teach us how to recognize a face.
This explains why, as a beginner, you could watch videos of someone coding or teaching some programming concept for hours and when faced with the code editor, you could not write any code by yourself.
We acquire tacit knowledge not through language but by observation, imitation, practice, apprenticeship, and feedback.
The key to acquiring tacit knowledge is experience and pattern recognition.
Imagine yourself seated next to a senior programmer who skimmed your code and gave you several recommendations after a couple of seconds.
You ask her, “How did you do that?”, and she replies: “I’m not sure really, it just felt right.”
What went on in her head during those few seconds? How could she do that so easily and fast? You wonder.
When experts face a problem, they observe the situation and immediately match it against a collection of patterns they already have in their brains.
If they recognise it as a known pattern, their brain immediately comes up with four things:
- A set of expectations: Experts will construct mental simulations of how the events happened and how they will continue. In other words, they will have some expectations for what happens next.
For example, the senior programmer reading a codebase might find several weird functions, and immediately suspect that a bug could develop or that edge cases are not being covered.
- A set of goals: Experts would know what to prioritise at the moment.
The senior programmer may receive a set of business requirements and immediately generate a prioritised list of goals in their head according to the recognised pattern.
- A set of relevant cues: Experts know what to pay attention to, beginners do not. Patterns come with a set of cues.
For example, when you’ve just started driving, you may find yourself overwhelmed with all the things you have to keep track of. But after a few months of practice, you do these things automatically.
- An action script: If the situation is typical, the senior programmer would have a course of action generated in her head. If the situation is not typical, her brain would still generate a set of actions, but she would slow down to walk through each action step in her head.
It’s important to understand that all of this recognition happens within implicit memory. Therefore, experts cannot describe with words what they are doing. It just happens too fast.
When you are learning from someone, what’s actually happening is that you are developing patterns in your implicit memory. Patterns that allow you to identify cues, goals, action scripts and expectations.
So the questions we should answer are
- How do we develop these patterns?
- Are there ways to get better at observing, imitating, and practicing?
- How do we optimize for feedback?
To broaden your spectrum of patterns, you want to identify areas of your knowledge and situations where you feel you are less experienced and systematically expose yourself to them.
Solve coding challenges and problems while thinking how these could be applied in context and projects, and how could you use them in real-life situations. Don’t just solve them in isolation.
When taking a course or doing a tutorial, identify when the instructor has a pattern you don’t and start wondering how the instructor arrived at the solutions, what was going on in her or his head and what was the context.
Try to emulate the way the instructor is thinking, what cues did he or she used to arrive at the solution, what were the expectations, priorities, and courses of actions that present themselves in the instructor’s mind.
If you encounter a situation where you would do something different from the way the instructor solved it, it also signs that the instructor is using tacit knowledge.
Get really good at identifying these patterns and then consciously try to emulate the situation and arrive at the same solutions by yourself, without external help. If you can’t, go back and repeat the process.
This boils down to asking lots of why questions.
When asking for feedback, describe the event linearly, as you experienced it, never revealing more information than you had at the time. You should put the expert in your shoes.
You want to compare:
- What cues you noticed vs what cues the instructor noticed.
- What you expected to happen vs what the instructor expected to happen.
- What actions you thought to do vs what actions the instructor thought to do.
Finally, reflect on what went well and not so well during a feedback loop. It will help you increase how much you learned from the experience and develop patterns faster.
It’s almost a cliché by now, but cliches are cliché for a reason. If you really want to solidify your knowledge and put it into context, build things.
In the previous section I wrote about how knowledge and learning work inside your brain and how repetition and practice will help you grow patterns. Building projects, applications, websites or whatever it is, is how you put it into context and tie everything together. I won’t go deeper into that.
What I will suggest next is what kind of projects I would build in order to maximize for two things: learning and your portfolio.
The typical to do app you get to build in your typical programming course or tutorial won’t make it, and don’t get me wrong here, to do apps are good for learning purposes but they are not for your portfolio. Future employers won’t get excited about them. With to do apps, you’re just maximizing for one of the two goals you want to maximize for.
And notice that by to do app I also mean every small to medium size application that you get to build side by side with an instructor during a course or tutorial.
Also notice that I’m not telling you not to build them, I think you should and it’s an important part of your learning process. Just don’t stop there, you want to build something of your own, without being hand held the entire process. You want to face all the struggles that building an application from zero entails.
When I say build something of your own, I’m thinking about the following characteristics
- The application is of your interest. You want to like what you are building because you are going to be building it for months.
- You want to make the application big enough that it takes you at least a couple of months to build.
- You want it to be a living thing, growing and improving over time as you learn new things.
- If possible, cover an entire stack of technologies to build it. Incrementally adding them as you learn them.
Why building something that big you wonder?
Most of what you will do as a Software Engineer is working with an existing codebase that has been under construction for years, so you want to experience how an extensive project is really like, how each part and technology is connected and interact with each other.
When applying for jobs, you won’t have that much competition if you have one or two big projects in your portfolio. Most won’t have any. So you get to differentiate yourself.
- I built the data scraper using Node.js and Puppeteer.
- The front-end uses React, styled-components and React Router.
- The API uses Node.js with Express.
- The DB is MongoDB with Atlas and Mongoose.
- The back-end is hosted on Heroku and the front-end on Netlify.
- The test suite is built using Jest and Testing Library.
By building this project I’ve been using almost an entire stack of technologies.
Also note that I’ve been building this project for months, slowly adding features, refactoring and improving the codebase and adding technologies as I learn them.
The idea is to build something of your own, scratch your own itches and solve your own problems, struggle to build it, find your way through and show it to the world (and employers).
Learning to code takes time. There is no way around it. Your brain has to develop millions of patterns and connect thousands of concepts and ideas together. That just takes time.
Don’t take my word for it, please read Teach Yourself Programming in Ten Years by Peter Norvig. I highly recommend it.
Your foundations are the most important thing in your journey, don’t rush on them.
Set reasonable goals for yourself, no one is expecting you to learn programming overnight. This is a marathon, not a race, a lifelong marathon indeed.
Sometimes it will feel like you are not making any progress, like you are stuck or even going backwards. That’s a good sign actually, this means you’re advancing through stages in the four stages of competence model.
There are four stages of competence:
Unconscious Incompetence: You don’t know what you don’t know. You don’t really know what’s out there. You’re ignorant.
Conscious Incompetence: You know what you don’t know. You become aware of what’s out there, but you don’t know how to do it yet.
Conscious Competence: You know what you know. You are aware of what’s out there and know how to do it, but it requires concentration and effort.
Unconscious Competence: You don’t know what you know. It becomes second nature or part of your unconscious mind. Think your native language, when you’re talking in your native language it’s almost second nature, you’re not constantly thinking about it, you just do it.
Don’t get discouraged if you feel like the mountain keeps getting higher and higher, you are actually making progress and becoming aware of what’s out there. You just have to keep pushing.
I read this idea first from Ryan Florence, and it has stuck with me since.
If you want to level up your programming skills, you have to read code, ideally code written by experienced developers.
In the words of Ryan Florence “My favorite thing to do is find some OSS thing that seems a little beyond my experience to build (for me that’d be maybe react-spring) and then try to build it, referring to the OSS source only when you’re totally stuck.”
This comes back to the idea that to acquire knowledge you need to observe, imitate, practice, and get feedback.
So how do you do it? How do you apply this process by cloning open source projects?
Try to build it yourself first, if you get stuck, go check the source code and keep building it yourself until you get it.
Don’t make a pixel perfect implementation of the project, just pick those parts that are of your interest or relevant to what you are learning.
How to get feedback on it? Just compare your implementation to the one made by the experienced developers.
Reflect on the differences between implementations. Go back to the “How learning actually happens” section and go through the feedback process. Ask questions and try to simulate in your head the cues, expectations, goals and action scripts the developer went through to arrive at the solution.
I think this is such a good idea and is so helpful to level up your programming skills that I’m putting together a repository of React projects built by experienced developers that might be helpful to use for this process.
Check it out here
The community is one of the most important aspects of your journey, and by community I don’t just mean places like Dev.to, Twitter, FreeCodeCamp or HackerNoon but also local Meetups, conferences and learning clubs.
Most of society’s advancements, innovation and knowledge are built on top of what others have already built before. Communities make this possible and make transferring knowledge easier and faster.
Most of the cool technology and software we have today has some kind of open-source code under the hood. From just a couple lines of code to entire libraries and frameworks like Preact and Vue. All this is enabled thanks to the community working together as a whole and individual contributors supporting each other all around the world.
You are not alone in your journey, you can almost certainly find someone that has already walked the path you are currently walking, and you can almost certainly find someone that is walking the same or similar path you are currently walking.
When you take part in the community, you are suddenly exposed to a new world of opportunities. Put yourself out there and help the community grow and support each other out.
And never forget to give back. There is always someone out there that might need your help and who you can help improve and grow. We are all in this together.