I learned programming through a relatively unorthodox method. I wanted to make a video game for my senior design project in high school, and I found myself on the Unity3D learn page. It’s basically a framework for creating 3D video games and involves some scripting in C#. It provides a game engine and an interface for manipulating game objects and assets, so you can intuitively put everything together. Unity is very well documented and provides a healthy amount of resources for learning how to develop with the platform.

This was not an easy way to learn how to write code. I did not know the first thing about a program, and the tutorials go pretty fast without very much in-depth explanation of the process. I could follow along easily enough, but when it came time to write code of my own, it was hours of frustration. Every time I tried something, it didn’t work. I was unable to efficiently identify the cause of any problem, and I would take an entire day or even a week to scour the internet for a kernel of understanding.

Despite the frustration, it turns out that this was actually the best way to learn how to write code. The unwavering sense that I was totally lost motivated my investigative problem-solving and prepared me for the daily struggle that comes with programming. The key characteristic of this experience was this: I had a clear directive. I already knew exactly what the video game was supposed to look like because it was an adaptation of a board game I’d created for a different school assignment. The challenge was translating it from physical game pieces to lines of code.

Programming is usually taught by starting with the simplest idea… It makes sense to approach it that way, but it is incredibly ineffective.

When I was working on the game, I knew what I was trying to do. I knew that, for example, the game needed to have cards. Each card behaved a certain way and was associated with certain values. I just had to figure out how to represent these behaviors and states in C#. This is exactly where the classical method of teaching programming goes wrong.

Programming is usually taught by starting with the simplest idea, variables, and working toward more complex ideas, like methods and objects. It makes sense to approach it that way, but it is incredibly ineffective. (Note that although I’m primarily talking about object-oriented programming, this applies to other modes of programming as well.)

As a teaching assistant for the introductory level computer science course at my university, I have worked with dozens of students who are approaching programming, specifically Java, for the first time. The course is structured like so:

  1. Variables and types
  2. If/else statements
  3. Loops
  4. Arrays
  5. Methods
  6. Objects and classes

This structure is bottom-up. Students start with something simple and work up to something more complex and abstract. People in the course right now are on step six — learning what a class is and what an object is and how to write classes and constructors, instantiate objects, and use these things to do something useful. As you might imagine, this point in the semester represents a major shift in the way that a student understands programming, and the transition is very challenging. If everything goes right, the struggle leads to a more wholesome understanding of how Java works. But it is an unnecessary threat to the student’s grasp and enjoyment of programming.

Psychology teaches us that we learn best when we are able to connect the ideas we are learning to something we are already familiar with.

That’s because the method is completely backward. Object orientation is the programming paradigm that students are supposed to carry forward, but it is one of the last ideas to which they are exposed. Variables, methods, loops, and if/else statements are nothing more than the tools that we use as programmers to define a class, but we often teach how to use these tools without first explaining why they exist.

Instead, programming should be taught top-down, like so:

  1. What is an object?
  2. What is state? What is behavior?
  3. How do we represent the state and behavior of an object?

There are two reasons this structure is superior. First of all, it puts the student in the object-oriented mindset from the start. This allows the student to tie every new thing they learn back to the idea of an object instead of being forced to cram a bunch of random things they have learned into an object. Psychology teaches us that we learn best when we are able to connect the ideas we are learning to something we are already familiar with. It’s difficult for a student to connect the idea of a variable to something already familiar. The idea of an object, on the other hand, fits perfectly into a student’s understanding of the world. We should take advantage of this from the beginning. The very start of any object-oriented programming course should pose this question: How can we use a computer to represent information that exists in the real world?

The unattractive aspect of a top-down structure is that it does not allow students to begin programming right away. A student will not be able to sit down and write a class just because they understand what it is supposed to do. The student must instead begin by learning the abstract concepts that guide their development as programmers without yet programming. Still, this method of instruction is superior to the traditional method. It gives students the clear directive that allows them to have a higher-level understanding of programming and be more purposeful with their work.

More concretely, this method addresses one of the greatest challenges associated with learning programming. When a student is just getting started with Java, they might be shown something like this:

public class HelloWorld {
    public static void main(String[] args) {
        String message = "Hello world!";
        System.out.println(message);
}
}

If you have any experience with Java, this is easy enough to understand. But if you’ve never seen a piece of code before, it may as well be Mandarin. Nonetheless, the student is taught that message is a variable of type string that holds “Hello world!” and System.out.println(message) prints the value of the variable to the console. The student is told, “Don’t worry about the ‘public class HelloWorld’ or ‘public static void main’ because you will learn more about them later.” They’re expected to take the instructor’s word for it, and continue to use these statements without understanding what they do or why they are necessary. But, hey, they know what a variable is.

Later in the semester, students are required to loop through each character in a string and check if it is uppercase. They must produce something that looks like this:

public class HelloWorld {
    public static void main(String[] args) {
        String myString = "Java Programming Is Fun!";
for (int i = 0; i < myString.length(); i++) {
            if (Character.isUpperCase(myString.charAt(i)))
                 System.out.println(
                 "Uppercase letter at index: " + i;
}
}

For this assignment, the student must use a class definition, a main() method definition, a string object, the length() method, the character wrapper class, the isUpperCase() method, the charAt() method, and the System.out.println() method without having any idea what a class or method is or why they are important. They are once again expected to take the instructor’s word for it — “charAt() gives you the character at the specified index, but don’t worry too much about how or why” because the point of the exercise is to practice loops.

You could certainly argue that this is simply a terrible assignment, and I would agree with you. The point remains, however, that it is very difficult to do anything in Java without using objects and methods. It’s quite confusing and feels pointless if you don’t have any idea what an object is or what a method is. Why doesn’t the course instead start with these ideas? The bread and butter of object-oriented programming should be introduced at the beginning of an object-oriented programming course.