Is Learning to Code Hard? What Years of Teaching Taught Me

What do you picture when you hear the word "coding"?

Perhaps visions of dense, incomprehensible lines of text scrolling on a screen? Intricate commands, symbols, and other characters, as unfathomable as ancient hieroglyphics?

data/admin/2023/6/confused-man-code-symbols.gif

I've been a programming teacher for several years, and a full-time bootcamp instructor for four of those.

I've seen students from every kind of background, at every age and stage of life, walk through our doors and get into coding.

I've also had a front-row seat to the rise of AI, which we'll tackle in due order.

I've also had a first-hand perspective on the rise of AI.

So I think I have a good perspective on the question above, and will do my best to answer it, if indeed you are trying for yourself to decide whether learning to code is right for you.

Joe Di Trolio class photo

Orientation

Let's start with basics. One of the first things I noticed when teaching beginners was that the struggle began before way before the code.

Students were not always stuck on programming concepts like variables or functions. Often, they were stuck on the surrounding environment: installing tools, understanding what an IDE (code editor) is, navigating the file system, creating and saving files, and working out how all these pieces connected.

It is easy to dismiss this as basic technical knowledge, but for many beginners it is their first real barrier

If they lacked it, learning to code was much harder for them.

Before you start, you do not need to be a technical wizard, but you should be comfortable using a computer a little beyond the average user. I’d also recommend learning some basic terminal commands, as the terminal is often used to navigate projects, run programs, install tools, and troubleshoot issues.

An individual feeling overwhelmed while trying to understand a coding environment

This is why I am not always a fan of the "just start coding" advice some tech influencers promote.

Experienced programmers often take the wider coding environment for granted, but for the beginner, all of this can blur into one really confusing workspace.

Coding is weird

Teaching different kinds of students also meant dealing with a variety of baggage. I mean that in the nicest possible sense. 

They'd bring it in from all sorts of places: ordinary language, mathematics, school exercises, previous jobs, everyday metaphors and some interesting beliefs into what coding is really "for".

The problem is that programming borrows from all of these areas while also changing the rules.

Let's take a simple coding example: assignment

In many programming languages, a statement such as this is completely normal:

let a = 2;

It concerns a variable, a, which is a sort of bucket for a value. For a beginner, this may seem straightforward enough. The variable a now stores the value 2.

Ok, that's all well and good, until the budding learner encounters something like this:

a = a + 1;

To someone thinking in purely mathematical terms, this looks weird.

How can a be equal to a + 1?

In mathematics, that statement appears impossible. In programming, however, the equals sign is not just saying that two things are already equal. It is performing an action. It means: take the current value stored in a, add 1, and then store the new result back in a.

So if a was previously 2, then after this line runs, a becomes 3. Makes sense, right?

Beginners are not always confused because the idea is complicated in itself. They are confused because the symbol looks familiar but behaves differently inside a programming language. Learning to program can mean unlearning one meaning and replacing it with another.

I am an academic at heart, so I have read quite a bit around this subject. What is interesting is that Benedict du Boulay, a University of Sussex academic, was making a similar point as far back as 1986 in his article “Some Difficulties of Learning to Program.” Published in the Journal of Educational Computing Research, the article explores why beginners struggle with programming, including the way helpful analogies can sometimes mislead learners.

There seem to be three important types that teachers of programming should look out for. First there are errors due to the misapplication of analogy. These are errors that arise when the learner tries to extract more structure or relationships from an analogy than are warranted. For example, students often believe that since a variable is like a "box" it can hold more than a single value.

Du Boulay follows up with a classic example: swapping values. I want to show it here because it captures the problem neatly, although I will use JavaScript rather than Boulay's original 1980s Pascal.

Imagine we have two variables:

let a = "tea";
let b = "coffee";

A beginner might think that swapping them should be as simple as this:

a = b;
b = a;

But this won't work as intended.

Once a = b runs, both variables contain "coffee". The original value of a, "tea", has been overwritten. By the time the second line runs, there is no longer any "tea" stored in a to copy back into b.

The correct version needs a temporary variable. The temporary variable provides a place for storing a copy of a.

let temp = a;
a = b;
b = temp;

This example is useful because it shows how strict sequencing is in programming.

