The Universe of Discourse

Wed, 25 May 2011 A couple of years ago I wrote an article about a stadiometer (height-measuring device) that used an optical scanner to read a Gray-coded height off the scale.

The article periodically shows up on places like Reddit and Hacker News, and someone often asks why the stadiometer is so complex. Most recently, for example:

How is this an advance on looking at a conventionally numbered ruler (with a similar bracket to touch the top of the head) and writing down the number? It's technological and presumably expensive, but it isn't delivering any discernible benefit that I can see.
Not long after I wrote the original article, I was back at the office, so I asked one of the senior doctors about it. She said that the manual stadiometers were always giving inaccurate readings and that they constantly had to have the service guys in to recalibrate them. The electronic stadiometer, she said, is much more reliable.

"But it's a really expensive stadiometer," I said.

"The service calls on the manual stadiometers were costing us a fortune."

This stadiometer transmits its reading via radio to a portable digital display. For this doctors' office, the portable display is a red herring. They had the display mounted on the wall right next to the stadiometer. I asked if they ever took it down and moved it around; the doctor said they never did.

At the time I observed that the answer was mundane and reasonable, but not something that one would be able to deduce. In the several discussions of the topic, none of the people speculating have guessed the correct answer.

When I was working on Red Flags talks, people would send me code, and I would then fix it up to be better code. Often you see code written in what seems to be the worst possible way, and the obvious conclusion is that the author is a complete idiot, or maybe just mentally ill. Perhaps this is sometimes the case, but when I took the time to write back and ask why the author had done it the way they did, there was usually a reasonable answer.

Here's an example that stands out in my memory. A novice once sent me a program he had written that did some sort of tedious file-munging job in Perl, selecting files and copying some of them around in the filesystem. It was a bad program in many ways, but what was most striking about it was that there were many functions to perform operations on lists of filenames, and whenever one of these functions called another, it passed the list of data by writing it to a temporary file, which the called function would then read back.

The diagram at right shows the structure of the program. Rectangles with rounded corners indicate subroutines; dotted rectangles are the temporary files they use for argument passing.

I suggested to the author that it would have been easier to have passed the data using the regular argument passing techniques, and his reply astounded me, because it was so reasonable: he said he had used the temporary files as a debugging measure, because that way he could inspect the files and see if the contents were correct.

I was thunderstruck. I had been assuming that the programmer was either a complete beginner, who didn't even know how to pass arguments to a function, or else a complete blockhead. But I was utterly wrong. He was just someone who needed to be introduced to the debugger. Or perhaps the right suggestion for him would be to call something like this from inside the functions that needed debugging:

        sub dump_arguments {
my ($file) = (caller)[4]; open my($f), ">", $file or die "$file: $!"; print$f join("\n", @_, "");
}

But either way, this was clearly a person who was an order of magnitude less incompetent than I initially imagined from seeing the ridiculous code he had written. He had had a specific problem and had chosen a straightforward and reasonably effective way to address it. But until I got the correct explanation, the only explanation I could think of was unlimited incompetence.

This is only one of many such examples. Time and time again people would send me perfectly idiotic code, and when I asked why they had done it that way the answer was not that they were idiots, but that there was some issue I had not appreciated, some problem they were trying to solve that was not apparent. Not to say that the solutions were not inept, or badly engineered, or just plain wrong. But there is a difference between a solution that is inept and one that is utterly insane. These appeared at first to be insane, but on investigation turned out to be sane but clumsy.

I said a while back that it is a good idea to get in the habit of assuming that everything is more complex than you imagine. I think there is parallel advice here: assume that bad technical decisions are made rationally, for reasons that are not apparent.