Thursday, December 16, 2010

Programmers as Children

Freud is quoted as saying that the postponement of gratification is the hallmark of maturity.  Developers are put the the test very often, since the computer can supply instant feedback on our programs - just run it and see what happens.  And, unfortunately, developers often fail this test.  It is much easier to try it out than to think it out!

When I started programming, up to the beginning of my student days, we could only use punched cards for our programs.  (Professors and other privileged people could use "terminals"!)  You had to punch your cards, then put the shiny deck on the dispatcher's table.  This high priest of the computer would be reading a newspaper, and although he would notice you staring at him, would ignore you completely.  Trying to hint to him that he should put your deck in the card reader would only make him slower.  Eventually, he would perform this operation, and then you had to wait for him to fetch the fan-folded paper from the big noisy line printer, separate it into individual printouts, then put it in your box.  And then you would find out that you forgot a comma.

The whole process would take about half an hour of turnaround time (for a few seconds of actual computation).  This made us very careful when submitting a job.  And, since there is only so many times you can go for coffee in one day, we would spend the turnaround time running the program in our heads: trying to figure out what can go wrong with it and fixing it on paper.

I will be the first to admit that checking for syntax errors is best left to the computer.  It is a waste of a developer's time to have to scan his code for them.  But time devoted to thinking about a program is time well spent.  As an undergraduate student, I wasn't thinking about formally proving my programs correct, and I didn't have the formal training for it, but in essence that is what I was trying to do.  And the result was that I found many logic problems before ever submitting the deck.

In my last year of undergraduate studies at Tel Aviv University, I took a compilation course and had to write a small compiler as a course project.  I decided to write it using a language made for the purpose: SNOBOL4.  Unfortunately, Tel Aviv U didn't have a SNOBOL4 compiler (probably because there wasn't one for the CDC 6600).  But I was taking a graduate course at the Weizmann Institute in Rehovot, and had an account on their IBM machine, which had the SPITBOL compiler for SNOBOL4.  Being reduced to the use of public transportation, I only visited Rehovot once a week, to attend my course.  So even though I had access to a 3270 terminal there and had almost instant turnaround time, I had to spend a week just staring at my listings between sessions.  I used that time to think about my compiler, and as a result finished debugging the whole thing in just two sessions at the terminal.  All told, I spent less time on the project that I would have if I had daily access to a terminal.  (Having a computer all my own to do my debugging on was totally unthinkable at the time.)

I'm ashamed to admit that I now find myself hitting "run" to see what happens, without thinking things through.  If it fails, I have learned something with little investment.  But what if it "works"?  Can I be convinced that my last change really eliminated the last bug, and I can go on to work on other things?  I still need to think carefully and convince myself that it will work on all other cases.

Testing is a useful way of increasing your confidence in your code.  But testing is not a replacement for thinking about the logic of your program!  What's more, writing good tests is a process that requires time and thought on its own.  And, like mental reasoning about programs, it is a process that many developers neglect.  But, more on that some other time.  I've got some code I need to think about.

No comments:

Post a Comment