The computer does not preserve the learner's overall intention. It does not think, "they probably want to swap these two values." It simply follows each instruction in order. If an earlier instruction overwrites a value, that value is gone unless the programmer deliberately stored it somewhere else.

It is one of those things experienced developers barely notice anymore, but for beginners it can be a real mental shift.

In normal communication, people constantly infer what we mean. If we explain something slightly out of order, another person can usually fill in the gaps. A computer cannot do that. It simply follows the structure of the instructions rather than the intention behind them.

Wabo has followed the first instruction literally. The pristine white tablecloth is now draped awkwardly over the tall, lumpy mountain of garbage on the table. Wabo stands next to it with a thought bubble: "Table set. Next instruction: clear boxes."

Indeed, notice how I described a variable as a "bucket." Du Boulay is critical of analogies like this. They can be useful because they give learners something concrete to picture, but they can also mislead. A real bucket can hold several things at once, whereas a simple programming variable typically holds one value at a time.

So in programming, small details really do matter.

Take also the example of punctuation, in programming, small symbols such as brackets, quotation marks, commas, colons, indentation and semicolons can completely change the meaning of code.

To the beginner, this can feel ridiculous. How can one tiny mark break the whole thing?

This is very different from ordinary writing. In an essay, a missing comma might make a sentence awkward, but a reader can usually recover the intended meaning. Programming is much less forgiving.

This is why I believe, right down to my core, that beginners are not simply "bad at computers" because they struggle with variables, assignment, or punctuation. They are learning a whole new symbolic system, and that is a difficult thing to do.

I really like an analogy Du Boulay makes by comparing learning to code with learning to use a toy construction set, such as Meccano:

"Learning to program is like learning to use a toy construction set, such as a Meccano, to build mechanisms, but as if inside a darkened room with only very limited ways of seeing the innards of one's creation working.

To someone unfamiliar with engineering many of the pieces inside such a set look very odd, and while the learner may have some general idea what the set as a whole is for, to build cars and cranes etc., she or he may not realize how apparently dissimilar mechanisms can be decomposed into similar small chunks and how the shapes of the pieces in the set are suited to the construction of such standard chunks."

But here is some good news, and I have seen enough of it in my time to know it holds.

Once beginners realise that code has to be read on its own terms, many early frustrations start to make more sense.

The good baggage

Let's turn our attention to some of the good baggage I'd often see students bring to the classroom.

When they came from certain fields, some seemed to pick up programming more quickly, possibly because their previous discipline had already “trained” certain mental muscles.

You've probably heard that problem solving and other cognitive skills are a huge part of coding.

Architects and structural engineers, for example, often seemed to have a slight head start. I'd typically put this down to their spatial awareness.

Spatial awareness is the ability to understand and interact with the environment around you. It's your capacity to perceive structures, patterns, and the relationships between different components in a system. People often say that activities like playing chess, solving puzzles, or even playing video games can help enhance spatial reasoning abilities.

This matters in coding because a codebase is not just a flat list of instructions. It is a web of classes, interlocking functions, shared data, dependencies, visible and hidden assumptions, and decisions made over time. Being able to understand how those pieces relate to one another, and how changing one part might affect the whole, is arguably one of the most crucial skills in effective programming.

In that sense, programming can feel a little like navigating a physical environment. It requires a kind of mental mapping, similar to the spatial thinking an architect might use when working in AutoCAD.

There is research that backs this up. Studies have shown a positive relationship between spatial skills and success in STEM fields. For instance, Sheryl Sorby’s 2009 paper, “Educational Research in Developing 3-D Spatial Skills for Engineering Students,” found that spatial skills can be developed through targeted training, and that this can contribute to student success in engineering education. So it is not especially surprising that students with previous experience in another STEM field may have an easier time finding their footing when learning to code.

A separate study by Caughman and Weigel (2022) found that biology students' attitudes toward mathematics and computer science were closely linked. In other words, students who saw value in mathematical thinking were also more likely to see value in computational thinking.

Let me be clear, however, this is not make or break. Not even close. There is a much bigger factor at play.

I spent more times than I can count convincing students who were on the verge of quitting to simply persevere.

A sheer determination is the next kind of good baggage that'll take you far.

