Symbolic Programming vs. The A.P. Curriculum: Software Engineering

Download as ps, pdf, or txt
Download as ps, pdf, or txt
You are on page 1of 9

Symbolic Programming vs. the A.P.

Curriculum

Brian Harvey
University of California, Berkeley
A popular metaphor in recent years compares the process of writing a computer program to that of designing and building a bridge. The point of the metaphor is that it's
not acceptable to debug a new bridge design by building the bridge, opening it to tra c,
and waiting to see whether or not it collapses. People who use this metaphor argue that
the analogous technique isn't acceptable in computer programming either. The phrase
software engineering was coined to evoke the comparison with civil engineering and other,
similar disciplines. The view of programming as software engineering has had a profound
in uence on computer science education. The purpose of this paper is to examine that
in uence, particularly at the high school level through the College Board Advanced Placement curriculum, and suggest an alternative view.
(I am focusing attention on the A.P. curriculum to make the point concrete, but it
is just one of many similar in uences. The College Board did not invent the software
engineering view; it tries to follow the lead of its client colleges. At the college level, the
ACM curriculum standard could be cited instead. I teach at both levels, but I feel most
strongly about the inappropriateness of the software engineering approach in secondary
education.)

Software Engineering: Programming as Discipline


What are the characteristics of the software engineering approach? One fundamental
assumption is that the goal of a project is given in advance. It is not the civil engineer's
job to decide where a bridge should be built, or whether a bridge should be built in the
rst place. Those decisions are made by someone else|politicians, tra c ow experts,
perhaps railroad owners. The engineer is employed to carry out a prede ned project, and
is given a formal speci cation of the requirements.
A natural consequence of externally-provided goals is a top-down design technique.
Ideally, beginning with the formal goal speci cation, the engineer maps out large subtasks,
then develops each subtask into more and more detailed structure by a process called
\stepwise re nement," one of the central elements of the structured programming methodology. Mastery of this technique is the main content, apart from programming language
syntax, of most introductory computer science courses.
If a bridge falls down, its designer can be sued for damages. A similar standard of
professional liability should apply to the authors of computer programs, if lives or property
are endangered by their failure. Some professional societies have begun to propose uniform
standards for licensing of software engineers. If programmers are held liable for their
failures, it pays to use conservative techniques in the design of new programs. Just as civil
engineers rely on a few well-understood designs for bridges, programmers should use proven
algorithms to ensure program correctness. Mistakes should not be debugged by trial and
1

error, but should be prevented in advance by redundant error checking, strict adherence to
design standards, and formal proofs of correctness, techniques that one popular text calls
antibugging Cooper and Clancy, 1985].
One person can't build a bridge alone. Bridges are built by large teams, and it's
important that each team member have a well-de ned job. Similarly, software engineering emphasizes the needs of programming teams in which each programmer is assigned
a subtask. The top-down design approach is particularly important in a team environment so that each program segment has a well-de ned interface to the rest of the project.
Rigid standards are required about things like scope of variables and documentation of
subprocedures.
Finally, an emphasis on product has been implicit throughout this description. What
is most important is the program, rather than the style of work of the programmers. A
software engineer derives job satisfaction from seeing people use the product, more than
from the programming itself.
(In a recently-published polemic, Edsger Dijkstra, one of the founders of the structured programming methodology, dissociates himself from the name \software engineering"
because he thinks that it evokes a methodology based on testing, rather than on the formal
mathematical reasoning that Dijkstra prefers. Still, from the point of view I am presenting, Dijkstra and the software engineers are in the same camp because they both focus on
producing a program that meets a prior speci cation, rather than on the development of
that speci cation.)

Arti cial Intelligence: Programming as Art


