• The Old New Thing

    Google is the cute two-year-old girl with curly blond hair that gets all the attention

    • 85 Comments

    Let's see, Google Maps adds the world outside the United States, Canada and the UK, and people go ga-ga. Nevermind that Google's new "maps" have nothing beyond country boundaries. "Aww, look at Google, she's so cute and adorable!"

    I'm sure the people at the existing online map services like MapQuest and MSN MapPoint are sitting there like older siblings, wondering when exactly they turned into chopped liver. MSN MapPoint has actual maps of most of Europe, and MapQuest's library of maps is larger still. (Kathmandu anyone?) Both sites provide documentation on how to link directly to them. Yet they don't get drooled over.

    Somebody at MapQuest should take out a full page ad that goes something like this:

    Dear Google Maps,

    Welcome to the rest of the world! If you ever need driving directions, don't hesitate to ask.

    Love ever,
    MapQuest

  • The Old New Thing

    Solving one problem by creating a bigger problem

    • 84 Comments

    Often, people will not even realize that their solution to a problem merely replaces it with another problem. The quip attributed to Jamie Zawinski captures the sentiment:

    Some people, when confronted with a problem, think "I know, I'll use regular expressions." Now they have two problems.

    For example, in response to "How do I write a batch file that..." some people will say, "First, install <perl|bash|monad|...>". This doesn't actually solve the problem; it merely replaces it with a different problem.

    In particular, if the solution begins with "First, install..." you've pretty much lost out of the gate. Solving a five-minute problem by taking a half hour to download and install a program is a net loss. In a corporate environment, adding a program to a deployment is extraordinarily expensive. You have to work with your company's legal team to make sure the licensing terms for the new program are acceptable and do not create undue risk from a legal standpoint. What is your plan of action if the new program stops working, and your company starts losing tens of thousands of dollars a day? You have to do interoperability testing to make sure the new program doesn't conflict with the other programs in the deployment. (In the non-corporate case, you still run the risk that the new program will conflict with one of your existing programs.)

    Second, many of these "solutions" require that you abandon your partial solution so far and rewrite it in the new model. If you've invested years in tweaking a batch file and you just need one more thing to get that new feature working, and somebody says, "Oh, what you need to do is throw away you batch file and start over in this new language," you're unlikely to take up that suggestion.

    So be careful when you suggest a solution that has a high activation energy. Sure, something could be taken care of by a one-line perl script, but getting perl onto the machine is hardly a one-line endeavor.

  • The Old New Thing

    Cleaner, more elegant, and wrong

    • 84 Comments

    Just because you can't see the error path doesn't mean it doesn't exist.

    Here's a snippet from a book on C# programming, taken from the chapter on how great exceptions are.

    try {
      AccessDatabase accessDb = new AccessDatabase();
      accessDb.GenerateDatabase();
    } catch (Exception e) {
      // Inspect caught exception
    }
    
    public void GenerateDatabase()
    {
      CreatePhysicalDatabase();
      CreateTables();
      CreateIndexes();
    }
    
    Notice how much cleaner and more elegant [this] solution is.

    Cleaner, more elegant, and wrong.

    Suppose an exception is thrown during CreateIndexes(). The GenerateDatabase() function doesn't catch it, so the error is thrown back out to the caller, where it is caught.

    But when the exception left GenerateDatabase(), important information was lost: The state of the database creation. The code that catches the exception doesn't know which step in database creation failed. Does it need to delete the indexes? Does it need to delete the tables? Does it need to delete the physical database? It doesn't know.

    So if there is a problem creating CreateIndexes(), you leak a physical database file and a table forever. (Since these are presumably files on disk, they hang around indefinitely.)

    Writing correct code in the exception-throwing model is in a sense harder than in an error-code model, since anything can fail, and you have to be ready for it. In an error-code model, it's obvious when you have to check for errors: When you get an error code. In an exception model, you just have to know that errors can occur anywhere.

    In other words, in an error-code model, it is obvious when somebody failed to handle an error: They didn't check the error code. But in an exception-throwing model, it is not obvious from looking at the code whether somebody handled the error, since the error is not explicit.

    Consider the following:

    Guy AddNewGuy(string name)
    {
     Guy guy = new Guy(name);
     AddToLeague(guy);
     guy.Team = ChooseRandomTeam();
     return guy;
    }
    

    This function creates a new Guy, adds him to the league, and assigns him to a team randomly. How can this be simpler?

    Remember: Every line is a possible error.

    What if an exception is thrown by "new Guy(name)"?

    Well, fortunately, we haven't yet started doing anything, so no harm done.

    What if an exception is thrown by "AddToLeague(guy)"?

    The "guy" we created will be abandoned, but the GC will clean that up.

    What if an exception is thrown by "guy.Team = ChooseRandomTeam()"?

    Uh-oh, now we're in trouble. We already added the guy to the league. If somebody catches this exception, they're going to find a guy in the league who doesn't belong to any team. If there's some code that walks through all the members of the league and uses the guy.Team member, they're going to take a NullReferenceException since guy.Team isn't initialized yet.

    When you're writing code, do you think about what the consequences of an exception would be if it were raised by each line of code? You have to do this if you intend to write correct code.

    Okay, so how to fix this? Reorder the operations.

    Guy AddNewGuy(string name)
    {
     Guy guy = new Guy(name);
     guy.Team = ChooseRandomTeam();
     AddToLeague(guy);
     return guy;
    }
    

    This seemingly insignificant change has a big effect on error recovery. By delaying the commitment of the data (adding the guy to the league), any exceptions taken during the construction of the guy do not have any lasting effect. All that happens is that a partly-constructed guy gets abandoned and eventually gets cleaned up by GC.

    General design principle: Don't commit data until they are ready.

    Of course, this example was rather simple since the steps in setting up the guy had no side-effects. If something went wrong during set-up, we could just abandon the guy and let the GC handle the cleanup.

    In the real world, things are a lot messier. Consider the following:

    Guy AddNewGuy(string name)
    {
     Guy guy = new Guy(name);
     guy.Team = ChooseRandomTeam();
     guy.Team.Add(guy);
     AddToLeague(guy);
     return guy;
    }
    

    This does the same thing as our corrected function, except that somebody decided that it would be more efficient if each team kept a list of members, so you have to add yourself to the team you intend to join. What consequences does this have on the function's correctness?

  • The Old New Thing

    At last you can turn off the USB 2.0 balloon

    • 84 Comments

    One of the more annoying messages in Windows XP¹ is the "This USB device can perform faster" balloon that appears whenever you plug in a USB 2.0-capable device into a USB 1.0 port. When I click on that balooon, I get a message that says, "Sorry, you don't have any USB 2.0 ports. You'll have to install one to be able to take full advantage of this device."²

    Yeah, that's really nice, but one of my machines is a laptop, so its USB ports can't be upgraded. And my desktop computer at the time had an older motherboard that predated USB 2.0. The really annoying part was that there was no way to turn off the balloon. "Yes, I know I inserted the device into a USB 1.0 port, but this computer doesn't have any USB 2.0 ports, so stop bugging me already."

    It actually got the point that I went out and bought a USB 2.0 adapter card just to shut up the stupid balloon.³

    Thank goodness that in Windows Vista, the USB folks realized how annoying it is to show a balloon that yells at you for something you can't do anything about, and they added a way to disable the pop-up.

    Nitpicker's Corner

    ¹Although this statement takes the grammatical form of a statement of fact, it is actually a statement of opinion. Other people may legitimately disagree with this opinion. Whether the message is in fact "one of the more annoying messages in Windows XP" is irrelevant to the story; the employment of this statement of opinion is rhetorical and serves a useful storytelling purpose, namely to serve as an interesting introduction and to establish a context for elaboration. It does not establish the official position of Microsoft Corporation regarding how annoying that message is.

    ²That is not literally what the message says, but the underlying meaning is comparable. The message text has been paraphrased for rhetorical purposes (to create a more informal tone) and for time-saving purposes (to save me the trouble of having to re-create the message and carefully transcribe the message word-for-word).

    ³Again, the use of the word "stupid" here is rhetorical, indicating my level of frustration and not attempting to establish the official Microsoft position on the intelligence of the balloon or the people responsible for it.

  • The Old New Thing

    Engineering is about tradeoffs: How hard will you work to save 68KB of disk space?

    • 84 Comments

    One of the recurring themes in the comments to my explanation of the historical reasons why there are two copies of Notepad was to use a hard link (or possibly a symbolic link) to save having to waste the disk space for two whole copies of Notepad. As I like to say, engineering is about tradeoffs. Let's look at the cost-benefit analysis.

    On the one hand: Install two copies of Notepad. Cost: 68KB of disk space.

    On the other hand: Use hard links or symbolic links. Cost: Add support for hard links or symbolic links to the FAT filesystem, to the operating system Setup program, to file formats such as the Windows Imaging Format, and to the various disk duplication systems that system builders (and corporate customers) use for deploying Windows to thousands of machines. Don't forget to count the cost for design and testing.

    Imagine you're the scheduling manager for the Setup team. Which of these two options do you choose? 68KB of disk space or doing all the work to support hard links during Setup and then waiting for all the existing customers to upgrade their tools to versions which support hard links—which could take several years. Are you going to be the one to have to stand up in the Ship Room and say, "We can't ship Windows because ten of our customers hasn't upgraded their deployment tools yet, and I have no idea how long we're going to have to wait until they do"?

    And for those commenters who said that Windows should just get rid of one of the copies, you'll be pleased to know that Windows Server 2008 got rid of the copy in the Windows directory. There is now only one copy¹ of Notepad, and it's the one in the system32 directory. It wasn't long after the product was released that I learned of a program that hard-coded the one that no longer exists; I wish the vendors good luck in getting a patch out quickly.

    Footnotes

    ¹Nitpickers not welcome here. There is only one copy remaining of the two under discussion.

  • The Old New Thing

    When visitors to the United States underestimate the size of the country

    • 84 Comments

    A friend of mine who is from Lebanon (but now lives in Seattle) invited his grandmother to come visit for the summer. When she arrived, he asked her, "Grandma, is there anywhere in particular you would like to visit?"

    His grandmother replied, "I'd like go to to Washington, DC."

    "Okay, Grandma. Let me buy some plane tickets."

    "No, let's drive."

    "You want to drive all the way to Washington, DC? Here, let me show you on a map how far away it is."

    Grandma replied, "Let's do it."

    My friend said, "Okay, Grandma, we're going on a road trip!" He got the rest of the family on board with the plan, packed up the car, and set out early one morning for their cross-country trip.

    By the end of the day, they had made it as far as Idaho, where they stopped for the night. I assume that they made plenty of stops along the way because (1) part of the point of a road trip is to enjoy the things along the way, and (2) Grandma.

    Grandma asked, "Is this Washington, DC?"

    "No, Grandma. Washington, DC is still very far away. Here, let me show you on the map where we are."

    Grandma was unconvinced. "If you'd only stop and ask for directions, we would have been there by now." Grandma was certain that the only reason they were driving all day was that her grandson was lost and stupidly driving in circles, and if he only had driven in the right direction, they'd be there by now.

    Grandma's reference for distance was Lebanon, which is a relatively small country. You can drive from the northern tip of the country to the southern tip in a day. The United States is a bit bigger than that.

    A related story was when my parents in New Jersey hosted some friends from Japan. The first excursion they took was to New York City, a convenient train ride away. For their second trip, they said, "How about today we drive to Chicago?"

    Third story.

    Please share any funny stories about geographic blindness in your home country.

    (This was supposed to be posted on Geography Awareness Week but I messed up.)

  • The Old New Thing

    The importance of error code backwards compatibility

    • 83 Comments

    I remember a bug report that came on in an old MS-DOS program (from a company that is still in business so don't ask me to identify them) that attempted to open the file "". That's the file with no name.

    This returned error 2 (file not found). But the program didn't check the error code and though that 2 was the file handle. It then began writing data to handle 2, which ended up going to the screen because handle 2 is the standard error handle, which by default goes to the screen.

    It so happened that this program wanted to print the message to the screen anyway.

    In other words, this program worked completely by accident.

    Due to various changes to the installable file system in Windows 95, the error code for attempting to open the null file changed from 2 (file not found) to 3 (path not found) as a side-effect.

    Watch what happens.

    The program tries to open the file "". Now it gets error 3 back. It mistakenly treats the 3 as a file handle and writes to it.

    What is handle 3?

    The standard MS-DOS file handles are as follows:

    handle name meaning
    0stdinstandard input
    1stdoutstandard output
    2stderrstandard error
    3stdauxstandard auxiliary (serial port)
    4stdprnstandard printer

    What happens when the program writes to handle 3?

    It tries to write to the serial port.

    Most computers don't have anything hooked up to the serial port. The write hangs.

    Result: Dead program.

    The file system folks had to tweak their parameter validation so they returned error 2 in this case.

  • The Old New Thing

    I drive a car the way most people use a computer

    • 82 Comments

    It was interesting to me reading the reactions to my adventures driving a manual transmission. People seemed to be spending a lot of time trying to convince me that if only I were to expend a bit more effort in learning the finer points of driving a manual transmission and log enough time behind the wheel, then the activity will become less taxing on my mental brainpower.

    But why should I care?

    To me, driving is not an end in itself. It is just a tool for solving the problem of getting from point A to point B. The less I have to learn about how to accomplish this task the better.

    My goal is not to become a car expert. My goal is to get to my destination conveniently. I don't want to "have greater control over the experience"; I don't want "more power"; heck, depending on where I'm going, I often prefer to take the bus, where I have no control over the experience at all!

    It occurred to me as I read commenter after commenter try to convince me that my own personal priorities were incorrect that I drive a car the same way most people use a computer. They don't want to know about the difference between ROM and RAM or how many floppy disks you can store in a 6 megabit cable modem. They just want to surf the web, send email, and look at pictures of their grandchildren. (Okay, they may want to do other stuff too, but knowing the difference between PIO and DMA is definitely not on the list.)

    There's no point trying to get these people to learn all these details about how computers work because they don't care. They just want to know where they need to click to see that picture of baby Annie. You can even tell them that the way they're doing it is suboptimal and there's a much more powerful way to view those pictures which also gives them the ability to alter the gamma curve and apply the correct color adjustment to the image to match their monitor's color temperature, but they won't care.

    And I don't blame them. Because I don't care either.

  • The Old New Thing

    The history of the Windows PowerToys

    • 81 Comments

    During the development of Windows 95, as with the development of any project, the people working on the project write side programs to test the features they are adding or to prototype a feature. After Windows 95 shipped, some of those programs were collected into the first edition of the Windows 95 Power Toys.

    As I recall, the first edition contained the following toys:

    CabView
    This was a handy internal tool which also served as a test of the shell folder design.

    CDAutoPlay, DeskMenu, FlexiCD, QuickRes
    These were side toys originally written by shell developers for their own personal use.

    Command Prompt Here, Explore From Here
    These were proof-of-concept toys which tested the shell command extension design.

    Round Clock
    This was a program to test regional windows.

    Shortcut Target Menu
    This was a feature idea that didn't quite make it.

    I wasn't around when the decision was made to package these toys up and ship them, so I don't know what the rule was for deciding what was PowerToy-worthy and what wasn't. Nor do I know where the name PowerToy came from. (Probably somebody just made it up because it sounded neat.)

    Upon the enormous success of the PowerToys, a second edition was developed. This time, people knew that they were writing a PowerToy, as opposed to the first edition of the PowerToys which was merely cobbled together from stuff lying around. The second edition of the Windows 95 PowerToys added FindX, Send To X, the Telephony Locator Selector, XMouse, and Tweak UI.

    Later, the kernel team released their own set of toys, known as the Windows 95 Kernel Toys. Alas, the original blurb text is not on the Microsoft downloads site, but here's an archived copy. (In reality, it was I who wrote all of the Kernel Toys, except for the Time Zone Editor, which came from the Windows NT Resource Kit. I also wrote the somewhat whimsical original blurb.)

    This was all back in the day when it was easy to put up something for download. No digital signatures, no virus checking, no paperwork. Just throw it up there and watch what happens. Today, things are very different. Putting something up for download is a complicated process with forms to fill out in triplicate and dark rooms with card readers. I wouldn't be surprised if an abandoned salt mine in Montana were somehow involved.

    Nowadays, every team at Microsoft seems to have their own PowerToys, trading on the good name of the Windows shell team who invented the whole PowerToys idea. (As far as I can tell, we don't get any royalties from other divisions calling their toys "PowerToys".) A quick check reveals the following PowerToys available for download from Microsoft; I may have missed some.

    (Plus, of course, the Windows XP PowerToys, which does come from the shell team. The Internet Explorer team originally called their stuff PowerToys, but they later changed the name to Web Accessories, perhaps to avoid the very confusion I'm discussing here.)

    What's frustrating is that since they are all called "PowerToys", questions about them tend to go to the shell team, since we are the ones who invented PowerToys. We frequently have to reply, "Oh, no, you're having a problem with the XYZ PowerToys, not the classic Windows PowerToys. We're the folks who do the classic Windows PowerToys."

    Even the blog name "PowerToys" has been co-opted by the Visual Studio team to promote their Powertoys for Visual Studio 2003.

    Some people claim that Tweak UI was written because Microsoft got tired of responding to customer complaints. I don't know where they got that from. Tweak UI was written because I felt like writing it.

    That page also says that sometimes PowerToys vanish without warning. That's true. A few years ago, all the Windows XP PowerToys were taken down so they could be given a security review. Some of them didn't survive and didn't come back. Other times, a PowerToy will be pulled because a serious bug was found. Since PowerToys are spare-time projects, it can take a very long time for a bug to get fixed, tested, and re-published. For example, the HTML Slide Show Wizard was pulled after a (somewhat obscure) data-loss bug was found. Fixing the bug itself took just a few days, but testing and filling out all the associated paperwork took six months.

    There's no moral to this story. Just a quick history lesson.

  • The Old New Thing

    People lie on surveys and focus groups, often unwittingly

    • 81 Comments

    Philip Su's discussion of early versions of Microsoft Money triggered a topic that had been sitting in the back of my mind for a while: That people lie on surveys and focus groups, often unwittingly. I can think of three types of lies offhand. (I'm not counting malicious lying; that is, intentional lying for the purpose of undermining the results of the survey or focus group.)

    First, people lie about the reasons why they do things.

    The majority of consumers who buy computers claim that personal finance management is one of the top three reasons they are purchasing a PC. They've been claiming this for more than a decade. But only somewhere around 2% of consumers end up using a personal finance manager.

    This is one of those unconscious lies. People claim that they want a computer to do their personal finances, to organize their recipes, to mail-merge their Christmas card labels.

    They are lying.

    Those are the things people wish they would use their computer for. That's before the reality hits them of how much work it is to track every expenditure, transcribe every recipe, type in every address. In reality, they end up using the computer to play video games, surf the web, and email jokes to each other.

    Just because people say they would do something doesn't mean they will. That leads to the second class of focus group lying: The polite lie, also known as "say what the sponsor wants to hear".

    The following story is true, but the names have been changed.

    A company conducted focus groups for their Product X, which had as its main competitor Product Q. They asked people who were using Product Q, "Why do you use Product Q instead of Product X?" The respondents gave their reasons: "Because Product Q has feature F," "Because Product Q performs G faster," "Because Product Q lets me do activity H." They added, "If Product X did all that and was cheaper, we'd switch to it."

    Armed with this valuable insight, the company expended time, effort, and money in adding feature F to Product X, making Product X do G faster, and adding the ability to do activity H. They lowered the price and sat back and waited for the customers to beat a path to their door.

    But the customers didn't come.

    Why not?

    Because the customers were lying. In reality, they had no intention of switching from Product Q to Product X at all. They grew up with Product Q, they were used to the way Product Q worked, they simply liked Product Q. Product Q had what in the hot bubble-days was called "mindshare", but what in older days was called "brand loyalty" or just "inertia".

    When asked to justify why they preferred Product Q, the people in the focus group couldn't say, "I don't know; I just like it." That would be perceived as an "unhelpful" answer, and besides it would be subconsciously admitting that they were being manipulated by Product Q's marketing! Instead, they made up reasons to justify their preference to themselves and consequently to the sponsor of the focus group.

    Result: Company wastes tremendous effort on the wrong thing.

    (Closely related to this is the phenomenon of saying—and even believing—"I'd pay ten bucks for that!" Yet when the opportunity arises to buy it for $10, you decline. I do this myself.)

    The third example of lying that occurred to me is the one where you don't even realize that you are contradicting yourself. My favorite example of this was a poll on the subject of congestion charging on highways in the United States. The idea behind congestion charging is to create a toll road and vary the cost of driving on the road depending on how heavy traffic is. Respondents were asked two questions:

    1. "If congestion charging were implemented in your area, do you think it would reduce traffic congestion?"
    2. "If congestion charging were implemented in your area, would you be less likely to drive during peak traffic hours?"

    Surprisingly, most people answered "No" to the first question and "Yes" to the second. But if you stop and think about it, if people avoid driving during peak traffic hours, then congestion would be reduced because there are fewer cars on the road. An answer of "Yes" to the second question logically implies an answer of "Yes" to the first question.

    (One may be able to explain this by arguing that, "Well, sure congestion charging would be effective for influencing my driving behavior, but I don't see how it would affect enough other people to make it worthwhile. I'm special." Sort of how most people rate themselves as above-average drivers.)

    What I believe happened was that people reacted by saying to themselves, "I am opposed to congestion charging," and concluding, "Therefore, I must do what I can to prevent it from happening." Proclaiming on surveys that it would never work is one way of accomplishing this.

    When I shared my brilliant theories with some of my colleagues, one of them, a program manager on the Office team, added his own observation (which I have edited slightly):

    A variation of two of the above observations that often shows up in the usability lab:

    A user has spent an hour battling with the software. At some point the user's expectation of how the software should behave (the "user model") diverged from the actual behavior. Consequently, the user couldn't predict what will happen next and is therefore having a horrible time making any progress on the task. (Usually, this is the fault of the software design unintentionally misleading the user—which is why we test things.) After many painful attempts, the user finally succeeds, gets hints, or is flat-out told how the feature works. Often, the user stares mutely at the monitor for five seconds, then says: "I suppose that makes sense."

    It's an odd combination of people wanting to give a helpful answer with people wanting to feel special. In this case, the user wants to say something nice about the software that any outside observer could clearly tell was broken. Additionally, the users (subconsciously) don't want to admit that they were wrong and don't understand the software.

    Usability participants also have a tendency to say "I'm being stupid" when those of us on the other side of the one-way glass are screaming "No you're not, the software is broken!" That's an interesting contrast—in some cases, pleading ignorance is a defense. In other cases, pleading mastery is. At the end of the day, you must ignore what the user said and base any conclusions on what they did.

    I'm sure there are other ways people subconsciously lie on surveys and focus groups, but those are the ones that came to mind.

    [Insignificant typos fixed, October 13.]

Page 6 of 419 (4,182 items) «45678»