TITLE: The Development Arc of a Program and a Teaching Idea
AUTHOR: Eugene Wallingford
DATE: December 04, 2008 7:25 PM
DESC:
-----
BODY:
While reading on-line this summer, I ran across a description
of how keyless remote entry systems work. I can't find that
page just now, but here is a
nice description.
I never knew how those things worked. Very cool indeed!
As I was reading, the programmer in me soon was thinking,
"I'd like to write that code". The teacher in me almost
as quickly thought, "What a great example for for my
programming languages course...": programs with state
and shared data. A homework problem was waiting to be
written!
This week we got to the point in the course at which this
is a perfect homework problem. I started thinking about
it, but the week was busy... Finally, the night before I
was to post the assignment, I sat down to write my solution.
Within an hour I have less than a page of code that
implements:
- a random number generator, based on a C program from
my grad school operating systems course, which itself
was based on an
article by Park and Miller
in the Communications of the ACM, and
- a pair of functions that implement the remote entry
idea for a single behavior (say, unlock) and up through
the receiver re-syncing with a skipped-ahead transmitter.
While thinking before programming -- even agile programmers
are allowed to do that -- I realized that "re-programming" a
desynchronized transmitter/receiver pair would be beyond
scope of my homework assignment and that multiple behaviors
(say, unlock and lock, turning on an alarm, etc.) added
complexity to the code but no interesting ideas. I also
realized that there was no shared data in this
problem, but two pieces of state held in common: identical
random number generators and a key code.
As I programmed, it slowly dawned on me that this problem,
in its full form, was surely beyond the scope of my homework
assignment. I had a couple of other tasks for them to do,
and the keyless entry problem would require both a whole
assignment to itself and fairly detailed guidance for the
students on how to implement a solution. The interaction
between the transmitter and the receiver means that the
solution code has to be developed and tested in parallel,
and there turned out more to be more layers of indirection
in the solution than I had expected: a lambda
wrapping a letrec wrapping a let wrapping
a letrec wrapping a lambda wrapping one
final lambda!
That's more complexity than I care for my students to
encounter in the context of this assignment. With more
time and more of the assignment "real estate", I could
perhaps leave design a solution to students and then guide
them during the process. But this is a programming
languages course, and I'm trying to keep the focus of the
course on features of languages, not on the application of
functional programming or Scheme.
(I do love to have students see functional programming and
Scheme applied to "real problems", because so often they
view the programming language applications as, well, not
real. This problem is especially cool for that purpose,
because the ability to create a simple closure over two
simple functions is so useful here.)
Sigh. The opportunist in me, though, thought, "No problem.
Perhaps can will demo the solving of this problem in class."
And now I had a new problem: The only code I have is the
final version of my program.
I can still build a demo, designing a session around how
I grew this program, but I will have to re-grow it in my
mind and in my lecture notes. Unfortunately, the second
time through a solution is never quite like the first for
me, and in a way that effects the quality of result. The
second implementation usually feels and looks a little
too pat, a little too straightforward, too obvious. Most
people don't learn much about how to build something by
looking only at the final product, and when the final
product looks inevitable at every turn, all hope is lost.
The process of writing the code, and the decisions made
along the way matter -- the insights and the false starts;
the intermediate steps.
All I have is my final version. If only I had developed
this program under version control! At least then I'd
have a sequence of intermediate solutions that could help
me recover the sequence of decisions and insights and
false starts.
I know some people use version control for more than
developing software; Martin Fowler has even wrote about
putting his whole file system under Subversion.
I may not want to go that far, but what about the
particular case of developing code for a new demo, lecture,
or presentation?
This seems like one of those ideas someone has already had
and profited from. I'm just now getting it. Do you ever
do this for purposes of teaching or exposition?
Oh, well. I had a lot of fun implementing this code, and
that is always a welcome joy. I may yet show it off in
class, if only as a finished product. We programmers are
often like artists and other creators, and even like
parents: we are so proud of our children that we simply
must show everyone and brag on them! But turning this
solution into a powerful class session about using state
and mutually-referential functions must wait until I have
more time. Maybe next time I'll try building my new idea
code under version control and be able to move more
quickly.
Now that keyless remote entry is off the table as a
homework problem, I am back to the drawing board for a
couple of new problems to round out this assignment.
Well, the random number generator is a nice stateful
problem in its own right. And if I can just simplify the
idea of the transmitter/receiver pair, maybe I can create
a problem in the spirit of keyless entry systems -- only
with security circa 1970 -- that salvages some of my
initial excitement for this problem. Hmm....
~~~~
Postscript. I wrote the first
draft of this entry last night, right after whipping up
my solution and despairing. Current students of mine
know that I did salvage the idea, because I have already
set the homework problems in question before them! The
simplification was easier to make than I had feared.
The transmitter and receiver use a fixed code and can
never be synched. That made all the difference in the
complexity of the solution. I left the other parts for
extra-credit...
-----