That matters because coding is not always like, let's say, an art class, where the relationship between effort and outcome can be seen almost immediately. In the early stages of programming, you can spend hours working hard and have very little to show but for a slightly more personal relationship with despair.

Yes, I do believe that there are some individuals who possess a kind of innate talent. The Beethovens of code, if you will. But of all those I've met and taught, they make up a tiny percentage. Indeed, if coding depended only on rare genius, we would barely have any coders at all!

That is because, by showing up and staying with the process, you develop that spatial reasoning we spoke of as a by-product.

Practice. Exposure. Struggle. Repetition. Emphasis on struggle. The experience will not always feel pleasant. It seldom is. But difficulty does not mean inability.

This is where I think comparing programming to human language is especially relevant, in particular when learning a foreign language.

If you’ve ever attempted it, you’d know that the early stages feel daunting. You are not just memorising words. You are learning grammar, syntax, context, rhythm, and the strange little rules unique to that language.

You worry about making mistakes, being misunderstood, or not understanding what is being said back to you.

But that's normal, right? You do not start having fluent conversations straight away. Slowly you get a feel for how the language works.

One thing I'd drum on repeat to our students is that the journey is not linear. It is more like a series of emotional ups and downs.

In your first month, you might feel great. You are writing your first bits of code, things are appearing on the screen, and you start thinking, "This is amazing. I'm flying."

Then, just as you start getting the hang of JavaScript and things are going swimmingly, do you think we are going to allow that? No. Absolutely not. You start learning a framework like React, cos everyone says that's the way to go. It won't take long before you think, "I hate React."

But as dramatic as it feels in the moment, it is never the end of the world. This is what the process looks like. You hit a wall, you work through it, you adapt, and then the next challenge appears. That does not mean you are failing. It means you are learning.

Yes, it is going to be intense. And yes, a lot of it is you versus you. You will need discipline, patience, and perseverance.

So be kind and patient with yourselves. The frustration, the dips, the sudden "I hate React" moments, all of that is totally normal. It's worth it.

You'd be surprised how much easier programming gets once you've built the foundations. Even learning other coding language gets significantly easier.

A watercolor illustration of a programming student seen from behind, sitting on a grassy hill with a laptop and looking into the distance, with rolling green hills symbolising the ups and downs of his learning journey.

If I may put on my pedagogical hat and make quick related side note for any teacher who may be reading this piece.

We do need to be careful about how we talk about aptitude, and even more careful about the assumptions we make about who is "naturally" good at this and who is not.

The cost of being written off before you have had a fair shot is often paid by underrepresented groups: women, people of colour, and people from non-traditional backgrounds who are already fighting uphill battles to carve out space for themselves in tech.

And once a student starts to believe they are not the "kind of person" who can code, that belief can become more damaging than the original difficulty.

Some arrive with confidence. Some arrive having already absorbed the idea that technology was not built for them. They all belong. As teachers, mentors, or even peers, we should be very careful not to confuse starting position with destination.

Do you know your "Why"?

Another key observation: Before students could focus confidently on syntax or problem-solving, they first needed a basic sense of purpose.

They needed to understand not just how to write code, but why code matters and what it allows them to do.

This is an important point because many beginners do not only struggle with the technical details of programming. They also struggle to locate themselves within the subject, and until they do the whole thing can feel abstract and disconnected.

So ask yourself, why are you learning to code?

Do you want to change career? Start a business? Build an app? Automate parts of your work? Make websites? Understand the technology shaping the world around you? Or do you simply enjoy problem solving and want a difficult thing to get better at?

There is no single correct answer, but you ought to have some kind of answer.

If you struggle to articulate your "why," the whole experience will probably feel more difficult. Not impossible, but more difficult. Your aspiration gives you something to return to on the days when the code refuses to cooperate, which, as we've established, will absolutely happen.

In my experience, this became most obvious when students reached their capstone projects at the end of the course. Seeing the visible results of their work, they's often began to progress faster. Something changed when the they could point to their baby and say, "I made that."

That is why I think a self-directed project is one of the best things you can include in the process of learning to code. 

This is your opportunity to dive into a topic you're passionate about, and create something uniquely yours.