Some computer programs actually do control processes in which a malfunction could
threaten human life. In those cases, I agree that programmers should regard their work
as closely analogous to other engineering disciplines, with the same professional standards
and the same conservative techniques. Much programming, though, does not have this
character. If a video game, for example, malfunctions, no lives are lost. Reliability is still
desirable, of course, but other characteristics, such as creativity in the design of the game,
are equally important. Unlike bridge-building, much computer programming is done by
hobbyists for their own personal satisfaction, and professional liability does not apply in
this case.
Among professional programmers, research work is in some ways more like hobbyist
programming than like civil engineering. Reliability may be less important than the exibility to explore new techniques. (Of course, reliability is itself the topic of some computer
science research, but even then the research cannot proceed by invoking already-known
methods.) In particular, arti cial intelligence research is characterized by the desire to extend the limits of what can be done with a computer; the researcher typically does not have
a body of well-understood, reliable methods to follow. It is not surprising, then, that AI
researchers have developed programming tools and approaches quite di erent from those
of software engineering.
2

In a research project, the goal of a project evolves in the work. That is, the programmer
starts with a broad idea, but often cannot specify the detailed behavior of the program
until it's written. She starts with a partial understanding, attempts to program some
better-understood corner of the project, and then interacts with the resulting program
to see in what direction to proceed. The goals are chosen by the same person doing the
programming.
If the goal is not precisely known in advance, a strict top-down design process is
impossible. Researchers use interactive design techniques, which may include some topdown components but also may include a bottom-up approach in which the work already
done provides a software toolkit that itself suggests new higher-level modules. Instead of
a single programming methodology like stepwise re nement, the researcher uses eclectic
techniques.
Since the result of a research project is rarely destined to be used directly in real
applications, there is no danger and no liability. Instead of following conservative, wellunderstood patterns, the researcher is encouraged to take risks and invent new methods.
Program debugging can be interactive; other members of the research community are often
encouraged to try out the program, not only discovering coding bugs but also contributing
to the incremental design process by suggesting improvements.
Research programs are rarely written by large teams. One reason is that you can't
get a Ph.D. for writing one percent of a program; another is that it's hard to coordinate
large teams without a precise, formal design document. But the most important reason is
that large teams are rarely creative. Instead, individual creation is required to solve new
problems.
To summarize, there must be an emphasis on process in the research programming
environment. The resulting program may be demonstrated once and never used again,
since it will probably be slow and clumsy, but by writing it, the researcher learns new ideas
that can be re ned and applied later. In education, too, the actual programs written by
students are unimportant; the student, not the program, is the \product" of the teaching
and learning activities. We should not be surprised if process-centered approaches to
programming turn out to be most helpful in education.
Even when a program is developed for practical use, the development process may
include steps that are more like research than like building bridges. Consider spreadsheet
programs. The history of their development, starting from VisiCalc and continuing to
current products like Lotus 1-2-3, has been a classic software engineering e ort, with large
development teams and precise goals. But the rst step, starting from nothing and getting
to VisiCalc, took two people, one of whom had the idea, \here is a new thing we can do
with a computer," and the other of whom was a virtuoso computer hacker, trained in the
MIT research environment.
(By the way, I do not mean to suggest that there is no research among civil engineers!
No doubt new bridge designs grow out of a development methodology much like the one I'm
3

describing for programming research. The contrast I am making is not between programming and civil engineering, but between research of any kind and the one-sided caricature
of civil engineering that provides the metaphor for the software engineering school.)
The metaphor of bridge-building powerfully captures the spirit of the software engineering view of programming. As an equally powerful metaphor for this alternative view,
I suggest considering programming as an art form, and the programmer as an artist.

How to Train an Artist


