BLOG@CACM
Computing Profession

Five Principles For Programming Languages For Learners

Posted
Mark Guzdial

Idit Harel posted an essay last month, American schools are teaching our kids how to code all wrong (see link here). She decried "pop computing" which doesn’t get to the "heart of computer science."

The light and fluffy version of computer science—which is proliferating as a superficial response to the increased need for coders in the workplace—is a phenomenon I refer to as "pop computing." While calling all policy makers and education leaders to consider "computer science education for all" is a good thing, the coding culture promoted by Code.org and its library of movie-branded coding apps provide quick experiences of drag-and-drop code entertainment. This accessible attraction can be catchy, it may not lead to harder projects that deepen understanding…The typical coding apps don’t get at the heart of computer science. Instead they stay at the surface, teaching what is comfortable and catchy.

Idit’s essay ignited conversation on CS education social media channels. Many of the conversations focused on drag-and-drop blocks-based versus text programming languages — which wasn’t Idit’s central point. I am responding to Idit’s essay by suggesting a set of principles for what we want in a programming language that we might use in schools. If we don’t want "movie-branded coding apps provide quick experiences of drag-and-drop code entertainment," what do we want? These principles are based on the work of other computing education researchers, including Seymour Papert, Cynthia Solomon, Alan Kay, Yasmin Kafai, and Idit herself.

Principle #1. Connect to what learners know

The first step when learning is to connect to what students already know. Nobody comes to class as a blank slate. Learning is a process of making sense of the world. We "make sense" of new phenomena in terms of what we already know. As The Atlantic published in its essay on the recently departed Jerome Bruner:

Bruner found that even very young children constructed their own knowledge—that is, they made sense of new information based on prior experience and understanding. The job of the teacher was to help students build upon what they already knew.

Logo is a terrific programming language explicitly designed for learners (see Wikipedia page entry). Logo is named for the Greek word for "word". Logo is all about words, which is something that even young children know about and are interested in. The terms word and sentence are primitives in Logo. Learners create new words in Logo by typing "to" and the new word, i.e., to square or to moveForward.

A teacher who says, "This is totally different than anything you’ve ever seen before" or "Forget everything you’ve learned before," is doing the students a disservice. Bruner and decades of cognitive psychology researchers since say that a teacher should relate new material to previously learned material. The first step is figure out what the learners already know and care about.

Principle #2. Keep cognitive load low

Human working memory, which we use when paying attention to something, is notoriously small and short-lived. We can attend to the "magic number seven" digits, but only five words, and even fewer chunks for children and young adults (see Wikipedia page). We underestimate how much cognitive load our modern programming languages require, because as experts in programming, much of our programming knowledge is tacit — we do it automatically without attending to the details, and without even being aware that we’re doing it.

Consider the phrase a == b+1 in a modern C/Java/JavaScript-like language in terms of all the questions that a novice has to consider. What’s the type of b? Can I add 1 to what’s in b? What’s the type of a? Can I compare a to b+1? Did I mean = or did I mean ==? Is this an off-by-one error — maybe I should add 2? Or -1? What am I trying to test here? Even knowing which of these questions is relevant and which isn’t requires executive monitoring that demands working memory.

Logo starts out with commands to an on-screen turtle which is programmed using functions that learners can do themselves. The command forward 10 means to take 10 steps forward. The learners can trace the command by doing it themselves. The command right 90 means to turn 90 degrees to the right — same tracing. A sequence of four forward 10 right 90 combinations makes a square. Later, the learner can start adding variables to represent the size of the square, and control loops to repeat four times without repeating the commands explicitly. The cognitive load here is small to start, and grows manageably.

Block-based languages are popular because they do a terrific job of reducing cognitive load. Studies by David Weintrop (see discussion here) and by Lauren Margulieux and Briana Morrison (see discussion here) have demonstrated the high cognitive load of textual programming languages and the much lower load of drag-and-drop blocks-based languages. Drag-and-drop languages can still be used to explore a huge range of CS topics (e.g., see description of GP). They are "real."

Principle #3. Be honest.

When Idit talks about the "heart of computer science," she means to show learners the real thing. She writes:

In other words, just as a kid playing Guitar Hero wouldn’t be considered a musician, someone playing with coding apps isn’t exactly a coder or computer scientist.

Jerome Bruner spoke of a similar goal in education (as quoted in The New York Times):

We begin with the hypothesis that any subject can be taught effectively in some intellectually honest form to any child at any stage of development.

