Become a Great Programmer Through Deliberate Practice: Goal-based Practice

The Goal-Based Programmer

In a past article I discussed how just plain practice is not enough for student programmers to become expert programmers or for expert programmers to continue to perform at an expert level. Gaining and maintaining expertise in programming, as in many other areas of life and work, requires deliberate practice that meets several criteria. My last article discussed how deliberate practice must take the programmer out of his or hers comfort zone in order to make the programmer better. In this article I’m going to talk about another facet of deliberate practice – it must be goal-oriented.

What is Goal-Based Practice?

As Anders Ericsson and Robert discuss in their book on deliberate practice, Peak: Secrets from the New Science of Expertise, people trying to become experts in their field work at practicing their craft toward some type of target performance. For example, for a musician, the goal may be a new piece of difficult music that has always been beyond their capabilities; for an athlete, it may be practice towards a new personal record or a medal in a competition. The point here is this – the effort of deliberate practice is aimed toward some specific goal and not just “toward some vague overall improvement.” (Ericsson and Pool, p. 98)

A musician trying to master a new piece of music will focus primarily on those parts of the piece that are the hardest to perform. They will work at these sections for long periods of time until they are able to perform the section with the same ability they perform already-learned pieces. An athlete, say a mile runner, will spend lots of time trying to build his or her speed by running short intervals many times a week. It is the development of speed that will help the runner win the mile event.

The point here is that, whatever the field, the person trying to achieve expert performance will concentrate their time and effort on the parts of the performance that are the hardest, and once they’ve mastered these hard parts, will combine them with the other sections they have already mastered into a complete, expert performance.

Goal-Based Programming Practice

How can we translate the way musicians and athletes perform deliberate practice towards a goal into something programmers can use to become better at their craft? We can break this down into two different areas – practice for the student programmer and practice for the working programmer.

Goals for the Student Programmer

It is easy to state the goals of the student programmer: learn and practice the various concepts and constructs that allow programmers to build and implement increasing complex programs in the programming language they are studying. We can break this down into three main areas (at least for non-functional languages such as C, C++, C#, Java, JavaScript, and Python): the imperative paradigm; the object-oriented paradigm; and data structures and algorithms.

Programmers first learning a language need to master the fundamentals of writing imperative programs. These fundamentals start at learning how to write simple programs that do arithmetic, using variables to store data. Next they move to decision making with if statements and Boolean logic. The next step is to learn how to perform repetition using while and for loops and the variations of these loop types. Most curricula introduce data structures (arrays and vectors) at this point, followed by functions. The sequence of these constructs moves the student programmer from writing simple, sequential programs to writing more complex programs where the control flow is manipulated using the newer constructs the student is learning. Some topics that are not part of control flow are introduced along the way, from scope to pointers, but this sequence provides the student programmer with the opportunity to practice writing more and more complex programs that improve their skill at programming by continually challenging the student in the difficulty of the material being learned.

The next step for the student programmer is to start to learn more about software design through their introduction to object-oriented programming (OOP). The student first learns how to perform encapsulation via the creation of classes, though some curricula, especially in C++, first introduce OOP via structures. Students learn how to design classes that more closely model the real world and learn how to manage complexity in their programs through the development of classes. The next step at this level is to learn how to leverage classes into hierarchies of objects using inheritance. Some curricula also introduce more formal definitions of composition at this point to make sure students don’t confuse modeling the has-a relationship using is-a concepts. The last step in OOP learning is usually learning how to use polymorphism to effectively utilize inheritance in the effective use of collections of inherited objects.

The last step in programming learning for most student programmers is the study of data structures and algorithms. Study and practice in data structures usually starts with arrays and vectors, moves to memory-managing structures such as dynamic arrays and linked lists, then on to stacks and queues. These are considered the lower level of data structure objects and once they are mastered, students move on to more advanced topics, including trees (b-trees, binary search trees, etc.), hash tables, heaps, and graphs, to mention most of the popular data structures studied. Usually at the same time, but sometimes in a succeeding course, algorithms are studied. Students first learn how to analyze algorithms for efficiency and then learn about the implementation of famous algorithms for sorting and searching data stored in various data structures.

There are other courses student programmers take that will challenge them to improve their skills as programmers – programming languages, compilers, and database courses. All these courses, as well as others, will help improve skill as long as the work is going above the skill level the student already has obtained.

The point of discussing this sequence of topics of study for the student programmer is to point out that in all cases, the material moves from the more basic to the more complex. Students need to master control flow constructs before they go too deeply into data structures and algorithms, and students should have a feel for the design, implementation, and use of functions before they study how to build objects that use functions (methods) in the implementation of their interfaces. If the student programmer continues to challenge themselves by continuing to move to more complex topics, their skills as programmer improve and they become more and more experts of their craft.

Goals for the Working Programmer

The working programmer faces a stiffer challenge when it comes to determining goals for their programming practice. First, there is a time challenge. The working programmer is already working a full day doing the various tasks programmers do, making it hard to find the time to improve their skills. Also, many of the programming tasks they perform day-to-day don’t really work to improve their skill since the level of coding they are doing is usually at the same level of what they are already do well. The challenge is to find time and find projects that push your skill level up. I won’t discuss finding time for deliberate practice in this post. That’s a whole topic. Instead, here are some ideas for programming projects that will challenge you and further develop your skills.

Learn a New Programming Language

The first idea is to learn a new programming language. If you work primarily in Java, learn Python. If you work primarily with JavaScript, learn C++. If you work primarily with object-oriented programming languages, learn a functional language such as Scheme or Haskell. Another option would be to learn one of the newer systems languages meant to replace C++ – Rust or Go. There are many, many programming languages you can learn. Pick one and spend a few months learning it.

How do you learn it? One way is to pick a project you’re currently doing at work and implement it on the side in the new language. If this isn’t possible, pick your own project and develop it with the new language. Having trouble deciding what project to work on? Develop a game. I like to learn a new programming language by developing a simple tic-tac-toe game in that language. Tic-tac-toe can be written using most of the features you need to learn about a new language – making decisions, performing repetition, modularizing the code with functions, and encapsulating the game in a class. I usually develop these games as console applications but if you want to get ambitious, you can also learn how to implement graphics in the language and build a graphical user interface for the game.

Build Something New in Your Current Language

If, on the other hand, you want to get better at the programming language you are currently working in, you can work on something new in that language. The key to this is that it needs to be something challenging. Is there a data structure you don’t use regularly in your work but might help out on some of your projects? Write a program that utilizes the data structure. Are you curious about how the hash table that underlies the data structure you’re currently using works? Design and implement your own hash table class. There are an unlimited number of projects you can work on to build your expertise in your current programming language. The project just needs to be something you are interested in and that will challenge you by extending your knowledge and skills beyond where they are right now.

The Key to Gaining Expertise is to Continually Have New, Challenging Goals

Once you’ve decided you have learned all you can learn, your skills start to stagnate and even decrease. This phenomenon has been observed in professionals in many fields, from artists to physicians. The key to gaining expertise in programming, and the key to retaining that expertise throughout your career, is to continually challenge yourself with new goals. It is not enough to just work at the level you are currently working at – your skills will atrophy. The old saying, “Grow or die,” can be replaced with this saying, “Grow your skills continually or those skills will die.”