Computer Programming for Everybody

Guido gives us a peek into the future of CP4E—will the Spanish Inquisition be there?

The on-line Python community is full of
little traditions that aren't immediately clear to the outside
observer. These can range from oblique
whole-sentence-in-one-hyphenated-string-signatures via the occult
(“channeling Guido”) to outrageous, e.g., references to the
Spanish Inquisition.

One recurring theme is my apparent possession of a time
machine. It's often believed this is just a rhetorical device; when
someone reports a bug in Python, I will appear to have gone back in
time to fix it, so I can answer “that's already fixed in the
current working sources.” It would be easy to fake this effect
with other means; however, in this article I will show that I
actually do have a time machine. I'll change the settings to let me
travel to the future instead of the past, and report back with what
I have seen. Let the demonstration begin.

[...Bzzzzzt!]

A cardinal in a bright red suit appears and accuses me of
heresy. His helpers grab me and throw me into their dungeon, where
I await execution. Fortunately, I still have my time machine
control device with me and quickly press its reset button.

[...Bzzzzzt!]

Oops! It seems I had mixed up reverse and forward, and was
accidentally thrown back into medieval times. As they say, “nobody
expects the Spanish Inquisition.” Cardinal Biggles, I'll come in
again.

[...Bzzzzzt!]

We're in a middle school, observing a computer programming
class. The year is 2002 or perhaps 2003—it's hard to tell. Each
pair of students has a computer in front of them. The computers
don't look much different from what we're used to in 2000. In fact,
they look like they were bought before that year—in the future,
educational budgets are obviously not too different from what they
are today. Maybe the biggest difference is they are all running
Linux—still uncommon in today's classrooms!

On the screen we see the user interface of an interactive
Python development environment. The development environment appears
to be derived from IDLE, the current Interactive DeveLopment
Environment for Python in Python, but it has undergone considerable
improvements compared to what's on the web site in early 2000.
Let's have a look.

We walk up to two girls in the back of the class who are busy
debugging a Barbie dress-up game used as an exercise. Not all
groups are using the same examples, by the way. We see kids
manipulating characters from a Pokemon-like game, controlling robot
fighters, constructing mathematical-looking curves and painting
dazzling abstract color patterns on their screens. We even hear
some computer-generated music.

The game doesn't seem to be working quite right yet: Barbie
is hanging in mid-air in a most uncomfortable pose. The girls are
engaged in a mild dispute over the right way to fix it. They decide
to run the program in slow motion so they can see exactly where the
code goes wrong. One girl presses a pink heart-shaped button
labeled “run” (she has customized IDLE's user interface to match
her taste...) and a menu with run options appears. Among these is a
control to choose the execution speed (from tortoise to hare) and a
separate checkbox for stepping. The girl leaves the stepping choice
unchecked and clicks on tortoise. The program now starts executing
line-for-line, highlighting the current line in the source window
and showing the variables in a separate window.

I notice the source window seems to keep the entire current
function in view so as to minimize scrolling and maximize context.
The background takes on a slightly different shade once a line has
been executed, giving us an idea of code coverage. When the program
hits an if or while statement, the outcome of the test is indicated
by briefly flashing the line in green (true) or red (false).
Variables are arranged according to frequency of use; whenever a
variable changes, its background lights up. Variables not actually
used by the program are grayed out. Whenever a function is called,
a new window showing its variables pops up, overlapping the
previous function's variable window but slightly offset below,
suggesting a stack of variable windows. Clearly it represents the
call stack.

After a few minutes of happy slo-mo execution, the program
goes off into a lengthy subroutine with which the girls appear to
be familiar. It seems to count to 100 doing little interesting
work, but taking several program steps for each iteration. The
girls quickly press a button labeled “boring” and the session
picks up the pace again. The “boring” button appears to have
marked the function as permanently uninteresting; later calls to
this function are treated as a single step instead of stepping into
it.

Whoa! The program, running in slow motion, now appears to
have hit the same snag we saw previously. Barbie is uncomfortable
again, but the program continues to run—things are getting worse!
The girl closest to the mouse quickly presses the stop button, and
asks the other what to do now. Her friend says to hit the “reverse
step” button a few times. This takes the program back in time and
the display unwinds as well, until Barbie is fully unknotted. The
girls now carefully take the program forward from this point one
step at a time, until the first sign of trouble appears. At each
step, they look for suspicious changes in the variables
window.

Aha! The bug is found. A method argument had a constant
value, but should be a variable instead. The code is changed, the
reverse step button pressed, then the run button activated again;
Barbie dances around as if she was born to dance. Note that the
execution didn't have to be restarted from the beginning. Are
dynamic interpreted languages great, or what?!

We leave our two girls alone and join two boys in the next
row. They are working on a networked game they just downloaded from
the Web. (The girls got the parts for their Barbie program from the
teacher.) The boys bring up a program dissection tool from a menu
customized in extreme-gothic style. The boys are looking for the
low-level network calls: the teacher has suggested that a nice
exercise would be to add a network performance monitoring feature
to the game, which should show the network activity generated by
each player. But first they need to find the networking
code!

The boys rotate through a number of structural diagrams of
the program, each looking at it from a different point of view:
module hierarchy, class inheritance diagram, call graph and so on.
None of these seem to give them what they are looking for, so they
decide to fire up a search instead. Hey! That doesn't look like the
familiar “find string” dialog at all: it looks more like a search
engine, maybe Google or Infoseek. Indeed, the results of the search
for “network” are sorted by relevancy. Each result is displayed
with a little bit of context and several buttons to view the result
in the various views.

