Learning to design programs is like learning to play soccer. A player must
learn to trap a ball, to dribble with a ball, to pass, and to shoot a
ball. Once the player knows those basic skills, the next goals are to
learn to play a position, to play certain strategies, to choose among
feasible strategies, and, on occasion, to create variations of a strategy
because none fits.
A programmer is also very much like an architect, a composers, or a writer.
They are creative people who start with ideas in their heads and blank
pieces of paper. They conceive of an idea, form a mental outline, and
refine it on paper until their writings reflect their mental image as much
as possible. As they bring their ideas to paper, they employ basic
drawing, writing, and playing music to express certain style elements of a
building, to describe a person's character, or to formulate portions of a
melody. They can practice their trade because they have honed their basic
skills for a long time and can use them on an instinctive level.
Programmers also form outlines, translate them into first designs, and
iteratively refine them until they truly match the initial idea. Indeed,
the best programmers edit and rewrite their programs many times until they
meet certain aesthetic standards. And just like soccer players,
architects, composers, or writers, programmers must practice the basic
skills of their trade for a long time before they can be truly creative.
Design recipes are the equivalent of soccer ball handling techniques,
writing techniques, arrangements, and drawing skills. A single design
recipe represents a point of the program design space. We have studied
this space and have identified many important categories. This book
selects the most fundamental and the most practical recipes and presents
them in increasing order of difficulty.
About half the design recipes focus on the connection between input data
and programs. More specifically, they show how the template of a program
is derived from the description of the input data. We call this <#89#>data-driven<#89#> program design, and it is the most frequently used form of
design. Data-driven designs are easy to create, easy to understand, and
easy to extend and modify. Other design recipes introduce the notion of
<#90#>generative recursion<#90#>, <#91#>accumulation<#91#>, and <#92#>history sensitivity<#92#>. The first one produces recursive programs that generate
new instances of problems as they recur; accumulator-style programs
collect data as they process inputs; and history-sensitive programs
remember information between successive applications. Last, but not least,
we also introduce a design recipe for <#93#>abstracting<#93#> over
programs. Abstracting is the act of generalizing two (or more) similar
designs into a one and of deriving the original instances from it.
On many occasions, a problem naturally suggests one design recipe. On
others, a programmer must choose from among several possibilities; each
choice may produce programs with vastly different organizations. Making
choices is natural for a creative programmer. But, unless a programmer is
thoroughly familiar with the bag of design recipes to choose from and
completely understands the consequences of choosing one over the other,
the process is necessarily <#94#>ad hoc<#94#> and leads to whimsical, bad
designs. We hope that by mapping out a collection of design recipes, we
can help programmers understand what to choose from and how to choose.
Now that we have explained what we mean by ``programming'' and ``program
design,'' the reader can see why and how teaching program design instills
thinking skills that are important in a variety of professions. To design a
program properly, a student must
- analyze a problem statement, typically stated as a word problem;
- express its essence, abstractly and with examples;
- formulate statements and comments in a precise language;
- evaluate and revise these activities in light of checks and tests; and
- pay attention to details.
All of these are activities that are useful for a businessman, a lawyer, a
journalist, a scientist, an engineer, and many others.
While traditional programming requires these skills, too, beginners often
don't understand this connection. The problem is that traditional
programming languages and traditional forms of programming force students
to perform a large amount of book-keeping work and to memorize a large
number of language-specific facts. In short, <#97#>menial work drowns the teaching of essential skills<#97#>. To avoid this problem, teachers must use
a programming environment that imposes as little overhead as possible and
that accommodates beginners. Because such tools didn't exist when we
started, we developed them.