Amy M Haddad

Deliberate Practice for Programmers

By: Amy M Haddad


You’ve probably heard of deliberate practice: an intentional and informed type of practice that’s used to enhance performance.(1) It means entering your practice with purpose, rather than mindlessly going through the motions. Setting specific goals, receiving feedback, and getting outside of your comfort zone are some of the core parts of deliberate practice.

The popularity around deliberate practice is rightly earned: research across a variety of fields has shown its effectiveness.(1)

But something is missing from the deliberate practice conversation: how can you apply deliberate practice to programming?

I answer this question in this blog post. I offer three ways you can apply core tenets of deliberate practice to programming. That way, you can gauge your progress and get the most from your programming hours.

Practice vs Deliberate Practice

Not all practice is equal.

When most people think of “practice,” they think of mindless repetitions. A basketball player shoots jump shot after jump shot. A pianist plays “x” song again and again. Eventually they'll get “good enough” and do not have to think about it.(1)

But this type of practice comes at a cost: they’ll eventually hit a plateau and stop getting better.(1) That is because repetition alone does not result in expertise.

Deliberate practice is purposeful, and it requires your full attention. Instead of zoning out, you’re fully focused on a specific goal, which is characteristic of deliberate practice. Receiving feedback and getting outside of your comfort zone are others.

This example drives home the point.

Programmer A:

  • Sets out to program today
  • Selects a problem that’s easy to complete
  • Periodically pauses to check phone and respond to texts

Programmer B:

  • Sets out to complete “hailstone” problem recursively (recursion is hard for Programmer B)
  • Will program for one hour
  • Makes notes of places to refactor while solving the problem
  • Once the problem is complete, Programmer B studies the code of others who’ve solved the same problem; makes notes about what was learned; compares the solutions and identifies what could’ve gone better

Who do you think will be better after a month of practice?

Deliberate practice isn’t about practicing harder by clocking a certain number of reps. Rather, it’s about practicing smarter. Getting good at anything requires more than just reps. It’s also how you go about it: the quality of your practice matters.

Below are three ways you can incorporate deliberate practice into your programming routine.

1. Set an Objective.

Have an objective each time you program. Examples include:

  • Find bug in ‘x’ program
  • Refactor ‘y’ class

An objective is specific: it’s a particular outcome you want. The best way to identify your programming objective is to work backwards. Say you’re going to program for an hour. Ask yourself: “What’s the one thing I want to get done during that hour?” The answer is your programming objective.

I find it helpful to take it a step further to define the small steps to take in order to hit the objective. For example, say your objective is to add CSS to the index page. Now think about the steps you’ll need to take or the resources you’ll need to make that objective a reality.

Setting an objective on the outset is critical. First, you’ll program with purpose because you’ve got a small, but manageable task at hand. As a result, you’ll use your time and mental energy more efficiently and effectively.

A second reason why an objective is useful is for the immediate feedback it provides, which can help you gauge your programming progress. When your programming time ends, look back at your objective, and think about the answers to these questions:

  • Did you hit your objective?
  • How far did you get?
  • Where do you need to pick up next time?

The answers to these questions will help inform your next programming practice session.

2. Get outside of your comfort zone.

Instead of opting for the problem that’s easy for you to solve, opt for the one that’ll challenge you a bit.

For example, say you’ve solved a problem iteratively. Now solve it recursively, if recursion is something you find challenging. The idea is to get outside of your comfort zone. Because each time you do, you redefine what’s possible.

I distinctly remember the first time I ran eight miles. It was a very cold February day, and I was filled with fear because I’d never run that far. But I did it, and as a result I reset the bar of my limits. That gave me confidence to hit my next milestone: 13 miles. Then 15 miles. Then 18 miles, and so on. I gradually increased my mileage, each time pushing myself just a little more outside of my comfort zone.

And that’s the point. Getting outside of your comfort zone doesn’t mean jumping into the deep-end if you can’t swim. It doesn’t mean moving from the “easy” problems on LeetCode to the “hard” ones in a day.

