Learning by grading

posted: May 15, 2017

tl;dr: You can learn a lot by grading dozens of answers to the same programming problem...

When I was an undergraduate at Cornell I had a better on-campus job than other friends of mine who worked in the dining halls: I was a grader (and also a tutor) for the Computer Science department, chaired by Prof. David Gries at the time (see Elegant simplicity in software). The CS department tapped me and a few other students who did well in the sophomore and junior-level classes and paid us to grade student assignments for the entry-level classes. I don't recall the English department doing this with undergrads, but grading computer programs written by beginners is a bit more straightforward than grading college-level essays.

At the time I thought it was a pretty sweet way to make some extra money, but what I’ve realized over time is how much that job taught me. Even today, more than thirty years later, I still feel I am performing that job to some degree as I read and review the code of the other developers on my team as well as open source code.

Some of the important lessons I learned in that job are:

There are many, many, many ways to solve the same problem. When faced with a programming challenge, you might consider a few ways of solving it before choosing the one that you think is best and writing the code. However, give that same problem to several hundred students, especially in an entry-level class, and you will see a stunning variety of different solutions. In addition to the very few that come close to matching the professor’s “recommended solution”, you will see programs that are three or more times the size; programs with huge nested if-then-else structures or switch statements; complex conditional iterations instead of recursion; data structures, objects, and classes galore; self-modifying code; and all sorts of other esoteric solutions limited only by the possibilities of the language being used (or, more accurately, abused). Many of these solutions will work under certain conditions, although often they will have boundary case problems or memory size or performance problems. The big lesson here, which carries over to the software profession, is that different people come up with different answers to the same problem, more often than not. This is something to be accepted, as long as the code works.

That’s why I take this line in the Zen of Python with a large grain of salt: “There should be one-- and preferably only one --obvious way to do it.” That’s nice, but the reality is that in Python or any other language there are a large number of ways to do it, a few of which are obvious and many of which are not.

Code should be written for readability. Of course a grader who has to grade fifty assignments in an evening is going to say this; no grader wants to figure out the potential pitfalls in code that is barely understandable, fifty times over. The same holds true in industry. The best code is the simplest code that gets the job done and is most easily understood by other humans. Computers can understand any source code that can be compiled into machine instructions; what’s more important is for that source code to be understood by the other humans who will be using, testing, and maintaining it.

Elegant code is a joy, like fine poetry. Every once in a while you run across some code that is a simple yet complete solution to the problem, with straightforward logic and data structures, perfectly chosen (descriptive yet concise) names, and just the right amount of comments to explain what isn’t obvious in the code itself. Code like this is a thing of beauty to the trained, appreciative eye. Very little code falls into this category.