Peanut Butter Sandwich

The name of an exercise I used to give to my programming students.

"You are watching the game. The commercials start. You get up from your chair to make a PeanutButterSandwich. Describe, in detail, completely, all the steps needed to make this sandwich from the moment you enter the kitchen to the moment you leave with the sandwich."

Then, on the day this was handed in, I would bring a loaf of bread, a jar of peanut butter, and a spreading knife. The rest of the class was basically spent in hysterics, watching students attempt to execute what they'd written.

Some of them would forget to take slices out of the loaf before smearing them with peanut butter.

But there was always someone (usually a few someones) who had thought it through and diligently listed all the steps. Those classes were a joy to teach.

I've used this model (though not with peanut butter sandwiches) as an apprenticing tool with some success. A simple task whose steps and results are already known is assigned, and the novice is monitored. Getting it right becomes a badge of accomplishment within the local culture.

I wonder what devices others use to teach the very basics of programming?

-- GarryHamilton

That sounds like fun! However, this is a self-selecting process. Some of us are obsessive about details as a matter of personality from an early age. That trait is one of the things that can lead to becoming a programmer. Contrast this with people whose personalities and mindset is such that they have a strong distaste (or other reason for avoiding) obsessing about details.

Now put both kinds of people in an intro class in programming. Guess which ones will do PeanutButterSandwich exercises in a workable way on the first try?

Or just check out self-taught successful programmers. Guess which personality traits they will have?

Personality makes a huge difference, although we can't entirely quantify the subject. We can, however, notice certain qualitative issues like this. Another area is musical performance. Some people are brilliant but mechanical in their playing; national and world competitions seek out those who also are able to be emotionally expressive in their playing. In general you can't teach one group to be like the other; you can develop a trait in them, but the trait has to be in them to start with.

   "You have style no one can teach. Must be born this way."
   -- Suyuan to June (Ming-Na Wen), "Joy Luck Club"
-- DougMerritt

That's why it's an introductory class, so that people can find out whether or not they can program with minimal cost. -- SunirShah

[ Actually, this was only the first part of a class (okay, 3 different classes) in your choice of AssemblyLanguage, CeeLanguage, or DataBaseLanguage?. I found, much to my horror in my first two semesters, that my assumptions about the foundation knowledge possessed by my students were woefully wrong. I introduced the PeanutButterSandwich exercise for two reasons: 1) discover what foundation my students actually had, and 2) undercut the lack of prior foundation. It also provided us with a bit of a laugh and an opportunity to break the ice. All of the classes I taught had prerequisites (the least being BASIC), but somehow the business of teaching logic had been missed. ] -- gh


Human manual processes very often have to be documented in detail for manufacturing (HawthornExperiment?, Time and Motion studies). LabaNotation (one of a few DanceNotationSystems) has been adapted to describe assembly at large companies such as GM.


This is an unfair problem, however. And it doesn't tell you anything about whether you can code, much less whether you can do any of the other things software engineers do.

In fact, in a job interview, I would probably rate more highly those applicants that had not written down every step from the beginning. Why? Because it shows they can think in abstractions rather than trying to juggle all the details. They can talk about getting a slice of bread without worrying about how the bread got out of the breadbox or where they're going to put it, both issues which can be handled by other definitions, other functions, which can be written as needed. It shows they can handle incremental development rather than defining everything up-front. It shows they'd work well in a code-test-refactor cycle. It shows they can solve problems as needed rather than wasting effort trying solve problems they may never need. It shows they're not afraid to reuse whatever solution may be available, rather than recoding everything using primitive operations. Actually, on this note, what is a primitive operation? Why is getting a slice of bread from a closed bag not a primitive? Why do I have to state explicitly that the bag must be opened? On the other hand, why is getting a slice of bread from an open bag indeed a primitive? Why don't I have to chart the course of the hand and fingers as they navigate their ways? No matter what primitives you use, you must rely on abstractions of some sort or the exercise itself falls apart. Why is one set of assumed-already-implemented abstractions necessarily better than another? I would agree that this is a biased problem that guarantees failure. The necessary steps can be continually decomposed and pushed back in history. Did you take the peanut butter jar out of the cupboard? Did you buy the peanut butter and put it in the cupboard? Did you specify that a clean knife is used to spread the peanut butter? Did you describe how to grasp and hold the knife? I don't see how this provides any basis for learning, what is the lesson?

I don't understand questions like this. Are you really looking for someone to give you every detail about why an exercise might or might not be useful for every possible potential audience? Are you so immersed in the details of the question that you can't stand back and say - there are lessons to learn here, although obviously it's not always completely relevant for everyone. Can't you take someone's idea and see how to use it constructively? Must you always pick holes in every suggestion? I'm sure that makes you useful for some kinds of work, but in this sort of communication medium I find it utterly destructive.

There are lessons to learn, and it's important to learn the right lessons. Thinking through all the steps ahead of time is a poor lesson to learn, as you can never keep the whole of a problem in the forefront of your mind, and as you will always misunderstand some detail of the system. (Compare BigDesignUpFront.) A beneficial lesson would be learning how to factor the problem so you can focus on only a part of it at a time. This is the basic lesson of software engineering, yet this is not the lesson novices usually learn. As a result, they must eventually unlearn bad habits: massive functions, overweight classes, unfactored designs; they must learn good engineering practices. People who are obsessive about details do not necessarily make better programmers or engineers. Successful programmers (self-taught or otherwise) are not detail-oriented; they are abstraction-oriented. Bad programmers keep long lists of details in their heads; good programmers know how to organize complexity so that it can be divided and conquered.

It is also important to learn how to respond to failure, and this can be an important lesson learned from this exercise. The best job interviews confront candidates and poke them in the eye, in order to see how they respond. Do they become defensive? Or do they further adjust their solution in order to address the problem?


I always thought the point of the exercise wasn't to install an insane sense of detail. Rather it is a very expressive way of explaining the literal-mindedness of computers and how that affects programming; especially as it realates to DoWhatImean. I've found TeachMeToSmoke to be highly useful in explaining why I can't "just tell the computer to do Foo" to the layperson. One interesting view of ObjectOrientedDesign is that it's just a way to incrementally build up a DomainSpecificLanguage, until you can actually tell the computer "Just do it."

Indeed - most of the complaints on this page seem to miss the point that education (done properly) is about learning - not about impressing the class, acing the quizzes, meeting the instructor's expectations, or anything else. An introductory exercise need not (and cannot) teach every side of every issue, but at one point or another the students will need to learn that programming a computer requires understanding how different their instruction set is from ours. True, it would be more accurate an exercise to explicitly list the allowed instructions beforehand, but I would contend that it is a basic fact that all exercises short of total immersion in a real-world working environment are necessarily incomplete. If you're aiming to introduce a fundamental concept, an overly simplistic exercise is quite appropriate. And if as a bonus you want to throw in a little preview of the very real ambiguity and mutability of their future employers' wishes and demands, an exercise they can't get right isn't such a bad thing to throw in every so often. I know I for one never learned much from exercises that I already [thought I] knew how to do.


Very similar to TeachMeToSmoke.

See also LearningProgrammingLanguages.


EditText of this page (last edited May 24, 2008) or FindPage with title or text search