I am discussing the nature of computer programming to make a point about the nature
of computer programming education. There are two very di erent kinds of programming
activity, bridge-building and art. I suggest that our standard computer science curriculum
does a good job of preparing students for the rst kind, but not for the second. If we want
to develop computer programming artists, we should explore the training of other kinds
of artists.
(Both of these approaches are extremes. Some readers may feel more comfortable
with an intermediate position, representable in metaphor by professions such as medicine
and architecture that combine the need for individual creativity with careful attention to
conservative techniques. Still, I am trying to call attention to an imbalance in our current
educational practice, and in this context I think it is valuable to show what the opposite
extreme would be like. I hope that even this extreme will not seem impractical, even if we
ultimately settle on a compromise view.)
The training of artists is not the exact opposite of the training of engineers; art schools
do not merely throw the student into a room full of materials and say, \go to it!" There is
a discipline to art also, including a collection of well-understood, conservative techniques.
I suggest that the training of an artist can be divided into three categories of learning.
There is technical knowledge, such as the di erences between oil paints and water colors,
or the rules of perspective. There is technical skill, such as the ability to draw a straight
line freehand without wiggling, or the ability to stretch a canvas evenly before painting on
it. And there is inspiration, seeing the world with an artist's eye and nding something
worth painting at all.
All three of these are essential to a great artist, but inspiration comes rst! I am not
an artist, and my personal experience of art instruction has been limited to a couple of
introductory courses when I was in high school. In those courses, though, the teachers
made a big fuss about staying away from technique. \Never mind what it looks like" was
a frequent comment. One beginning exercise was to draw a chair with our eyes closed; the
point was to overcome our anxiety about photographic exactness and get us to enjoy moving
a pencil over paper in broad strokes. The teachers promised that technical instruction, for
those of us who did develop a deeper interest in art, would come later.
Art instruction that began with endless practice at drawing straight lines and perspective cubes would chase away any true potential artists. At best it would produce
\commercial artists," a classic oxymoron. This is the risk we run in computer science
4

education. (Commercial artists are socially useful, and so are the members of software
engineering teams. But there could be no commercial art without true creative artists to
invent the language and the tools of art.)

The Programming Language Paradox


Software engineers believe in constructing a program top-down. That is, they start
with the broad ideas of the program, and ll in the details later. You would think their
design tools would support programming in terms of broad ideas. Yet the programming
languages of software engineering, of which Pascal is the prototype, focus attention on
low-level details. They use explicit storage allocation, so the programmer must think
about the size, location, and extent in time of each data aggregate. They use strong
typing, encouraging the programmer to concentrate on the precise encoding of symbolic
information rather than on the meaning. They provide half a dozen speci c, hardwired
control structures, emphasizing the sequence of events in a computation rather than the
input-output behavior of functions. Complex data structures are manipulated with explicit
pointers, a common source of confusion and bugs.
Some of these low-level properties of software engineering languages are the result
of their early history as merely an abbreviation for machine language instructions. But,
for example, the transition from C (a hacker's language) to C++ (a software engineer's
language) has brought more attention, not less, to these low-level details. The improvement
is that in C++ the details can be represented more rigorously, with less need to rely on
ad hoc escape hatches such as type casting.
Software engineers recognize the inadequacy of their programming languages as design
tools. That is why they develop their programs using \pseudocode," essentially English
with indentation to indicate block structure. English is a good high-level design language
precisely because it does not require the programmer to think about memory allocation,
variable types, and so on. The di culty is that if one really designs in English, it's possible
to write an instruction that has no obvious translation (or even no translation at all) into
any programming language. To end up with useful pseudocode, the programmer must
actually cheat, writing the program mentally in something like Pascal and then translating
into English and leaving out most of the details.
There are programming languages that don't require such extreme attention to lowlevel details as the ones software engineers love. These symbolic programming languages
can readily express overall design as well as details. Why don't the software engineers
choose higher-level languages? The reason is that they overemphasize their concern with
reliability, and in particular with possible low-level bugs. For example, although a language
with explicit variable typing forces the programmer to be concerned with low-level details,
it also may help catch bugs in which an incorrect value is assigned to a variable.
The educational cost of the software engineering languages is that much of the time and
e ort in introductory courses goes into syntactic details, and into such low-level semantic
issues as binary representation, word length, ASCII codes, and pointer arithmetic. By
5

