The argument in brief
The question
What separates a good programmer from a mediocre one, if it isn't the language or framework they learned?
The claim
What makes a good programmer is less the latest language or framework than five skills courses rarely teach: thinking in abstractions, seeing the wider system in your mind's eye, reasoning about data structures, recalling how to build from a blank sheet, and the curiosity to tinker. Wanting it, and the time that wanting buys, is what develops them fastest. Confidence: A personal view from my own career as a programmer and from talking to people who want to start. No studies of programmers are cited.
The evidence
  • My own experience programming since I was 11, including patents filed through my work at IBM and Ericsson, building the Mattress Online website from scratch and building Flowtelic.
  • Conversations with people from other careers who ask me about becoming a programmer.
  • Worked examples from e-commerce, APIs and text editors that illustrate each skill. They illustrate; they don't test.
  • One replication of the deliberate-practice research, which found practice matters but explains less of skill than the popular 10,000-hour idea suggests.
The best counter
Some of these skills may be taught well in good courses and simply learned late, and success may depend as much on aptitude, opportunity or a good team as on obsession. Hours alone may not be what produces mastery.
What would change my mind
Evidence that programmers who are not especially curious or obsessed become just as skilled in the same time, or that formal training reliably develops these five skills.

The question: What separates a good programmer from a mediocre one, if it isn’t the language or framework they learned?Often someone will come to me and inquire about following the path to become a programmer. These people can come from a range of backgrounds, such as data analysts, pilots and robotics automation. I find it hard to provide the right advice because what is right for me might not be right for them.

What makes me suitable to share my insights into what makes a great programmer? I’ve been programming for a long time. I started when I was 11 years old, and over the years I have filed patents through my employment at IBM and Ericsson, as well as programmed the website for Mattress Online completely from scratch. I’m even building Flowtelic, my own note-taking app, to help inspire a generation of thinkers and doers.

Limits: This is one programmer’s path. I haven’t compared it with how other good programmers learned, so the skills below are my reflection, not a survey.So with this insight, I’ve reflected on what makes the difference between where I am in my programming journey and those who are just starting out. Let’s explore what is often missing from most education around programming, but I feel is more important than learning the latest language or framework.

Wanting to be a programmer

To become a programmer, you need to be:

  • Curious: have an intrinsic desire to make it work
  • Focused: know exactly what you are trying to achieve
  • Determined: it needs to take priority over other things
  • Slightly obsessed: think about it when you’re not at the computer

Most people’s motivation usually comes from:

  • The idea of remote working
  • Job security
  • Money

But when I speak to them, what is lacking is an innate excitement about being a programmer. As in, sitting for hours at a time and just wanting to create something.

So while I can recommend a pathway, give insights into what goes on in each area, and explain what the jobs look like, I can’t make them want it. And I mean really WANT it. That can only come from them.

But I’ve been reflecting on this. What is different between them and me? What is missing from those who are starting out programming and the struggles they experience? What makes a good programmer different from a mediocre one? Let’s explore.

1. The ability to abstract

Claim, confidence:a strong personal view from my own work; not tested: Thinking in abstractions is the number one skill when it comes to programming. The code represents some logic that in turn represents the real world. For example, in e-commerce, the customer “object” represents a real person who is buying a product. That person may buy many products, one product, or refund a product. All this is abstracted through a “customer object”.

The same is true for conceptual logic. For example, if I’m building a text editor, I have abstracted the concepts of blocks (paragraphs, titles, lists and so on), selection (where the cursor is), and the render (how it’s displayed on screen). Knowing what is abstracted and where, and what their role is in the system, is vital. For example, is a cursor position the same as a selection? What if it’s a multi-user edit and there are multiple cursors?

2. Seeing what’s not in the code

Programming software applications can become very complicated. When you look at a piece of code, it’s performing a set of responsibilities in a larger system. How do they relate to the other parts of the system that aren’t on the screen?

This is where your ability to see the “system” in your mind’s eye, and have an awareness of what it might do as a result of you changing the code in front of you, is vital.

For example, you’re working on an API response that gets the orders for a given customer. You find that it’s running out of memory because one customer has thousands of orders. So you want to introduce pagination (where only a part of the list is sent at a time). How does this impact the code that depends on it? What client programs expect the full list? Will it be backward compatible until the front end is updated with the “Load more” button? What if a customer wants to find their older orders and can no longer search their web page?

Let’s try an example. Close your eyes and imagine a car. Conceptually, in your mind’s eye, you know where the engine or motor is, where the driver’s seat and steering wheel are, where the passengers go, where the doors are, and where the wheels are. You also know that the function of the steering wheel is related to the wheels, and the pedal to the engine or motor. But the doors aren’t critical to either of those.

You have a concept map in your mind of how things relate together. Because you’ve seen and experienced a car, it’s easier to visualise.

An assumption: I’m assuming this mental map is a skill that can be built through exposure and practice, the way familiarity with cars builds the car map, rather than a fixed trait some people have and others don’t.But in the mind of a programmer, you can do the same with abstract components. You can see the server, the API layer, the authentication layer, the middleware, the database connector and so on. These are all components in a larger system that have a relationship with the other components.