If you're stuck for an idea, simply ask yourself, "What problem am I trying to solve?" and "What can I do differently?". The best applications are typically those that address a specific problem or need, for yourself or for your community. Consider what resonates with you, and how you can potentially solve them with technology. It might be a problem-space you understand better than anyone else. Be entrepreneurial.

You could also consider the industries you are interested in working in. Your portfolio is a great way to showcase your skills to potential employers. By focusing your project on the industries you'd like to work in, you can make yourself a more attractive candidate.

Another cool thing to consider are the tools or technologies you want to learn or deepen your knowledge in. Your personal project could provide an excellent opportunity to get hands-on experience with these technologies, making you even more marketable.

I've had students build, intelligent menu systems, a virtual arcade, a score keeping system for their local badminton club, a game that helps improve your touch typing, a voting system for when humans colonise Mars, an AI recipe generator, An app for identifying waste and encouraging the community to come together to improve their community, An Anime/Manga discovery tool. There have been so many cool ideas.

The Ailephant in the room

Ok, we're finally at this point of the discussion, and to be honest I was avoiding it up until now.

But hey, we can't have an honest discussion here about learning to code today without talking about AI.

Geometric ivory line-art elephant head on a dark green marble background with pale veining.

As a teacher delivering full-time programming courses between 2021 and 2025, I witnessed the change firsthand. And boy did it change.

Students were using AI to explain concepts, fix errors, summarise lesson material, and sometimes complete entire exercises before they had fully understood what the exercise was asking them to do. I am quite sure ChatGPT became intimately familiar with our lesson plans during this period.

The fallout triggered intense debate among my colleagues, and I was firmly in the camp of, "This is not something we can simply wish away."

That ship has not just sailed; it has opened a bloody champagne bar on deck! 

The question is not whether students should ever use AI. They already are. The better question is whether they are using it in a way that supports learning.

AI can give students somewhere to turn when they are stuck, tired, or too embarrassed to ask the same question again.

That matters more than it might sound, because discouragement was one of the biggest reasons students dropped out, and remember what I said about needing to stay the course to succeed?

So there's value in the grind.

The early stages of learning to code are meant to feel confusing. Not because confusion is noble, or fun, or some grand rite of passage, but because that struggle is where the learning happens. If AI removes every moment of friction too quickly, it can also remove the repetition and wrestling that allow those ideas to compound.

A good teacher does not simply hand over the answer, and if you are self-learning, you should not do that to yourself either. If you are on a course or at college, questions of ethic and plagiarism aside, you are only cheating yourself.

For that reason, I would avoid leaning on AI too heavily for at least the first three to six months of your coding journey. You would not learn to speak a new language by running every sentence through Google Translate, don't do same to code.

I've dabbled a bit into the emerging research concerning the impact of AI in education. Becker et al. 2023, for example, propose using AI to support code reviews and expose students to the variety of ways a problem can be solved. That's indeed useful, as programming problems tend to have several valid solutions

And I agree with that. I really do. But only once you have built a decent foundation.

The best use of AI is not, "write this for me", it's "help me understand what is happening." A student might ask, "can you explain this error message without giving me the full answer?" or "can you give me a hint?" or "can you ask me questions that help me work out the next step?" Used this way, AI becomes part of the work, not a way of pretending the work has been done.

Then there is the harder truth.

In the workplace, developers will absolutely use AI. Of course they will. But professional developers are not valuable because they can generate code. They are valuable because they can judge code. They can read it, question it, test it, improve it, and understand whether it actually solves the problem in front of them.

I mean, how can you even know how to prompt effectively if you do not know what you are trying to ask for?

A whole world at your fingertips

"Wait! How can I possibly learn to code with AI" is an excuse I've heard way too often.

But one thing this world isn't short of are resources to learn that don't involve AI.

Books. Documentation. Courses. Tutorials. YouTube playlists. MDN. Codecademy. The Odin Project. Blog posts. GitHub repos. Stack Overflow threads. Oh how I can on!

A resource need not be just a course, a video or website, it can be a body.

Instead of using AI as your assistant every time you get stuck, why not pair up with a fellow learner? You sit together, talk through the problem, take turns typing, explain what you think is happening, and catch each other’s mistakes. When you explain your thinking to another person, you are forced to organise it. When they ask questions, you notice gaps. When they explain their thinking, you get to see another route through the same problem.