contrast, an introductory computer science course that uses Lisp Abelson and Sussman,
1985], coming from the arti cial intelligence research tradition, can focus attention on such
high-level semantic issues as functional programming, object-oriented programming, and
logic programming methodologies, data abstraction, and higher levels of abstraction such
as the design and implementation of a programming language. There is no pseudocode in
this text; a Lisp procedure written in terms of subprocedures that may not yet be de ned
provides the right level of abstraction, while retaining technical rigor.
The title of this paper is \Symbolic Programming vs. the A.P. Curriculum." It could
equally well have been \High-Level Semantics vs. the A.P. Curriculum" or \Programming
as Art vs. the A.P. Curriculum." For my purposes, what's important about symbolic
programming is that it allows us to step back from technical details, in a way somewhat
analogous to blindfold drawing exercises. There are technical ideas in the curriculum, but
they are high-level ideas, and they don't deaden the hacker spirit (that is, the artistic
spirit). In fact, as an introductory college-level course, I think the Abelson and Sussman
course works better than the traditional curriculum even from a bridge-building perspective, because even software engineers should start with the big ideas. Data abstraction,
for example, is part of the structured programming approach as well as the arti cial intelligence approach to program development.
I want to address a possible misunderstanding of the point I'm making. The choice
of programming language is not the central issue in designing an educational process. It
would be possible to teach a software engineering curriculum in any language, including
Lisp. (Indeed, these curricula generally make a point of not specifying a language, and the
authors of the curricula respond to accusations of language chauvinism by pointing that
out.) Such a curriculum would be just as bad as the same course taught in Pascal. Rather,
my point is that an examination of the programming languages that the adherents of each
approach actually do choose sheds light on how these approaches work out in educational
practice. The principle of top-down design sounds great when expressed in the abstract,
but the real teaching done in its name too easily gets bogged down in low-level technical
details.

What High School Students Need


In the United States at present, high school computer science education is strongly
a ected by the accidental fact that there is no o cial secondary curriculum, but there is
an o cial college-level curriculum for secondary schools in the form of the College Board
Advanced Placement exam. The result is that most high school students who are interested
in programming are now taught from a model that was designed (and badly designed, as
I have argued above, at that) for a college population. The problem is not the College
Board's fault; a lack of creative leadership at the secondary level has allowed what should
be an advanced curriculum for a minority of students to set the tone for all programming
instruction.
6