When debugging a program, this concept map that you have will help you quickly identify where the impact of the bug is, and where the possible causes might be.

3. Data structures are the foundation

Most applications need to store some type of state. This might be in the running application (such as where you’ve filled in your email on a form) or could be a database (such as saving customer details).

How you reason about this state is absolutely vital. Get it wrong and you find that you can’t implement the code you need because something is missing. Get it right and everything seems to fall into place.

Being able to understand how that state will be used is a crucial skill. For example, if I’m recording purchases by a customer in a database, I may want to store their details such as name, email and address. Then I might want to record the list of products they have ordered in a “purchase” table.

Conventional learning will teach you how to relate the purchases with the products so you can easily allow many customers to buy the same product. All is good.

Then you realise you need to increase the price of the product. That’s when it dawns on you. Everyone who purchased previously will now have their purchases look like they paid the new price. The data structure was insufficient to model the real world.

So having an awareness of the implications of the data structure is vital. This also means you need to have a strong awareness and understanding of what goes on commercially in running a business. You need to know that prices might change, customers might cancel orders, discounts might get applied, or partial refunds might get issued. How you model this in your data structures can have a huge impact on being able to maintain the code over time.

4. Recalling how to do things

I like to call this the “blank sheet of paper” problem. Often a new programmer will be learning from other code and can easily reason about what it’s doing and how it works. Life is great.

Then they’re faced with building their own project, from scratch. Where do they start?

A competing explanation: Some courses do have students build whole projects from nothing. The gap may be less that it isn’t taught and more that it takes many repetitions before it sticks.Knowing how to create something from scratch starts by understanding the building blocks that need to be in place. You may have a database, server API, client API, front-end UI, and the logic that renders it. These are all building blocks that are used to assemble an application, each with their own set of responsibilities. This can be overwhelming for new developers, as they’re often only introduced to each block and haven’t spent enough time assembling them, swapping them for a different technology, or creating their own.

5. The obsession to tinker and create

The final critical skill that will determine if you’ve become a great programmer is your curiosity to tinker, extrapolate and create.

Going back to the text editor, let’s say you want to create a new one, but you’re using an open-source editor library and following its documentation. You understand the concepts. What do you do after learning this? Do you move on to the next thing to learn?

No. A true programmer will take this editor and start to break it, rebuild it, adapt it, and try out new ideas. Start to explore doing things that the editor doesn’t necessarily do from its documentation.

For example, you might want a toolbar to appear only when you select text. Or you might want to be able to style the text from a predefined set of styles. Or you might want to allow the user to drag an image into the document. None of these may be examples in the documentation, so what do you do?

You try to reverse engineer how other plugins are done and extrapolate how it could be used for your own goals. You reach out on forums and scan GitHub issues to see how others approach solving the problem. Your curiosity pulls you forward, and along the way you start to become an expert in it.

What if you aren’t obsessed?

A competing explanation: Obsession may be a result of early success as much as a cause of it, and aptitude, opportunity or a good team may matter as much as drive. I’m describing a pattern I’ve seen, not separating these causes.If you just don’t have the innate drive to be curious and obsessed with programming, then you’re going to be on a slower path to success. Claim, confidence:a personal view from people I've talked to and mentored; not measured: Simply because you’ll try out fewer things and put in less time. Boredom will creep in and you’ll move on to other things. This is a common pattern I see. People like the idea of being a programmer, but their actions tell the truth.

That said, do not despair if this is you. I said it will be slower, but not impossible. Being obsessed means you’ll gain the skills more rapidly. Not being obsessed but still putting some time in will mean you’ll still gain skills, but it will take longer. Just be careful that you’re actually progressing with deliberate practice and not churning over the same beginner exercises. You need to stretch yourself.

Limits: The 10,000-hour idea, popularised by Malcolm Gladwell from Anders Ericsson’s research on deliberate practice, is a rule of thumb rather than a finding. A 2019 replication of Ericsson’s violinist study found practice mattered but explained about a quarter of the differences in skill, roughly half what the original reported.Over time, you’ll naturally gain these skills mentioned above. That will make it easier, and when things are easier, you’ll enjoy them more and do them with less friction. That’s when true mastery can settle in. You just need to stick with it long enough for that to happen. You need your 10,000 hours.Source: A replication with violinists in Royal Society Open Science. Accumulated practice explained about 26% of the variance in performance, against 48% in the original study. The paper notes that Gladwell popularised the 10,000-hour rule; it does not test the rule directly.The role of deliberate practice in expert performance: revisiting Ericsson, Krampe & Tesch-Römer (1993), Brooke N. Macnamara and Megha Maitra, 2019

What would change my mind?: Evidence that programmers who aren’t especially curious or obsessed become just as skilled in the same time, or that formal training reliably builds these five skills, would change my view.

I hope that you’ve enjoyed this article. I’d love to learn more about your experiences and find out how I can improve my teaching.

Sources

  1. The role of deliberate practice in expert performance: revisiting Ericsson, Krampe & Tesch-Römer (1993), Brooke N. Macnamara and Megha Maitra, 2019

Books behind this essay

Not sources for any claim here. These are books I have finished that shaped how I think about this question. Where I rely on evidence, it is cited in the text.

The whole shelf