That is pair programming, and at its best, it gives you something AI cannot quite replicate: camaraderie. You sit together, talk through the problem, take turns typing, explain what you think is happening, and catch each other’s mistakes. There is a real difference between being stuck alone and being stuck with someone else.

The act of learning to code does not need to be a solitary endeavour. If you do not already know other learners, go looking for them. Local events on sites like Meetup can be useful for this, and so can online spaces like Reddit, Discord, forums, and course communities. I have attended plenty of tech meetups myself, and I was always impressed by keen beginners who were willing to put themselves out there, ask questions, and seek advice from people further along the road.

And if you can find a mentor, even better. A mentor does not need to be some grand, formal figure who guides your destiny from a leather chair. Sometimes it is just someone a few steps ahead of you who can look at your code, answer a question, recommend a better resource, or reassure you that the thing you are stuck on is genuinely hard.

Not all coding education is created equal

This democratisation of learning is undoubtedly a good thing, but it also brings a new set of problems.

Take that huge list of learning materials I wrote above.

Well, the breadth and depth of learning materials now available to budding coders is immense.

It is no wonder people end up in what is often called tutorial hell.

Variety can be useful, of course. But too much variety can become paralysing. This is similar to what psychologist Barry Schwartz called "The Paradox of Choice," where an abundance of options does not always make us feel freer. Sometimes it just makes us anxious.

Some learners do better with hands-on, project-based tutorials where they can build something and learn through trial and error. Others prefer a more structured, lecture-based course that explains the theory before asking them to apply it. Some people need visuals. Some need repetition. Some need a real-world problem before anything clicks. The complexity of the subject, the quality of the resource, and the learner's previous experience all play a part.

The trouble is that beginners are not always in a good position to judge the quality of what they are using.

That is where tutorial hell becomes especially cruel. A student struggles, and instead of thinking, "Maybe this resource is not explaining the concept well," they think, "Maybe I am just bad at this." So they drop the course, switch to another one, then another, then another, always hoping the next tutorial will finally make everything click.

Sometimes the problem is not the student. Sometimes the explanation is poor. Sometimes the course skips steps. Sometimes the tutor assumes knowledge the learner does not have. Sometimes the format is just wrong for that person.

So, if you want to navigate tutorial hell, you need to approach it with a discerning eye. Work out what actually helps you learn. Spend time finding the tutors, courses, playlists, books, or websites that fit the way you think. Treat that search as part of the learning process, not as a distraction from it.

But if there is one thing that can lift you out of tutorial hell faster than almost anything else, it is not just another course

It is a good teacher.

I have taught coding for years, so yes, I may be slightly biased. But I have seen the difference this makes. A good teacher does not just explain things. They diagnose. They spot the missing step. They notice the misconception hiding underneath the false confidence.

There is research to back this up too.

Benjamin Bloom was a famous educational psychologist, not a programmer, but he carried out an experiment that caused a huge stir in education. I am not sure how much anyone outside education cared, but within that world, it was a big deal. It became known as the Two Sigma problem.

In the 1980s, Bloom and his team studied students in Chicago public schools. One group of students learned through conventional teaching methods: lectures, tests, group work, and the usual classroom setup. Another group learned the same material, but with one-on-one tutoring. These students worked through problems with immediate feedback and only moved on once they had demonstrated mastery of the concept.

Bloom found that the tutored students vastly outperformed the students in the conventional classroom group. The improvement was around two standard deviations, hence the name Two Sigma. In practical terms, it was like moving an average student from the 50th percentile to around the 98th percentile.

That is a staggering result.

It is almost the complete opposite of the old "Camel Has Two Humps" idea, which suggested that some people were naturally suited to programming and others were not. Bloom's finding points in a very different direction. It suggests that, with the right support, feedback, and step-by-step mastery, average learners can perform at an exceptional level.

The problem, of course, is scale. That is why Bloom called it a problem rather than a simple solution. We know tutoring can work incredibly well, and especially if it's personalised, it's just not something everyone may have access to.

But in coding education, we see versions of this all the time.

Successful bootcamps or college curriculums often work because students are not left alone with a pile of videos and excise. They have live lectures, guided exercises, and tailored feedback loops. Even imposed deadlines can make all the difference.

