The Golden Calf is not a great code reviewer.

So I’ve been teaching programming for a few years now, and doing so with a mixture of age groups and instructional practices that seems somewhat unique. I don’t know of a lot of middle school teachers, for example, who teach the Git workflow as a core competency. This isn’t to brag — I only mean that I have happened upon an approach that is both unique and effective. Maybe it’s because all my technology skills are self-taught; maybe it’s because I come from a background of teaching writing (and martial arts). Whatever it is, I’ve had some success teaching kids to write good code. For them, myself, and hopefully you, dear reader, I thought it might be useful to document the Big Ideas of the craft I try to teach.

Actually, before we jump into the Laws, the notion of teaching programming as a craft is itself important for us educators. How is teaching a craft different from any other form of teaching? Take writing. Ideally, we would teach the craft of composition — grammar, syntax, and style — in a course that is related to but separate from courses on literature. Constraints of time and tradition tend to prevent this approach, regardless of how correct it would be. And it is obviously correct, following the principle of doing one thing well rather than two things (at best) adequately. So too with programming. When first introducing the concept, the course should be rather pure in its content, focusing on code and the best practices of writing software with code. In a craft approach, both product and process matter, but our focus on process includes the shaping of good habits. Even when there are many “right” ways to solve a problem, there is often a best strategy for determining the appropriate solution.

You might argue that concepts of computer science are necessary for a full education in the craft. I agree, but for younger students especially, that is a heavy cart before a tiny horse. Getting students producing output as quickly as possible is the ticket to engagement and success in the elementary/middle school years. Maybe even later.

Programming-as-craft also lends itself to a curriculum that is appropriately paced for students. Imagine setting final expectations for the course at the beginning: “You will be able to make this,” then allowing students to progress and master as they are ready. The object is to reach the final exhibition of mastery by the end of the course. Everything else is paced as students require. Such an approach isn’t always feasible, but that is the craft approach taken to its logical conclusion. If possible, I strongly recommend structuring introductory — perhaps even intermediate — programming courses in this way.

Now, on to the Laws. We separate into two sections: Habits of Mind, and Habits of Code.

Habits of Mind

Practice (ABC — Always Be Coding)

I will take any opportunity to relate things back to martial arts.

I did not train at a monastery in Kunlun. I did not seek The Ancient One and practice arcane rituals to gain my skills. I do not claim full mastery of this discipline, but I do practice all the time. Like Hundred Eyes says in the clip above, that is Gong fu. That’s how we get to mastery.

Accept Temporary Failure

At the beginning, programming means a great deal of frustration. Most of our time is spent with our code not working. Over time, this will change as you internalize the basics. Your code doesn’t fail because you can’t code; your code fails because you are human. Failure is a step on the way to mastery. Be humble in the face of your temporary shortcomings.

Know the Problem

Code is a bridge between a problem and a solution. Like any good engineer, a programmer must understand the parameters of the problem before designing the solution. This might seem obvious, but the problems solved with code are often within complex systems that require careful study.

Put another way, it isn’t enough to understand the inputs/outputs of an implementation. The context is also crucial. A good test is if you can tell the story of the problem to someone unfamiliar with it. If you can you’re ready to attempt a solution.

Break Everything Down

Most big problems are just smaller problems stacked inside a trenchcoat. Learning to deconstruct a problem into smaller, manageable pieces is essential — not just for good program design, but for the confidence of the programmer.

Follow the Chain of Error

Before asking for help with nonfunctioning code, consult, in this order:

The error message: can you read it? Is there a line number? Your code. Is it correct? Did you check? Check again. Check again. Check again. The documentation. Can’t read it? Scroll up or click back to the index until you find a page you can understand. Continue until you reach the page you need. The error message again. Your code again. Me.

Notice that StackOverflow is not on this list. Masters get to take shortcuts. You do not.

Attempt to Generalize

Think you’ve got a specific problem licked? Cool. Is it like other problems in the same system? Is there a way to abstract your solution to handle all of those problems? If so, write that. Knowing how to generalize solutions will save time in the long run. Knowing when not to generalize will too.

Habits of Code

Don’t Repeat Yourself (DRY)

An application of Attempt to Generalize. Loops and recursion can be daunting to new programmers. Even variables can be, depending on the data type. DRY obliges us to write the minimum amount to express an instruction to the computer. Why is this good? It may have performance advantages, but most of the benefit is human. Not only will our code be easier to read, each repetition we avoid is one fewer chance for us to make a mistake.

Types

This one is an application of Know the Problem. A program is a manipulation of information. Understanding the forms of the information at every point of the process guides algorithm design and implementation. What’s coming in, what’s going out? What is the best way to represent the problem?

Functions

This one is an application of Break Everything Down. When you begin to code, often your scripts are written as simple sequences of instructions. Certain introductory materials, like Turtle or Code.org, even encourage this. But once you begin thinking of code as transformation of data; once you’re thinking about types, you’re ready to abstract your solution to functions. Writing functional code is a style and a philosophy — all programmers do to one degree or another. I advocate quickly moving to functions as the atoms of algorithm design for students. Not only will the code be easier to maintain, it’ll be easier to think about.

Comments

Comment where necessary. But wherever possible, write code that doesn’t require much additional explanation.

There are other recommendations I have for my students in the specifics of their craft, but these are, I think, the long and the short of the straight-up musts I expect all students to internalize by the end of their journey with me. Now that I have these written down, I may expound on these in detail in later posts. Feel free to use these, expand on them, modify them, etc. They are, like all my work, open source.