I aimed to keep this piece short. However, in doing so, I didn’t hit important details in the Grand Challenges in Computer Science Education call. In particular,
| The submission should focus on a precise description of the problem, and of the perceived benefits that a solution would bring to the community. |
I didn’t go into great depth describing the problem, nor did I really address the benefits of solving this problem. My primary goal was to keep my expression of this challenge short, but in doing so I think I assumed too much on the part of my readers. I suspect I fell into a trap others will as well: I didn’t clearly differentiate between the challenge of teaching programming and the challenge of teaching computer science. This, however, may be forgivable.
I claimed we needed to carry out a hierarchical task analysis of introductory programming. Such an analysis would provide a road map through the concepts required to write programs at the novice level. To make this a bit more concrete, we might wonder what we would gain from a hierarchical task analysis of, say, assignment? From the hyperdictionary, assignment is
| Storing the value of an expression in a variable. This is commonly written in the form “v = e”. In Algol the assignment operator was “:=” (pronounced “becomes”) to avoid mathematicians qualms about writing statements like x = x+1. |
A hierarchical task analysis of assignment would give a conceptual road map that takes us from basic building blocks (things we assume all students know) through to the ability to write code like
x = 3
or
x = x + 1
Right from the start, I can say that variables are troublesome things; Jorma Sajaniemi has done some excellent work exploring variable roles in novice programs (PPIG 2002 paper, PDF). Sajaniemi identifies common usages of variables in novice (procedural) programs: temporaries, followers, one-way flags, gatherers… all very different ways to use variables in a program. They all involve assignment of the values of expressions to variables, and use the results of that assignment in very different ways.
So what does it take to understand assignment? We need to understand … a notion of containment? Side effects? State? Do we need to understand the underlying machine model? Is it more important to understand the uses to which assignment may be put? Where does it end? Where do we begin?
In Physics, I like to think I was taught a well-structured series of lies—fibs, maybe—where the more subtle truths were revealed to me as I progressed from Intro, to Waves, to Classical Mechanics, E & M, and then Quantum. At each stage, I learned more of the model, and I can see where abstractions and simplifications were made for pedagogical purposes.
So what series of abstractions is appropriate for programming instruction and, more broadly, computing? How should we structure programming instruction so that our students, when they get done, can clearly see why they learned what they did, when they did? Should we be looking to functional languages? Object-oriented languages? Should we be looking to event-based, massively parallel, or media-driven paradigms? There is lots of good work by lots of good people out there, and there may be more than one ordering that gets us to where we want our students to be. But from conversations with people in these communities, I know there are a lot of closed minds; too many people think they’re right and everyone else is wrong.
Even one clear, pedagogic ordering of concepts required for teaching any kind of introductory programming would provide an excellent starting point for analyzing other instructional approaches. It would eliminate the need to argue about functional-first or objects-first, and instead let us wonder how these different paradigms relate or differ from each-other in meaningful ways. I’m sure the holy war of first language choice would persist (there’s a lot of money tied up in that holy war), but the side-effects of finding a starting place would be amazing. We could lay the foundations for computing at a much earlier age, much like we lay the foundations for trigonometry and the algebraic manipulation of mathematical structures long before we actually teach children trig or algebra. Pedagogical programming environments for pre-programmers could be built—environments that could would introduce core concepts necessary for learning to program, design DFAs, prove language equivalences, write operating systems, structure queries, and all the other things we do as computer scientists. We could better structure instruction for physicists, chemists, biologists, and other scientists who are eager to learn to use the computer to further their own science, while maintaining some semblance of good instructional practice.