Thursday, March 5, 2009

The Dead Mother Counter

This is a story of how a series of completely rational decisions can lead to a completely irrational result. It was told to me nearly 20 years ago, as then-recent history; I have retold it many times since. While it's possible that the original teller embellished the story somewhat, or that I've embellished it since, I believe that the events actually occured, in generally the order given here.

The story takes place in the internal IT group of a company that manufactures aircraft engines. If you haven't worked for such a company, or haven't been otherwised involved in aviation, you may not realize just how much paperwork accompanies the building of a jet engine. Each part, from the time it's a billet of metal to the time that it's fastened into an assembly, has a paper “routing sheet” that lists every step of that part's manufacture. When the engine goes out the door, all of these routing sheets are sealed in an argon filled container, as a permanent record of the engine's history. The only time these containers get opened is when an aircraft goes down.

As a practical matter, however, paper routing sheets aren't very useful. They can't be analyzed for cost and quality-management purposes. Most important, in the case where a [art fails and causes an engine to self-destruct, it's not easy to find all the other [arts — and their engines — made from the same batch of metal.

This is where the IT group enters the story, with a hardened shop floor terminal connected to a central computer. At each step of the process, the shop worker scans his badge (and in the 1980s, “his” was appropriate), works on the part, scans his badge again, and inserts the routing sheet for the official printed record. On the other end, the computer generates voluminous reports on green-bar paper, describing in great detail the operations of the shop.

And this is where Human Resources enters the story. According to the story, one day an HR person saw a worker scanning his badge, and realized that their manual timecard system was obsolete. So they requested the IT group to add timecard functionality into the system.

I had to “punch a clock” for a job I had in High School. It seemed pretty simple: when arriving in the morning I'd put the card into the machine and it would print the current time on the card. I'd do the same thing when I'd leave. We received a paid half hour lunch break (primarily because we worked off-site), but the same process applies if you have to punch out for lunch. In a large organization, I would expect timecards to be machine readable, to minimize processing costs.

And it seems like a pretty simple process to automate. Given the limited tools of the time, perhaps a month or two to implement, test, and deploy. This particular project took far longer …

The reason was the foreman's terminal. Flex-time is unknown in a large industrial shop. If you're late, or miss a day's work, you need to have your foreman write up an explanation. It's unclear to me whether HR actually asked to have this automated, but automated it was. The foreman would scan his badge, then your badge, then choose from a list of reasons for missing work. One of these was “death in the family.”

And then someone asked the fateful question: “how can we track whether a person repeatedly claims a death in his family?” And the dead mother counter was born. It was a field in the database that would be incremented each time a person used that excuse. And there were volumninous reports on green-bar paper that listed the people who used and abused the excuse.

This was the point at which HR stopped funding the project. And when I joined the IT group a couple of years later, there were still timecard machines in the entrance to each shop building.

Tuesday, February 24, 2009

Wikipedia is the new Yahoo

In the beginning — 1994, early 1995 — Yahoo wasn't a portal, or a search engine. It was a collection of links to “cool stuff,” compiled by a group of grad students. They categorized everything that they found on the web, and the rest of us benefited: we could go to Yahoo, drill down through the categories, and learn about whatever we were interested in at the moment.

The web expanded, of course, until it was no longer possible for human-powered indexing to capture everything. And that's when the search engines took over: Yahoo itself, Altavista, and the current king, Google.

The trouble with search engines is that they aren't very selective — although Google certainly tries. I see this with my own website: there's a single line in my pancake recipe that describes the appropriate time to flip a pancake, and it regularly turns up highly ranked for the search term "pancake flipping." I can only imagine that the people who search for that term want to learn how to flip a pancake, not when. None of them have clicked through to my recipe.

I've recently noticed a change in my own browsing habits: when I want to learn about something, I don't go to Google first. Instead, I turn to Wikipedia. This in itself isn't unusual: lots of people turn to Wikipedia for a summary view of a topic. What is unusual is that, after reading the entry, I start clicking on the footnote links.

This makes sense: these links are selected by the people editing the article, as authoritative references to the subject. They are almost guaranteed to be the best, most relevant links for that topic.

All of which reminds me a lot of 1994, except the index has moved out of the dorm room.

Thursday, February 5, 2009

Mental Models

In Java, an anonymous inner class is permitted to reference the variables and parameters defined by its enclosing method — but only if they're declared as final. For example, the Runnable below can use foo1, but not foo2:

public Runnable prepareOperation(final Foo obj1)
{
    Foo foo2 = // get another instance
    return new Runnable()
    {
        public void run()
        {
            // do something
        }
    };
}

Why the restriction? The JLS simply says that it exists. The Inner Classes Specification (which only appears to exist as part of the JDK 1.1.8 documentation set) requires that “the same value is produced everywhere, so that the name consistently appears to refer to the same variable in all parts of its scope,“ but doesn't give a rationale.

Certainly there's no physical reason for this requirement: the inner class can't hold an actual pointer into the method's stack frame. Indeed, the specification goes on to describe the mechanism that's actually used: the local variable is passed to the inner class constructor, so the inner class holds its own copy. Given that, the local variable could change without affecting the copy held by the class, and vice-versa.

But doing so would break the mental model of Java variables. On the one hand, there's the idea that local variables and member variables are equivalent in every way but scope. On the other, the idea that an inner class has the ability to change the member variables in its enclosing instance, and those changes will be seen by the enclosing instance as well as the inner class.

But allowing the inner class to change its copy of an enclosing method's local variable, without propagating that change to the enclosing method, would subtly break that model. Requiring the local variables to be declared final preserves the model at the cost of a needless bit of syntax. Is it that important?

To answer that, I'll ask a different question: have you ever climbed a staircase where one stair was not quite the same height as the others? Did you notice it? Did you trip?

When approaching a staircase, you unconsciously build a mental model of that staircase, then use that model to place your feet while climbing. I recall reading that most people place their foot within 1/16 of an inch of the expected height. This mental model is so strong, and the consequences potentially so expensive, that the International Residential Code (excerpted at stairways.org) specifies no more than 3/8 inch variance between the shortest and tallest stairs in a flight — about the width of your smallest fingernail.

The mental models that we build for programming are equally strong. They cover everything: the syntax and semantics of the language, the flow of data and code, the order of method parameters, and the One True Brace Style™. When you program in an environment where the models are consistent, you don't have to expend mental energy remembering how something works. When the models are inconsistent, particularly the semantics of the language, it's like placing your foot a half inch above the stair tread.