At the college level, where we are engaged in the training of professional programmers, the software engineering approach is sensible, even if not the whole story. I have
not suggested abandoning concerns about professional liability, conservative design, and
teamwork in the context of programming projects in which lives or property are at risk.
Rather, I have argued that software engineering concerns should be balanced by a lively
sense of the artistic, creative side of professional programming, and that large ideas should
come before technical details in the curriculum.
At the high school level, I want to argue for a more extreme view. High school
students are not about to enter the job market as professional programmers. Rather, they
are exploring a possible interest in programming, and preparing for further instruction at
the college level. They can learn discipline later. Now they need a kind of apprenticeship:
real tasks to work on, the freedom to experiment and to risk failure, but in an environment
that models respect for commitment. They need teachers who serve as experts available
for consultation, rather than lecture on technical knowledge or set exercises of technical
skills.
(I am concerned here with the needs of those students who are interested in computer programming. The design of a \computer literacy" curriculum for all students is a
separate issue. I have argued elsewhere that it is really a non-issue; students should be
quite comfortable with word processors and other utility programs long before they leave
elementary school. The widely perceived need for a secondary school \literacy" curriculum
is a temporary result of the fact that computers have only recently entered the schools in
signi cant numbers.)
Not every teenager wants to program computers, but many do. Computers are powerful, responsive tools. Apart from reading, few intellectual skills appeal so strongly to
young people, especially not formal, technical ones. We educators are lucky that computer
programming ranks almost as high as skateboarding and playing the guitar! We should
teach programming in a way that nurtures this excitement, not turning it into one more
academic subject full of facts to be paraded on exams. Instead, high school programming
instruction should be project-based, with projects chosen by the students themselves as
much as possible. The A.P. curriculum is particularly bad, because of its emphasis on conservative technique and correspondingly low-level details, but any xed curriculum would
interfere.
Of course the student's apprenticeship can't begin without an initial period devoted to
learning the rules of a programming language. But I think we should look upon this early
work as an unfortunate necessity, rather than as the focus of our curriculum, and we should
try to get it over with smoothly and quickly.* To this end, we should choose a high-level
language such as Lisp to minimize the time spent on syntax and machine representation
issues. (Abelson and Sussman use the Scheme dialect of Lisp in their text; for high school
* In practice the division into stages is not so clear-cut. Students can be working on
independent projects in parallel with formal instruction in the language. Still, the two are
very di erent in style, and will probably be experienced by students as separate activities.
7

students I prefer the Logo dialect, which provides many of the same high-level mechanisms
along with a user interface that is less intimidating to a beginner.) I also like to minimize
formal lectures, relying instead on a self-paced format and scheduling advanced students
into the lab at the same time as the beginners to allow for informal one-on-one tutoring.
In this early stage, I have come to think that debugging (and antibugging) should not
be a large part of the student's experience. It's true that debugging is excellent mental
exercise, but real beginners tend to make uninteresting mistakes. Spending 15 minutes
struggling with an unnoticed punctuation error just teaches frustration, and so I will often
debug a beginner's program myself and encourage the student to get on with the big
idea that the bug interrupted. Only if the bug seems to indicate a serious conceptual
misunderstanding do I make any fuss about it.
The second stage of the student's apprenticeship focuses on projects. This e ort
should be supported structurally with a curriculum-free lab course that can be repeated
for credit; interested students may enroll in the lab throughout half a dozen semesters.
(One problem with the \back to basics" movement is that it has encouraged a uniform
set of courses for all students. One semester of programming is more than many students
need, but not nearly enough for many others.) If the school will allow the course to be
taught without assigning grades, so much the better. The teacher's role at the beginning
of the semester is to ensure that each student takes on a project that is challenging but not
overwhelming; later, the teacher serves as a consultant, looking over shoulders when that
feels appropriate. It is also appropriate to make concrete suggestions about programming
style, pointing out how a particular student program could be organized more clearly, but
I think teachers should not insist on universal adherence to broad a priori rules.
For most high school students, this second stage can last through the senior year.
If the programming projects are selected well, each student will learn certain universally
important ideas (such as recursion), and also each student will learn many other ideas
that happen to be relevant to his or her projects but are di erent from another student's
learning. This project laboratory will be excellent preparation for a more rigorously structured computer science curriculum in college. Some students, however, will eventually
get tired of projects and will ask for more formal instruction about meatier ideas. For
them, a third-stage course can introduce computer science topics such as automata theory
or compiler construction; alternatively, a true Advanced Placement course can be o ered
using the Abelson and Sussman text.
I have written a series of three texts, using Logo, to support these three stages Harvey,
1985, 1986, 1987]. The rst (introducing the language) and the third (computer science
topics) are meant to be read sequentially, like most texts. The second is a collection of
projects, in no particular order, intended to serve as an inspiration and to provide starting
points for student projects rather than to be read from cover to cover. A series like this
has the advantage of a uniform style and the ability to rely on earlier learning in the later
volumes, but alternatives are available for each of the three stages. In particular, there are
many collections of programming projects available, and the computer lab should have a
wide assortment. In the third stage, even a Pascal-based text covering the o cial Advanced
8

Placement curriculum wouldn't be too harmful; my concern is that that curriculum has
become, by default, the only programming experience for many high school students.

Conclusion
To summarize, I am presenting for computer science an argument that has come up
before in many other areas of science and mathematics education. Our o cial curricula,
I think, run the same risk as the o cial physics curriculum that caused Albert Einstein
to drop out of school. Such rigidity would be particularly regrettable in a subject like
computer programming, which lends itself so readily to a exible, experimental approach.

References
Abelson, Harold, and Gerald Jay Sussman. Structure and Interpretation of Computer
Programs, MIT Press, 1985.
Cooper, Doug, and Michael Clancy. Oh! Pascal! Second Edition, Norton, 1985.
Harvey, Brian. Computer Science Logo Style, MIT Press.
Volume 1: Intermediate Programming, 1985.
Volume 2: Projects, Styles, and Techniques, 1986.
Volume 3: Advanced Topics, 1987.

You might also like