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.
- "No, Bill, your instructions don't include "take the lid off the jar."
- "Err, Sally, wouldn't it help to *open* the bread before removing a slice?"
- "Ed, you never picked up the knife; 'scoop out a dolop' ... with what, a finger?"
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.
- Programming, especially in CeeLanguage and AssemblyLanguage is about thinking in sequences; abstractions follow from this, but not before you have some idea what you're abstracting.
- Each instruction in a sequence is an abstraction. You cannot think in sequences of instructions without thinking in abstractions. All computer programming relies on abstracting at some level, as does this problem. By teaching students to be detail-oriented rather than abstraction-oriented, a professor is getting them off on the wrong foot.
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.
- Job interviews take place after a person has (hopefully) learned to program. After you know how to drive a nail and cut a board, it's fine to talk abstractly about "framing a house," but by that time we hope the basics have been covered.
- So a carpenter teaches his apprentice to drive a nail by whacking it hard? (Rather than by keeping your eye on the nail.) Or to cut a board by leaning into it? (Rather than letting the saw do the cutting.) No, of course not! The basics must be learned correctly. Likewise, a beginning programmer must learn first to deal with simple sets of instructions, then he can build up to more complex abstractions. But he still must learn the simple abstractions correctly.
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?
- Remember, when teaching low-level languages, you are interested in how primitives are built and how they relate to the other stuff. The students very often could only talk abstractly about how to accomplish something, but given the task, could not implement.
- For the problem to be valid for this purpose, you must first give the student an instruction set he may use. Otherwise, whatever instructions he invents to express the procedure are valid, and the professor by criticising them is being unfair.
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.
- The class wasn't "SoftwareEngineering" but a low-level language class. Very "WaxOnWaxOff" -- fundamentals. You don't teach guitar or flute by starting with the symphony; you start with notes and chords.
- WaxOnWaxOff is about establishing good habits. Obsessing about details is a bad habit; dividing a problem into smaller units is a good habit. You teach guitar by first telling the student how to hold the instrument and making sure he is doing it correctly. Then you teach him what notes he has available. Finally, you let him play a simple tune. PeanutButterSandwich as presented starts at the wrong end, asking the student to play Pachelbel's Canon without so much as a piece of sheet music. However, it can be saved by becoming a means to discover how to decompose a problem.
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.