I first learned to code when I was sixteen, back when the spectre of uncool nerdiness still hung over everything to do with computers and programming them. In our school's ancient computer lab we had a retired chemical engineer step us through the basics of writing programs in VB.Net (version 6, I believe), with the whole "building forms with drop-down components" style of developing UIs and then writing code behind them to bring them to life. The first project I built was a basic tide calculator, and I even wrote my own functions to approximate sines and cosines using a Taylor series expansion. We got taught the importance of comments and documentation from someone serious about engineering practice, and while I'm not sure I'd teach new programmers this way (certainly not using VB.Net), but all in all, I don't think this was the worst possible introduction to programming.
More recently, I've been working with a few newer engineers in a mentoring arrangement. This has been quite a lot of fun, and it's also given me a bunch of thoughts about how we teach coding in general. See, a lot of the students get their initial education from computer science courses, and while they do a good job of teaching people how to program in the bare sense of the term, they don't really have a good grasp of how to go from writing code to building something useful for them or other people. This leads to people being a bit demotivated and just flat not learning well, and also leaves them feeling not very confident in their ability to write code well.
This is bad for a few reasons: it means that we have to do a lot more work to get junior engineers up-to-speed and productive than we would otherwise. It means that a lot of people who could be decent engineers kinda just check out and write bad code, and that they find the whole thing joyless and painful. Even the good and motivated engineers find themselves doing a hell of a lot more work simply to find the people who can write good code, and then even more work to learn from them informally. It also means, in the end, that a lot of people who'd be brilliant software engineers just bounce off the field completely, and that a lot of people who find no joy in anything and just want a big salary wind up in the field, never realising that they have no liking or aptitude for it.
Given this, I think that we're more than a little muddled in how we teach people to code, and that we could do it an awful lot better with a little thought.
What we teach when we teach programming
The reason we get muddled, I think, is that those of us who are practising engineers don't often quite get what we're teaching when we teach people how to write code. For most teachers, and a lot of people in the world in general, teaching people to code is basically teaching them they mystic runes that they need to know to make the computer obey them. While lots of people think this way, any serious engineer will quickly pick up that this is actually a really bad way of teaching: after all, 90% of software engineering has nothing to do with actually writing code. What we actually care about making stick are two things. The first is a kind of second sight, or a new way of seeing the world. The second is the ethics of care that comes with our profession.
One of the best things about learning new things, for me, is that moment where, after a few weeks or months of struggling with a problem, something clicks and you get to see a part of the world through entirely new eyes. I've had the experience in fields as far apart as quantum mechanics, Latin and the baking of bread, and it always feels good. What we try and teach people learning to write software, then, is the ability to see the computers that they interact with every day through an engineer's eyes.
Doing this takes a few skills. First off is developing what we might call "code literacy". Code literacy means being able to map symbols to the things that the symbols represent in the same way as you do in any language, being able to understand how those symbols relate to each other to convey meaning and being able to do this in a fluid, intuitive way. It's the ability to read a piece of code in the same way that you would an essay, understand what it's doing and the thrust of what it communicates, both to you and to the computer. Being fluent in code is really important for being a truly good engineer, and I think most of us practising engineers will happily support the idea that a lot of people working in software never develop it.
The second part of seeing the world through an engineer's eyes is teaching people how to analyse and break down a problem so that it can be solved with software. In the same way as writing about something means being able to break it down and understand it in a very particular way, solving a problem with code means being able to look at the problem, break it down into small chunks that you can solve with code and then put those chunks back together in a way that solves the problem. It's important to note that this doesn't really have much to do with code as such: it's much more about being humble, taking a step back and really understanding the problem you're trying to solve.
Finally, you have the ability to understand what a computer-type device might be doing day-to-day. For most people, what a computer's doing under the hood is a complete mystery, and there's no real understanding of what a computer usually does and how those things can break. Building an intuitive sense of what the machine might be doing in any situation is really important for being a good engineer, and it's a skill that we really need to focus. Taken together, these things make up what we might call the engineer's second sight, or the ability to see the world of software in the way that an engineer does. To get good software engineers, we need to teach this and do it effectively.
The other thing that we want to convey to teach people to be good at writing code is the ethics of care behind it. Obviously most people are broadly moral and ethical and care about good code, so this isn't exactly trying to teach people good morals like some kind of Sunday school thing. It's more about conveying what's important to focus on to get the results you want. Using Git is an excellent example of this: it's really important that we use it and use it well, but for new engineers it's quite hard to explain why they should care and why it's important for them to understand it in order to write good code. A large part of teaching people how to code, then, is figuring out ways to get people to understand what we do, why we do it and why it's important when we care about writing good code. This really only comes from repeated practice while working on something that you really care about.
Keeping this in mind, it's clear that a lot of the ways in which we teach people to write code really don't reinforce these values enough. Bootcamps and even some fairly serious software engineering courses at universities tend to go all in on the "teach the mystic incantations" style of teaching. A lot of courses never need you to actually deploy anything, the use and teaching of Git is patchy at best and people never really get the chance to build something that does something useful or that they actually care about: it's almost all toy problems or the kind of stuff that your worst idea of a Silicon Valley start up will put out. This tends to lead, as you might expect, to a lot of new engineers being confused, demotivated and struggling to write good code or work effectively in a software environment.
HTML as a teaching tool
With this in mind, I think that Python, Java and a lot of the other languages that we use as teaching tools are not very well suited to the task. The core of the issue with them is that, unless you already have a decent understanding of a quantitative field (maths, stats, the physical or social sciences, that kind of thing), it's very hard to make them do anything that a person new to programming who isn't already a maths nerd would find useful. You start with building a basic "hello world" program, move to variables, loops and conditionals, touch on modules and functions, and at the end of it, the best you can do is usually still just to process data and dump it to a file with no guarantee that anything about the file contents is interesting or useful. Sure, if you're a statistician you can have some fun with model-fitting, and if you're a mathematician or a physicist you can do some fun stuff with differential equations (which is how I approached it), but most people, and even most programmers, just don't do that. And let's face it, FizzBuzz is kinda boring.
The problem with this is that if what you're using to teach software is boring and useless to the person, they won't care about it. It doesn't matter to them, really, whether a program that they've written works or not. They're just mapping one set of symbols onto another set of symbols, with no connection to anything in the real world that might matter to them. If they learn the material at all, they're going to be sloppy about learning how to write code well. They might not bother to write tests, do version control in any serious way, think about how to deploy their code and ship it to someone or generally do all of the things that we think of when we think of what a good engineer does. If you get an engineer out at the end at all, they're going to start off confused, demotivated and doing sloppy work, and if they ever improve, it can take them years to do it.
The traditional solutions to this problem were devices like floor turtles. If you're not familiar with them, they're little robots that look a bit like this:

These take a few basic instructions in a language called logo (which is apparently a Lisp dialect): lower or raise a pen pointed at the ground, move forward or backwards and turn left or right. The idea is that by programming the turtle, new students of programming can think about a physical thing drawing actual lines on actual paper on the floor, which helps them connect the symbols that they put into the turtle to the behaviour of an actual machine. They're very cool, and I honestly have a massive soft spot for them.
The main issue with the floor turtle is that, while the images can be pretty cool, it's still not clear how this is actually useful to anyone: you might be able to make an analogy with a computer-navigated cutter or something similar, but those aren't things that most of us have on hand, and so we're stuck in the same place. While I'm not entirely familiar with Scratch, and I think it does better on some axes, the fact that it's very much aimed at children also makes it less than ideal if you're teaching adults or youth. Fortunately, there's one technology that does an awful lot of what we want, is used almost everywhere in our work and can do something that's useful to almost anyone, especially someone who wants to learn programming.
If you're teaching someone how to code these days, may I suggest starting with HTML?
HTML gives us a lot of what we want when we teach programming. The important thing is that the learner has to learn to write symbols that aren't the same as the output that they want to, but they can immediately see what the output is. You need almost nothing in the way of tools: a text editor and a browser will do just fine. That makes it a lot easier to learn that, for example, an <h1> tag will get you something different from an <h4> tag or a <p> tag, and that you have to get syntax right in order to get the result you want. It also gets you something that you want and care about: a website, that these days you can put on the internet really easily thanks to some really good services, that can be about literally anything you want and look however you want it to look. You aren't tied down by social media platforms and their formats and standards: you can just do what you like. For almost any professional, and especially a software professional, having your own website is really useful and makes you look that much more serious, and if you're an artist or someone who makes stuff, you can sell or promote your work on it. In short, there are a bunch of reasons for almost everyone to care about being able to build their own website and stake out their own little part of the internet.
Styling the website teaches its own useful set of skills. Attaching classes and ids to elements and attaching styles to them teaches the elements of how variables work and can be referenced. Importing stylesheets teaches the idea of an import or a module: the idea of linking code files from different places together. Certainly, none of this is exactly the same as what you do in a programming language more generally: web technologies are fuzzy and need to work in conditions where you'd want a regular programming language to fail. But if you've already learned and made those skills a part of yourself, it'll be much, much easier to learn how things work in a programming language proper.
Making the jump directly from HTML and CSS to programming is still going to be a bit tricky. Fortunately, learners don't have to do that, because we have a good intermediate step: static site generators with templating engines. Templates are useful for a few reasons: first of all, when you're mixing outside data with your HTML, you have to start thinking carefully about how you store and structure your data, and where you get it from. Data structures are a very big part of most practical software work, so exposing people to this early and in an easy-to-understand way is very useful (this also means that we get to show our new learners proper variables and how they work for the first time). Most templating languages also let us start talking about loops and conditionals in a way that's less abstract than what we usually give people and that you can see the results of very quickly: this lets people build an intuitive understanding of how these things work before you have to tackle it in something like C, which I think is a good thing.
Finally, a website is easy to deploy and it makes sense to deploy it. This is important because, as you might have guessed from the heading immediately below this:
You have to ship something from the start
Software engineering has to be one of the very few fields of work where a) it's possible to build something, deploy it and share it with the world from the very start and b) when teaching people how to do it, we don't expect them to do that. Think, for a moment, about someone learning to bake bread. They certainly wouldn't start with sourdough, and they'd probably start with a learning recipe like focaccia over anything else, but the expectation is there from the start that they'll make an edible loaf that they can serve to someone, even if it's only themselves or their immediate family. If someone tried to teach baking by having students bake ever-more-elaborate practice loaves using fake ingredients and then throw them out, you would probably be concerned.
The strategy is similar in fine arts, performance arts and music: from the very start, you exhibit your work, you perform, you show it to other people and get feedback. It'd be hard to even come up with the concept of fake practice art at all. Conversely, the fields where you have to rely on fake practice models are ones like civil engineering, where for obvious reasons you can't just send out a bunch of first-year engineers to build a bridge for obvious reasons. And even in those fields, we have to do eight hundred hours of work in an apprenticeship setting, working with older engineers on real projects. Software has to be one of the very few places where we think we can teach people to be good at it without doing real work.
What this means is that I think that when teaching people to code, we should be deploying something real to the real internet almost from the very start: as soon as we've managed to get people to the point where they have a website they can put on the internet, we should get them to put it up there.
There are a few reasons this is important: the core of it is that having people build a website from scratch and put it on the internet gives them a reason to care about the quality of their work from the very start. You want to make sure that your website is always exactly the way you want it to be and that changing it doesn't break it? You'd probably better learn how to use Git well. You want to make sure that your website doesn't get hacked? Then it's important that you think about security. Want to catch breaks ahead of time? Might be time to write some automated tests.
Deploying code also gives learners the chance to understand the whole of the software development life cycle and to take part in it. You need to understand how to make, how to approve and how to push changes to your website after the fact. You need to understand how to test the software that you've deployed, and (the amount that you learn of this depends on how exactly you're hosting your website) how the servers and the cloud infrastructure that supports your website actually works. Given how many developers there are out there who know almost nothing about Ops and who make life much harder for Ops people in the process, this can only be a good thing.
In the end, there's a lot that you can only learn about software engineering by doing it for real and with real stakes. It's hard, I think, to exactly say what you'll learn, because a lot of it depends on the real problems that'll crop up when you do the thing. But every good engineer has in their minds a whole stockpile of memories and lessons learned that they intuitively lean on, and this, as much as any formal skills, is the core of engineering expertise. If we want to have good software engineers, then, we should probably start building up that stockpile as soon as possible.
Meeting the moment
It's fair to say that the tech industry at the moment is not in a good place. Software engineers tend to be detached, demotivated and unwilling to care much about the work they're doing beyond their paycheck. Code quality is poor on the whole, made worse by the current spate of vibe coding and whatever other febrile ideas come out of Sam Altman's brain. Much of the software that we write is either useless or actively hurts people. And the talented, creative people that we most need in the industry are pushed to the margins of it.
This all begins with education: with the kinds of people we attract into the field and how we shape them when we teach them how to write code. Right now, with the way we teach, the people whom we encourage into the field are not the ones we need. We hide the expressive elements of the field and do our best not to show anyone the things in tech that give you the power to express yourself, to self-publish or to do your own thing without gatekeepers. We encourage people with a tolerance for boredom and substandard work, and we push creatives and people who just want to do cool things with tech to the edges of the field. And when, by some miracle, good engineers still wind up learning to code, we make it clear in half a hundred little ways that their care and their way of seeing are wrong and that they need to conform to the degraded, ignorant state of the field as it is.
If this is how we keep acculturating people to software, our field will die. We'll be laid to rest alongside multi-level-marketers and used car salesmen as a profession that only the morally bankrupt would ever consider taking on. And our software will reflect that. If we want to save our profession, we need to attract different people to the field, and we need to teach them differently. We need to show them what the things we work with can do, we need to show them how they can use our tools to make the world better, and we need to give them a reason to care about what we do.
And perhaps that could start with some personal websites.
Enjoyed this article? Please consider setting up a regular donation, or making a one-off one! These donations help me pay the bills and allow me to keep producing compelling independent writing that casts light on our industry and its problems.
Support independent writing →
Developing the skills and engineering mindset that I've described here is much easier to do with a coach or mentor, and this is very much a service that I provide. If you feel that you could benefit from developing a more resilient set of engineering skills and mindsets, or if you know someone in your life who's about to be thrown into what's a very tough engineering market, get in touch!

Comments
Nothing yet. Say the first thing.
Sign in to join the conversation.