The boys click on various buttons (they're obviously new at
this too!). We notice that the views try to be helpful: they
scroll, zoom or distort to show the context of the search result we
select. In one of the more detailed views, we see the source code
of a method that sends messages to the network.

We now want to know if this is the routine we're looking for.
The system can't answer that question directly, but it can answer
two others that help us. First, it can find all the call sites for
this method. Second, it can look for other “similar” routines.
How does it define “similar”? Hard to say exactly, and
unnecessary; something like “uses some of the same externalities
or instance attributes” might get close. In any case, matches are
sorted by relevance again, and the boys deal with it the same way
they deal with web search engines: inspect a few items near the top
of the list until they're satisfied they have found the right
method. The boys find one other method that looks almost identical,
and checking for call sites shows that it's never used! Looking
more carefully, it seems to be a debugging version of the same
routine, left in the code “just in case”; we can safely ignore
it.

Another question this system can answer for us: how
frequently is this function called? That's important because we
want to instrument it. To find out, we run the program with the
profiler enabled. Fortunately, there are some other players in the
class, so we get to see some action right away: our robotic
character runs after others like it through doom-laden corridors,
while in a separate window the profiler's statistics light up,
showing repetitive patterns as the game goes through its
phases.

When we feel we've collected enough data, we abandon the
chase and look at the profile data. Opening the source code window
for the method we selected earlier, we find that the background has
been colorized according to use: the most frequently used lines
have the most colorful background. The most obvious conclusion we
draw from this is that there's a very short common path through the
code and the other paths are rarely taken. A huge piece of
exception-handling code has not been touched at all. With a few
mouse clicks, we open a window with details about this function: it
was called 9,245 times, total execution time was 2.4 seconds,
averaging 0.26 msec per call. We also see the callers, sorted by
call frequency, and we can hyperlink to the call sites.

The boys have their work cut out for them. It's time to leave
them alone with their programming exercise and pay a visit to the
teacher. Her computer is networked with all the students'
computers, and a status display summarizes what each pair of
students is (and has been) doing. One of the summary windows is
flashing: the students are asking for help or have handed in their
project for review. Since this is an ordinary classroom, the
students rarely use this feature to get help, unless the teacher is
busy helping someone else; but in a distance learning situation, a
teacher can use it to chat with students while looking at their
project on her own screen. She can even drive the student's user
interface this way, to show them how something's done or to fix an
error.

This time, it seems that a student's project is ready for
review. The teacher clicks on “download project” in the flashing
window, and a local copy of the student's project is created and
opened.

The teacher pulls “verify project” from her File menu now,
and we see the project verifier churn away on the modules in the
project. No errors are found; a few warnings show up, such as
unreferenced variables and methods, and some style issues
(irregular indentation and a bit of spaghetti-code), but nothing to
make the teacher frown. After all, these are 14-year old kids, so
we can cut them some slack! When the verifier is done, it displays
an overall structural diagram of the program. One nice touch: since
the goal of this project was to extend an existing project, it uses
a different background color for classes and methods that the
students have changed, and a different color again for totally new
ones. The teacher samples a few changed and new methods, then
decides to run the program.

Our teacher trusts her students and is proud of them—but she
wasn't born yesterday, and she knows from experience that student
projects can contain pranks or accidental bugs. Therefore, she runs
the student program in “restricted execution mode”. This limits
the program's ability to access files or programs outside its own
project directory and prevents accidental or intentional mishaps on
the teacher's system. The student projects are chosen to minimize
the needs for such access; the teacher has configured her
environment restrictions to allow access to certain trusted
applications and the network.

The program runs: it is a simple puzzle game with a 3-D user
interface. The teacher interacts with it, looking for ways to break
it. The program stands up to scrutiny: it behaves correctly even in
the face of incorrect input. The teacher now inspects the profile
window for irregularities; in particular, looking for performance
snags and code coverage. Everything checks out: the students
deserve an A. The teacher opens an annotation window for the
project and enters her notes to the students there; a click on the
“send feedback” button mails her notes back to the students. She
gets no time to relax: two students need help understanding the
inheritance diagram of a large application they are just starting
to dissect, while another pair have crashed their machine for the
third time in a row. Some things never change.

We leave the teacher to her hectic job, and decide we've seen
enough for a day; it's time to press the button on our time machine
control again.

[...Bzzzzzt!]

Phew! Wasn't that exciting? I wish we could've stayed longer,
talked some to the students and seen some more software
demonstrations. While I was there, I noticed some interesting new
things on the Linux desktop that I didn't get to have a good look
at. But LJ's editor is waiting for my copy,
and it seems I can't use the time machine to extend
deadlines!

For some references you can follow without time travel, see
Resources.

Guido van Rossum
(guido@CNRI.Reston.VA.US) is the
creator of Python, one of the major free scripting languages (he
prefers to refer to Python as a very high-level language). In 1995,
he moved to the U.S. and he now lives and works in Reston,
Virginia, for CNRI (the Corporation for National Research
Initiatives). At CNRI, he heads a research group working on CP4E
(using Python in education) and is technical director of the Python
Consortium, an international consortium hosted by CNRI, formed to
promote and further the development and use of Python.