And this matters even more once learners move beyond the beginner stage.

From tutorial hell to the tutorial plateau

I recently read a point from Erik Trautman, founder of The Odin Project, that put this well. In his article "Why Learning to Code is So Damn Hard," he describes how beginners start with a high density of resources, but once they move beyond the hand-holding stage, useful guidance becomes harder to find. He calls this phase the "Desert of Despair."

Anyone who has made the jump from beginner to intermediate knows this. At the start, everyone wants to teach you variables, loops, functions, and how to make a to-do list. But later, when you are trying to structure a real project, debug a difficult issue, or make the call on an architectural decision, the beginner-friendly resources suddenly thin out.

It is the stage where you know enough to know that you do not know enough. The tutorials are too simple, but the professional documentation feels too dense. You are no longer asking, "What is a variable?" You are asking, "Why is my authentication flow broken in production?" And that is a much harder question to Google when you barely know which words to use.

Eventually, if you stick with it, the resources return. You become comfortable reading documentation, searching technical blogs, watching deeper screencasts, and asking better questions. But that middle stage is brutal because part of the challenge is not just finding the answer. It is learning what the question even is.

That is why good teachers, mentors, and learning communities can make learning to code easier than otherwise. They help you bridge the gap between beginner material and independent problem solving.

Increased abstraction

If you are still with me, then bravo for making it this far. If you will allow me, I want to make one final point that I do not think gets made often enough.

If anyone told you that AI was the sole game changer, they're lying. Or just haven't been in this game long enough.

One interesting reason that has helped coding become more approachable is the evolution of programming languages towards increased abstraction.

In programming, abstraction is the process of simplifying complex systems, reducing information and detail to focus on higher-level concepts. The progression from low-level languages such as Assembly, which are closer to machine language, to high-level languages like Python and JavaScript, which resemble natural language more closely, embodies this notion of increased abstraction.

This trend towards abstraction has significantly impacted the learning experience for novice programmers. High-level languages abstract away complex, low-level tasks like memory management, which could be daunting for beginners.

This is not a new concern either. Kelleher and Pausch's 2005 survey traces a long history of programming languages and environments designed specifically to lower the barriers for novice programmers. So while AI may feel like the most dramatic recent change, it sits within a much longer story: programming has been getting more accessible for decades, partly because the tools we use to write code have changed.

So which is it, hard or easy?

Well, that depends on what we mean.

I have tried to be honest throughout this piece. Learning to code may not be as difficult as it once was, for many of the reasons we have looked at. The tools are better. The languages are more approachable. The resources are everywhere. AI can help. Communities exist. There are more routes in than ever before.

But you may have noticed that almost every advantage comes with a downside.

More resources can mean tutorial hell. More accessible tools can hide complexity until later. AI can support learning, but it can also replace the struggle that learning depends on. High-level languages can make the start gentler, but they do not remove the need to think clearly, debug patiently, and build a proper mental model of what is happening.

So yes, learning to code is hard.

But it is hard in the way many worthwhile things are hard.

 It is not hard because only a special kind of person can do it. 

It is hard because it asks you to think differently, tolerate confusion, make mistakes repeatedly, and persevere.

Joe Di Trolio sat in a library studying

References

Du Boulay, B. (1986). Some difficulties of learning to program. Journal of Educational Computing Research, 2(1), 57–73.

Sorby, S. A. (2009). Educational research in developing 3-D spatial skills for engineering students. International Journal of Science Education, 31(3), 459–480.

Caughman, A. M., & Weigel, E. G. (2022). Biology students’ math and computer science task values are closely linked. CBE Life Sciences Education, 21(3), Article ar43.

Becker, B. A., Denny, P., Finnie-Ansley, J., Luxton-Reilly, A., Prather, J., & Santos, E. A. (2023). Programming is hard, or at least it used to be: Educational opportunities and challenges of AI code generation. In Proceedings of the 54th ACM Technical Symposium on Computer Science Education V. 1 (pp. 500–506). Association for Computing Machinery.

Schwartz, B. (2016). The paradox of choice: Why more is less. Ecco.

Kelleher, C., & Pausch, R. (2005). Lowering the barriers to programming: A taxonomy of programming environments and languages for novice programmers. ACM Computing Surveys, 37(2), 83–137.