May, 2009

  • The Old New Thing

    Microspeak: T-shirt sizing

    • 16 Comments

    Larry Osterman discussed the buzzword T-shirt sizing, which means "making extremely rough estimates in terms of a small number of predefined categories." The term comes from the traditional way T-shirt sizes are specified in the United States. Instead of having T-shirts in sizes 4, 5, 6 and so on, there are only a small number of sizes: Small, medium, large, and extra-large. (Sometimes augmented by extra-small, extra-extra-large, etc.)

    Forcing the estimate into one of a fixed set of sizes allows the process to go quickly while still producing a result that is at least within the same zip code as a more detailed answer. The idea is not to pin down the schedule precisely but rather to get a back-of-the-envelope feel for whether a project is a two-week project, a two-month project, or a two-year project.

    The size breakdowns vary depending on the scope of the project. For a small project, small might mean "less than a day", whereas for a large project, small might mean "less than a week". People can usually come up with a gut feeling as to whether something will take "less than a week" much more quickly than they can say whether something will take one day, two days, or three days.

    As the concept of T-shirt sizing spread through Microsoft, it inevitably became the source of a new set of derived jargon. I've seen T-shirt costing on a meeting agenda. Though thankfully I have yet to see T-shirting.

  • The Old New Thing

    How do I get a window back on the screen when it moved far, far away?

    • 63 Comments

    Commenter Aggravated notes that some programs remember their location when the window is closed and restore to that location when the window is reopened, even if that position is off the screen. These programs clearly were using screen coordinates instead of workspace coordinates to save and restore the window.

    Okay, so you've got a program that restored its window position incorrectly and ended up putting it off the screen. Now what do you do?

    The keyboard interface comes to the rescue.

    Switch to the application, say by clicking on its taskbar button or by Alt+Tab'ing to it. Then type Alt+Space to call up the System menu: You should get a window floating at the edge of the screen. Type M to select Move, then press an arrow key to enter Move mode. (Doesn't matter which.)

    At this point, you could stick with the keyboard motif and hold down the appropriate arrow key to move the window back onto the screen. Or you can pull a little magic trick: Wave the mouse around. Boom, the window leaps to the mouse like one of those cheapo magic tricks where something leaps into your hand.

    I'm like 95% sure they use string. But it could be magic. No, I'm going with the string.

  • The Old New Thing

    Writing a sort comparison function, redux

    • 47 Comments

    Prerequisites: Experience with sort functions such as qsort.

    Overqualifications: Familiarity with sort algorithms.

    If you break the rules for sort comparison functions, then don't expect the result of a sort call to be meaningful. In fact, if you really mess it up, you can corrupt memory or go into an infinite loop.

    My program hangs when I used this sort comparison function (pseudocode):

    int compare(x, y)
    {
     return x >y ? +1 : -1;
    }
    

    What's even more strange is that sometimes instead of hanging, the program crashes. It all works correctly if I add one line:

    int compare2(x, y)
    {
     if (x == y) return 0; // added
     return x >y ? +1 : -1;
    }
    

    What's going on? The array I am sorting contains no duplicate elements, so the two items x and y should never be equal.

    First of all, your first comparison function clearly violates the requirements for being a comparison function: It must return zero if the two items compare equal. As a result, the behavior is undefined, and hanging, crashing, or returning an incorrect result are all legitimate behavior.

    But let's dig a little deeper to see why hanging and crashing are plausible responses to an invalid sort comparison function.

    A common sorting algorithm is quicksort. I'll leave you to go off and learn on your own how the quicksort algorithm works. Come back when you're done.

    Okay, welcome back. The central step in quicksort is the partition, and some variants of the quicksort algorithm rely on the partition element comparing equal to itself in order to remove a comparison from the inner loop. For example, an index may walk through the array looking for an element greater than or equal to the partition, fully expecting at least one such element to be found because in the worst case, it will find the partition itself. But if your comparison function fails to report the partition as equal to itself, this search may run off the end of the array and eventually crash with an access violation when it reaches invalid memory.

    That explains the crash, but what about the hang? Well, notice that the comparison function is also inconsistent. In particular, the anti-symmetry rule is violated: compare(x, y) and compare(y, x) return the same value (as opposed to the opposite value) if x==y. The function returns -1 both times, saying "x is less than y" and "y is less than x" simultaneously. This inconsistency can easily send a sort algorithm running back and forth trying to find the right place for the partition.

    The moral of the story is the same: Your comparison function must meet the criteria for a proper comparison function. If you fail to do this, then the results you get will be very strange indeed.

  • The Old New Thing

    A puzzle: Why are so many fake LiveJournal blogs written by 29-year-olds?

    • 32 Comments

    NPR's All Tech Considered blog notices a huge spike of LiveJournal users who claim to be 29 years old. They conclude (almost certainly correctly) that these are all fake journals created by spam bots. But why 29 years old?

    One possible answer.

  • The Old New Thing

    When you subclass a window, it's the original window procedure of the window you subclass you have to call when you want to call the original window procedure

    • 23 Comments

    When you subclass a window, you set the window procedure to a function of your choosing, and you remember the original window procedure so you can pass it to the CallWindowProc function when your subclass function wants to pass the message to the original window procedure. For example, if you subclass a window like this:

    SubclassWidgetDialog(HWND hdlgWidget)
    {
      HWND hwndButton = GetDlgItem(hdlgWidget, ...);
      wndProcOrig = (WNDPROC)
         SetWindowLongPtr(hwndButton, GWLP_WNDPROC, (LONG_PTR)SubclassWndProc);
      // -or-
      // wndprocOrig = SubclassWindow(hwndButton, SubclassWndProc);
      ...
    }
    

    then your subclass function should go something like this:

    LRESULT CALLBACK SubclassWndProc(
        HWND hwnd, UINT wm, WPARAM wParam, LPARAM lParam)
    {
      switch (wm) {
      ...
      default:
        return CallWindowProc(wndprocOrig, hwnd, wm, wParam, lParam);
      }
    }
    

    The window procedure you pass to CallWindowProc is the one which was the window procedure of that window before you subclassed it, not the window procedure from some other window. In the same way that when you create a derived C++ class, you pass method calls along to your base class, not to somebody else's base class:

    class DerivedClass : public BaseClass {
     ...
     // override base class: do some extra stuff
     int Method(int param)
     {
      ExtraDerivedStuff();
      return BaseClass::Method(param);
     }
    };
    

    When you are finished with your customization in DerivedClass::Method, you let the base class do what normally would have happened if you hadn't overridden the method in the first place by calling BaseClass::Method and not by calling SomeOtherClass:Method.

    This sounds blatantly obvious, but you'd be surprised how often people mess this up. For example, if you subclass multiple widget dialogs, you have to save the old window procedure in a different place for each one, because each button may have had a different window procedure by the time you got around to subclassing it. For example, one of them might be a plain button, whereas another of them was subclassed in order to provide a tooltip. If you make wndprocOrig a global or static variable, then you're assuming that every widget button has the same window procedure. You are subclassing a window and forgetting to handle the case where the window is already subclassed! You forgot that somebody else could have done exactly what you're doing.

    There is a popular commercial program that comes preinstalled on many computers which creates a common file open dialog box and subclasses both the file name combo box and the file type combo box, and figures that, well, since they're both combo boxes, they must have the same window procedure, right? Unfortunately, there's no guarantee that they do, because the common file dialog is free to subclass them in order to provide custom behavior like autocomplete. It so happens that the program grabs the window procedure from the subclassed combo box window and uses it for all combo boxes. (These are probably the same folks who would have called the BOZOSLIVEHERE function if given the chance.)

    This makes for very exciting crashes when they take the original window procedure from the subclassed combo box and use it for the other, unsubclassed, combo box. The subclass window procedure finds itself handed a window that it never subclassed. As a result, it not only can't perform its own subclass behavior, but can't even just fall back and say "Well, I can't do my custom stuff, so I'll just forward to the original window procedure" since it can't figure out what the original window procedure was either. It's the window manager version of writing this strange C++ code:

    class SiblingClass : public BaseClass { ... };
    class DerivedClass : public BaseClass {
     ...
     // override base class: do some extra stuff
     // then pass method to the WRONG base class
     int Method(int param)
     {
      ExtraDerivedStuff();
      return ((SiblingClass*)this)->Method(param);
     }
    };
    

    When you subclass a window, and you want to call the original window procedure, make sure you call the correct original window procedure: The one that was the window procedure of that window before you subclassed it.

  • The Old New Thing

    You can tell which people listed blogging as a performance review goal

    • 36 Comments

    I had been kind of baffled by some of the Microsoft employee blogs that appear to consist almost entirely of rehashes of Knowledge Base articles, or sometimes even just "A new Knowledge Base article on topic X has been published." Now, that's useful information to have if you're interested in topic X, but is it really something you can build a blog around? Can't you just sign up for KB notifications manually? (That's probably how the blog author found them anyway.) And then there are the head-scratcher blog entries like There are no new KB articles this week.

    But I never really thought too much about them. They merely registered as noise to me. Baffling noise, but still noise.

    And then I learned why these types of blogs exist: Because somebody put down blogging as a goal on their annual performance review. If you want to say that one of your goals for the next year is to maintain a blog, you have to specify how to determine whether that goal was met. As I've noted earlier, Microsoft is obsessed with measurement, so the way to tell whether your blog was a "success" is to come up with some sort of metric for success. These people naturally chose Number of blog postings per month as their metric. Running behind this month? No problem, just crank out a few Hey, here's a Knowledge Base article you might be interested in postings and you've filled your quota.

    This is another example how deciding how you're going to measure something affects the people you're measuring: They alter their behavior to maximize the metric rather than the concept the metric is supposed to be tracking. If you decide that you want to expand the Knowledge Base and set numeric goals for employees on how many Knowledge Base articles they should write each year, don't be surprised if you find that in the waning weeks of the year, there's a spurt of largely useless Knowledge Base articles.

    In an internal discussion of this topic, I wrote, "Blogging to improve your review score is like entering politics to get rich." While it may be true that politicians tend to get rich, and many people enter politics in order to get rich (or more legally, enter politics in order to exit politics in order to get rich), I believe that getting rich shouldn't be the motivation for entering politics. And improving your review score shouldn't be the motivation for blogging.

  • The Old New Thing

    The social skills of a thermonuclear device: Why did you hang up?

    • 45 Comments

    One morning I'm working in my office and I'm interrupted by a telephone call. The caller-ID shows that it came in through the switchboard. (I.e., somebody called the main Microsoft number and asked for me by name.)

    Me: Hello?

    Caller: [angrily] Mr. Chen, why did you hang up?

    I don't recognize the voice, and I haven't received a phone call in several days, so I have no idea who this person is or what he's talking about. But if somebody starts out rude to me, that doesn't put me in the friendliest of moods. Still, I use a polite tone of voice.

    Me: Oh, I'm sorry. I'll do it again. [click]

    A few minutes later, my phone rang again. The caller-ID shows that it is once again a call from the switchboard. I let it go to voice mail.

    Shortly thereafter, I received a notification that I have a new voicemail message. Here's a transcript:

    [swearing in a language I don't recognize] Why do you keep hanging up on me? I asked you, are you Raymond Chen, and then I talk to you, and you hang up. Are you stupid or something? [click]

    Now I kind of feel bad that the caller probably got the wrong person. There are at least four people at Microsoft who share my name (or a name very similar to it).

  • The Old New Thing

    The dummy icon that doesn't know that its fifteen seconds are over

    • 17 Comments

    Commenter Myron A. Semack asks via the Suggestion Box why there is a hardware notification icon that doesn't do anything. This is the notification icon that is left behind if you dismiss the hardware notification balloon.

    I don't know, but I can figure it out based on information both you and I already know.

    First of all, notice that the only way to show a notification balloon is to associate it with a notification icon. After all, the tip of the balloon has to point to something. Therefore, it's not surprising that when the balloon shows up, a notification icon also appears. You can't display "just a balloon"; you have to attach the balloon to a notification icon, and if you don't have a notification icon, you'll just have to create a dummy icon to attach it to.

    Second, you already know that taskbar notification icons are not told when the user clicks the × to dismiss the balloon. If you dismiss the balloon with an ×, the dummy notification icon still hangs around because it doesn't know that it's just standing around for no reason.

    When you dismiss the balloon, you just leave the dummy icon behind, and the dummy icon is pretty dumb.

    You see this dummy icon in other places. For example, if there is a delayed-write failure or if the system needs to grow your pagefile, a balloon appears to let you know about the situation. These balloons are really error messages from the kernel, but repackaged to be less annoying. If you've used earlier versions of Windows NT, you'll remember that these messages used to be in-your-face pop-up message boxes. The kernel folks agreed to add an option (on by default) to auto-convert annoying pop-up message boxes to balloons. But all message boxes can do is show some text and collect a response. They don't have a customizable right-click context menu or a tooltip, so there's nothing to attach to those behaviors when they are auto-converted to a balloon.

    I guess clicking on the dummy icon could redisplay the balloon. That would at least make it slightly less dumb.

    Update: Commenter John points out that my memory of how balloons are dismissed is incorrect, once again demonstrating that this Web site is for entertainment purposes only.

  • The Old New Thing

    When advanced users outsmart themselves: The device removal notification icon

    • 135 Comments

    A customer submitted a suggestion to the user interface team about the device removal notification icon.

    The device removal notification icon is far too hard to use. When I click on it, I get a menu that says Safely Remove Hardware, and when I click on that menu item, I get a dialog box that lists all the removable devices, with vague names like USB Mass Storage Device and propeller-beanie details like Connected on Port 0006, Hub 0004. When I click the Display device components check box, I'm presented with a tree view of hardware devices that only a geek could love.

    This is far too complicated. When I click on the device removal notification icon, I expected to get a simple menu that listed the devices that could be removed in an easy-to-identify manner, such as USB Mass Storage Device on Drive E:. Please consider making this improvement in the next version of Windows.

    Um, actually, that menu you are describing is already there, on the left click menu. Because, according to the traditional rules for notification icons (and the device removal icon was written back in Windows 95, when the traditional rules were operative), left clicking gives you the simple menu and right clicking gives you the advanced menu. This customer was so accustomed to right-clicking on notification icons that the idea of left-clicking never even occurred to him.

    When I tell this story to other advanced users, I often get the same reaction: "What? You can left-click on that thing and it does something different from right clicking? Dude, why didn't anybody tell me this? I've been doing it the hard way all this time!"

    I find this story interesting for a few reasons. First, it shows that differentiating the left click from the right click on notification icons as a way to determine whether to show the simple menu or the advanced menu is now obsolete. Just show the same menu for either click, because users (and these are advanced users, mind you, not just novices) don't even realize that a left click and a right click are different operations at all! And second, it highlights the ineffectiveness of having an Expert mode. These were all advanced users. If there were an Expert setting, they would have set it. And then they not only would have found themselves having to micro-manage the process of removing hardware devices, but also would have asked for a feature that was the same as restoring the novice UI.

    Update: Remember, this is part three of a series. Don't forget to read the other two parts.

Page 3 of 3 (29 items) 123