Rather it means setting an objective that’ll challenge you enough. Say you’ve written a React project using functions. Redo the project using classes, if classes are hard or new for you.

Yes, getting outside of your comfort zone is hard. You probably haven’t done what you’re setting out to do or can’t do it repeatedly with perfection. However, it’s definitely within your grasp—if you bring your “A” game.

It’s also uncomfortable—at first. But eventually the light will go on in your mind. You make the connections. You spot the patterns. You’ve re-defined what’s possible.

3. Find a coach, even if you have to improvise.

It’s no surprise that a personal teacher or coach offers many benefits. They can provide feedback and practices you can work on.(1) They can also tell you what areas to focus on.

But what if you don’t have a personal programming teacher or coach?

The solution is to find an expert, or someone who you think is a great programmer. Fortunately in our field, there’s a large supply. Let them be your coach or teacher—they don’t even have to know about it.

Study Expert's Habits

That’s because many programmer’s share their ideas through books, articles, and blog posts. Of course, GitHub is also a useful source of information. Use the information that’s publicly available to study great programmers: their learning habits, programming practices, and learning paths.

If you have a particular programmer in mind, then reach out to them. Ask about what topics they learned and when. Find out about learning strategies they used. Or simply ask what they’d do differently if they had to start all over again.

Experts can be useful to get answers to some big picture questions you have. Use these answers to inform your own learning journey.

Study Expert's Code

You can also use great programmers as a teacher by studying their code. After you solve a problem, study the solutions of others who’ve solved the same problem. LeetCode and Exercism both offer community solutions to study and learn from. By studying the code of great programmers, you can learn the traits of well-written programs and pick up on new techniques and methods.

Reading code is a topic I’ve written about before. But it’s worth yet another mention here because it’s a great way to get the most from your improvised teacher: the code of a great programmer.

The idea is to solve a problem. Then, find a programmer who’s solved the same problem and study their solution: summarize each line of code by writing a comment in your editor.

Let a few days pass, and re-solve the problem. Use the comments you typed out as hints to guide you along the way. Finally, compare your new solution to the one you studied, and make any necessary changes.

This is a learning technique that I borrowed from Benjamin Franklin, who used a similar approach to get better at writing. I’ve modified and customized for programming. This technique touches on several key parts of deliberate practice: using a teacher, getting outside of your comfort zone, and getting feedback.

As a result, you’ll get better at reading code. You’ll also pick up ideas on good design, add new tools to your programming toolbox, and sharpen your programming skills.

Learn to Self-Assess

But there’s something more at work here: you’ll learn to self-assess. It’s easy for someone else to point out your mistakes and areas of improvement. But, without a teacher, we need to learn how to self-assess. On the road to getting better, you’ve got to learn how to spot mistakes and fix them.

That’s why the last step in the reading code practice mentioned above matters. Once you’ve re-solved the problem, compare your new solution to the one that you studied. Spot your mistakes, understand why you made them, and fix them.

Another way to get practice with self-assessing your work is to be your own teacher. After you complete a problem, walk through it and verbalize the solution out loud. Explain what you did and why. This is a great way to spot areas of improvement and check your understanding. If you can't clearly explain a line of code, that may be a sign of a trouble spot to focus on.

Make your Programming Hours Count

“The very great achievers, a Napoleon, a Leonardo da Vinci, a Mozart, have always managed themselves,” recognizes Peter Drucker. To Drucker’s point, it’s up to us to take ownership of building our programming skills. That is, we must manage ourselves.

In this context it means getting the most from our time spent programming, which boils down to a single phrase: deliberate practice. “Anyone can improve,” writes psychologist Anders Ericsson, “but it requires the right approach.”(1) So if you’re going to spend the time practicing, make it deliberate.


(1) Ericsson, Anders, and Robert Pool. Peak. New York, New York, Houghton Mifflin Harcourt Publishing Company, 2016.

← back to all posts