The Philosophy of Picturing Programs

© Stephen Bloch 2009

Philosophical musings for instructors

My name is Stephen Bloch. I'm a computer science and math professor at Adelphi University, near New York City, and I've taught a variety of computer science courses for about twenty years.

Some computer science courses are about one or more specific programming languages. I teach such courses frequently, and I start the semester with a list of commonly-used features of that language that I think students should know; the more of these language features we cover, and the more language features my students can use fluently by the end of the semester, the more successful the course has been.

A beginning programming course is different. I start the semester with a list of fundamental concepts, techniques, and habits of programming; the better my students have mastered these by the end of the semester, the more successful the course has been. In this setting, I want to cover as few language features as possible -- only the ones that are necessary in order to teach the fundamental concepts, and those only when necessary in order to teach the fundamental concepts. The language should be the servant, not the master, of course content.

Any programming language is a necessary evil: necessary in order to write real programs that really run on real computers, but evil insofar as it distracts students from the important stuff: the process of analyzing a problem and finding a good solution to it.

If you're teaching the former kind of course, you teach the language that's specified by the course goals. If you're teaching the latter kind, you should choose a language that gets out of the way and lets you teach programming: a language in which your students can write powerful, sophisticated programs with very few language constructs, and in which you can introduce those constructs one at a time as motivated by the fundamentals. Languages like C++ or Java may be very good for industrial programming, yet don't meet these criteria and therefore aren't suitable for beginning programming.

Where this book came from

In 1999, I attended a workshop on a new approach to teaching beginning programming, called TeachScheme!. It started with a relatively simple, consistent language named Scheme, then used only a small fraction of that language, enforced by a beginner-friendly development environment that gave error messages appropriate to the level of the student. More importantly, the associated textbook, How to Design Programs, emphasized a process of problem-solving (henceforth "Design Recipe"), with specific, concrete questions students could ask themselves at each step. I loved the approach, and started using it in my own courses. Even when I had to teach those courses in a more difficult language like C++ or Java, I incorporated as many of the TeachScheme! lessons as possible: we spent more class time on language syntax and less on programming, but the explicit step-by-step process of problem solving still helped my students.

I joined the TeachScheme! team and, with the aid of NSF grants, taught dozens of other high school and college faculty to use the approach, including not only a Scheme-based first course but how to transition students to a more complex but more mainstream language like Java, while preserving the valuable lessons of the first course. Some of the high school faculty found the approach promising but reported that their students couldn't understand or relate to the textbook, How to Design Programs. So in 2006, Matthias Felleisen (lead author of How to Design Programs) suggested that I write a "high school edition" of the book. I started doing so, incorporating not only new techniques that the community had developed since How to Design Programs was published, but also insights from my years of experience teaching "Computer Programming for Non-Majors" at the college level. The result is Picturing Programs.

Many of my non-major students come into the course with math anxiety: they "know" they "can't do math", and their palms start sweating at the sight of an algebraic expression. So my book starts with graphics, and doesn't use an arithmetic operator until Chapter 7. Before that, students have learned about expressions, function composition, variables, function definition, a step-by-step design recipe, design for re-use, and the beginnings of event-driven, model-view GUI programming.

The curriculum is driven by data types. For every function the students write, the first question is "what type(s) of data does it take in, and what type of data does it return?" And I motivate every programming technique with the need to operate on a particular kind of data. Types with variants and cases motivate conditionals; types with fields motivate constructors and getters; self-referential types motivate recursion.

By the end of a semester, my English and History majors are writing recursive traversals of linked lists and binary trees, using higher-order functions, and building games with a model/view framework that respond to the keyboard, mouse, and clock. They've only learned half a dozen syntax rules -- not enough to get you through "Hello, World!" in Java or C++ -- but they've learned to design and test their programs carefully.