Today, learning scientists speak of authenticity (see paper by Shaffer and Resnick). Learners want to learn things that are authentic, that are worthwhile. There are different senses of authenticity. Are you making things like those that professionals make? Are you using the same tools and working in the same way? Are students being assessed on concepts and skills that they need to know to be successful outside the classroom? Do students find the activities personally meaningful (see principle #1)?

Students don’t have to use Java and C to be doing something honest and authentic. They should be able to make real things, to explore important ideas in computer science, and to go as deep as they want. In contrast, a "programming" tool that only allows students to move a robot or avatar is not authentic in any sense of the word. It doesn’t depict a real notion of computer science.

The original Logo was sometimes called "LISP without parentheses." Logo could be used to explore a wide range of computer science topics, from modeling of natural systems, to artificial intelligence. It is authentic in the Bruner sense — it’s an intellectually honest form of CS.

Idit writes in her essay:

We are doing a disservice to kids by assuming that they can’t grasp industry-standard languages, complex computer science topics, and applications. By limiting them, we undermine their capabilities and stifle their creative and inventive potential.

We don’t want to limit students (see the next principle), but a language that is good for professional use is probably not good for learner use. Professionals have tacit knowledge — they can do a lot without taxing cognitive load. There is no advantage to using industry-standard languages for learners. They are often overly complex.

Even if we wanted to teach our children something that is "industry-standard," it’s not clear which industry’s language is most standard. Engineers use MATLAB, artists use Processing, statisticians use R, and Java is still the most common programming language in the software industry. Surely, we don’t think we should prepare all children for any one industry. "CS for All" should not mean "CS for the Tech Industry."

We should teach languages that are useful for learners’ purposes. You don’t need to learn carpentry with a nail gun, and you may never need a nail gun if you just want to repair a loose step. Our goal should be for children to work with programming languages in which they can explore complex topics (in CS and other disciplines) and expand their creative and inventive potential.

Principle #4. Be generative and productive

Computer programs are a medium that allows us to express and communicate ideas that we can’t in any other medium. Computer programming for children should be taught as a literacy that expands their ability to explore complex ideas. Children must be able to use programming to generate new ideas and be productive in learning in new domains. This idea started in CS. Alan Perlis (first ACM Turing Award recipient) said in 1961 that he couldn’t think about integral calculus the same way after learning iteration in a programming language (generative), and programming helped him see mathematics and economics in new ways (productive).

Logo is a great example of a programming language that has been used in classes from language composition, to science, to art, and to mathematics (see blog post describing these cross-curricular connections). Idit’s dissertation study was a terrific example of using programming to improve mathematics learning. But it’s not just Logo. Squeakland is about moving from the turtle up through physics simulations (see examples here). Bootstrap and CCL are two other projects that have explored using programming to help students learn algebra, physics, chemistry, biology, and other disciplines (see references here). I teach a course on economics and statistics called Computational Freakonomics using Python. Yasmin Kafai recently published a book about the wide range of ways in which programming can be generative and productive for learners.

The programming language matters. Bruce Sherin showed that students learn something different when learning physics with programming (in Boxer) compared to using algebraic equations (see post describing Bruce’s work here). Programming is not generative and productive if there is no language, no notation to think with. A tool in which students can build apps and games but doesn’t give them programming as a tool to think with (see example here) misses out on the greatest advantage of programming for learners. Programming language features which are about software development alone are likely not generative and productive, like typing public static void main at the beginning of every program.

Principle #5. Test, don’t trust

The hardest part about choosing a programming language for children is realizing that we can’t remember what it was like to be a child and we can’t actually think like children anymore. As experts, we have blind spots due to our tacit knowledge. It is literally inaccessible to our memories to think the way we did before we learned programming. When an expert says, "Oh, that’s easy — any child can do that," don’t trust them. Test, don’t trust.

We can’t even rely on teacher’s opinion about what will work for children. Teachers are much better judges than computer scientists, but only the best teachers are good at knowing what’s hard for children (see study on measuring this knowledge of teachers). Since computer science teaching is still so new, few teachers have developed a rich sense of what’s hard and easy for children. We need to try things, to put them into classrooms, and to measure what happens over time.

Low Threshold, High Ceiling

Brian Harvey coined the phrase "low threshold, high ceiling" to describe the goals of Logo. "Low threshold" means that that programming languages for learners should be easy to get started with (Principles 1 and 2), and "high (or no) ceiling) means that the language could be used to explore a wide range of ideas (Principles 3 and 4). I agree with Harvey’s description, and add to it that we just don’t know where the threshold and ceilings are until we try (Principle 5). It’s in our student’s best interests that we try more experiments, keeping in mind that we need to connect with children were they are, that we can too easily overwhelm them, that we should show them the real thing which is real CS not "industry-standard languages," and that we teach programming as a literacy that is generative and productive.

I used this principles in a kind of heuristic evaluation to analyze JavaScript and Ready as programming languages for learners (see post here).  The evaluation is biased, as all heuristic evaluations are. The point is to use the principles as a checklist, to make sure that we’re considering the important issues.

Sometimes we hear the idea that the only real "coder" or "computer scientist" is one that programs in a language that is used in the Tech industry. Yet we know that more than half of all programmers today are not in the Tech industry (see post here). It’s tempting to teach children the languages that are freely available, ubiquitous, and commonly used by professional programmers, but those professionals tools are likely not good programming languages for learners. Fortunately, we can invent languages that are just as free, run everywhere, and are designed well for learners.

Join the Discussion (0)

Become a Member or Sign In to Post a Comment

The Latest from CACM

Shape the Future of Computing

ACM encourages its members to take a direct hand in shaping the future of the association. There are more ways than ever to get involved.

Get Involved

Communications of the ACM (CACM) is now a fully Open Access publication.

By opening CACM to the world, we hope to increase engagement among the broader computer science community and encourage non-members to discover the rich resources ACM has to offer.

Learn More