January, 2008

  • The Old New Thing

    No matter where you put an advanced setting, somebody will tell you that you are an idiot


    There are advanced settings in Windows, settings which normal users not only shouldn't be messing with, but which they arguably shouldn't even know about, because that would give them just enough knowledge to be dangerous. And no matter where you put that advanced setting, somebody will tell you that you are an idiot.

    Here they are on an approximate scale. If you dig through the comments on this blog, you can probably find every single position represented somewhere.

    1. It's okay if the setting is hidden behind a registry key. I know how to set it myself.
    2. I don't want to mess with the registry. Put the setting in a configuration file that I pass to the installer.
    3. I don't want to write a configuration file. The program should have an Advanced button that calls up a dialog which lets the user change the advanced setting.
    4. Every setting must be exposed in the user interface.
    5. Every setting must be exposed in the user interface by default. Don't make me call up the extended context menu.
    6. The first time the user does X, show users a dialog asking if they want to change the advanced setting.

    If you implement level N, people will demand that you implement level N+1. It doesn't stop until you reach the last step, which is aggressively user-hostile. (And then there will also be people who complain that you went too far.)

    From a technical standpoint, each of the above steps is about ten to a hundred times harder than the previous one. If you put it in a configuration file, you have to write code to load a parser and extract the value. If you want an Advanced button, now you have to write a dialog box (which is already a lot of work), consult with the usability and user assistance to come up with the correct wording for the setting, write help text, provide guidance to the translators, and now since it is exposed in the user interface, you need to write automated tests and add the setting to the test matrices. It's a huge amount of work to add a dialog box, work that could be spent on something that benefits a much larger set of customers in a more direct manner.

    That's why most advanced settings hang out at level 1 or, in the case of configuring program installation, level 2. If you're so much of a geek that you want to change these advanced settings, it probably won't kill you to fire up a text editor and write a little configuration file.


    Joel's count of "fifteen ways to shut down Windows" is a bit disingenuous, since he's counting six hardware affordances: "Four FN+key combinations... an on-off button... you can close the lid." Okay, fine, Joel, we'll play it your way. Your proposal to narrow it down to one "Bye" button, still leaves seven ways to shut down Windows.

    And then people will ask how to log off.

  • The Old New Thing

    In order to serve you better: Chase resets your marketing preferences


    Whenever a company says "In order to serve you better", you can be pretty sure they're about to do something that will make your life more miserable.

    This time, I'm going to call out Chase Financial Services, who recently sent out notices to customers who had specified that they did not want to receive marketing materials informing them that they now have greater control over which marketing materials they will receive, and the default is that they will receive everything. Strange, you'd think that if somebody said, "Don't send me marketing materials," then they probably meant "Don't send me marketing materials," and therefore that the translation of this into a "fine-grained control" is "no to everything." Because that's how they've interpreted it up until now anyway.

    Of course, the real reason they did this is to reset all their customer's preferences so they can start sending them advertising again. Notice that your opt-out choice must be renewed every five years. Hey, at least it's better than having to reiterate your preferences every three months like some companies require.

  • The Old New Thing

    Windows is not an MFC delivery channel


    Depending on what version of Windows you're running, there may be a variety of support DLLs for things that aren't formal product components, but which are merely along for the ride. For example, Windows 95 came with MFC30.DLL because the Fax Viewer was written with the help of MFC 3.0. But if you look at Windows 98, MFC30.DLL is gone.

    What happened?

    What happened is that Windows 98 didn't have a fax viewer that used MFC 3.0. The fact that some MFC 3.0 DLLs wound up on the machine with Windows 95 was merely a side effect of the implementation and not a part of the product specification. And in fact, if you chose not to install the Fax Viewer during Windows 95 setup, you wouldn't have gotten MFC30.DLL at all either, because MFC30.DLL wouldn't have been needed.

    We had a category of Windows 98 compatibility bugs from programs that assumed that MFC30.DLL was a contractual part of Windows. If the tester did a minimal install of Windows 95 and then installed the application, the application wouldn't run there either. The application vendor simply assumed that MFC was part of Windows, even though it wasn't. In other words, the program didn't work even on Windows 95. Is it a bug in Windows 98 if the program didn't work on Windows 95?

    This problem persists today. People go scrounging around the binaries that come with Windows looking for something they can remora. And then they're surprised when those binaries change or vanish entirely. For example, one customer had reverse-engineered the Kodak image viewer in Windows 2000 and wanted to keep using it in Windows XP. But those components are not included in Windows XP; the Kodak image viewer was merely a stopgap solution until the Windows XP fax and image viewer came along. (The linked Knowledge Base article has more information on that product.) I mention this because that customer, a Fortune 500 company, was trying to copy the files from Windows 2000 and install them onto a Windows XP machine and actually came to us asking for help in what may very well have been a violation of the Windows license agreement! (And certainly a violation of Microsoft's agreement with Kodak.)

    (I now predict that everybody will comment on the last two sentences and completely ignore the point of this article.)

  • The Old New Thing

    How does the calculator percent key work?


    The Windows calculator percent sign works the same way as those cheap pocket calculators (which are often called four-function calculators even though they have around six function nowadays). What you first have to understand is that the percent key on those pocket calculators was not designed for mathematicians and engineers. It was designed for your everyday person doing some simple calculations. Therefore, the behavior of the key to you, an engineer, seems bizarrely counter-intuitive and even buggy. But to an everyday person, it makes perfect sense. Or at least that's the theory.

    Let's look at it from the point of view of that everyday person. Suppose you want to compute how much a $72 sweater will cost after including 5% tax.¹ Pull out your handy pocket calculator² (or fire up Calc if you don't have a pocket calculator) and type

    72 + 5% =

    The result is 75.6, or $75.60, which is the correct answer, because 5% of 72 is 3.6. Add that to 72 and you get 75.6.

    Similarly, suppose that sweater was on sale at 20% off. What is the sale price?

    72 − 20% =

    The result is 57.6 or $57.60. This is the correct answer, because 20% of 72 is 14.4. Subtract that from 72 and you get 57.6.

    You can chain these percentage operations, too. For example, how much will you have to pay for that 20%-off sweater after adding 5% tax?

    72 − 20% + 5% =

    The result is 60.48. A mathematician or engineer would have calculated the same result via the equivalent computation:

    72 × 0.80 × 1.05 =

    Okay, now that we see how the calculator product designer intended the percent key to be used, let's look at what the calculator engineer it has to do in order to match the specification. When the user enters A + B % =, the result should be A × (1 + B/100) or A + (A × B/100) after you distribute the multiplication over the addition. Similarly, when the user enters A − B % =, the result should be A × (1 − B/100) or A − (A × B/100).

    Aha, the calculator engineer says, we can achieve this result by defining the percent key as follows:

    When the user enters a value, an operator, a second value, and then the percent key, the first two values are multiplied and the product divided by 100, and that result replaces the second value in the ongoing computation.

    Let's walk through that algorithm with our first example.

    You typeRemarks
    72First value is 72
    +Operation is addition
    5Second value is 5
    %72 × 5 ÷ 100 = 3.6
    3.6 becomes the new second value
    =72 + 3.6 = 75.6, the final result

    If you watch the display as you go through this exercise, you will even see the number 3.6 appear in the display once you press the % key. The percentage is calculated and replaces the original value in the ongoing computation.

    This algorithm also works for the chained percentages.

    You typeRemarks
    72First value is 72
    Operation is subtraction
    20Second value is 20
    %72 × 20 ÷ 100 = 14.4
    14.4 becomes the new second value
    +72 − 14.4 = 57.6, intermediate result
    57.6 is the new first value
    Operation is addition
    5Second value is 5
    %57.6 × 5 ÷ 100 = 2.88
    2.88 becomes the new second value
    =57.6 + 2.88 = 60.48, the final result

    This even works for multiplication and division, but there is much less call for multiplying or dividing a number by a percentage of itself.

    500 × 5 % =

    The result of this is 12,500 because you are multiplying 500 by 5% of 500 (which is 25). The result of 500 × 25 is 12,500. You aren't computing five percent of 500. You're multiplying 500 by 5% of 500. (It appears that the authors of this Knowledge Base article didn't consult with the calculator engineer before writing up their analysis. The percent key is behaving as designed. The problem is that the percent key is not designed for engineers.)

    What if you want to compute 5% of 500? Just pick a dummy operation and view the result when you press the percent key.

    500 + 5 %

    When you hit the percent key, the answer appears: 25. You could've used the minus key, multiplication key, or division key instead of the addition key. It doesn't matter since all you care about is the percentage, not the combined operation. Once you hit the % key, you get your answer, and then you can hit Clear to start a new calculation.


    ¹In the United States, quoted prices typically do not include applicable taxes.

    ²In my limited experiments, it appears that no two manufacturers of pocket calculators handle the percent key in exactly the same way. Casio appears to handle it in a manner closest to the engineering way. TI is closer to the layman algorithm. And when you get into cases like 1 ÷ 2 %, calculators start wandering all over the map. Should the answer be 50, since 1/2 is equal to 50%? Or should it be 0.005 since that is the numeric value of 0.5%? Should that answer appear immediately or should it wait for you to hit the equals sign? I don't know what the intuitive result should be either.

  • The Old New Thing

    The impact of hardworking employees on their less diligent colleagues


    Slate investigates the question "Do hardworking employees make their slacker colleagues more productive?" Tim Harford cites the study Peers at Work by Alexandre Mas and Enrico Moretti which used a grocery store check-out line as its laboratory, and the results are illuminating. (It may be hard to find, but the key paragraph is in the middle of page 4, the one that begins, "We find that...")

  • The Old New Thing

    Jag är inte heller en Microsoft-talesman på svenska


    The Swedes haven't quite figured out that my blog entries do not constitute the official position of Microsoft Corporation. I like how they don't even mention my name anywhere. They just say "Microsoft doesn't this" and "Microsoft doesn't that". If you go back to the article they used as a source, you'll see that I provided a variety of reasons for not going into the Start menu point system, but this author decided to claim that reason 1 was not only the only reason but in fact the official reason.

    Perhaps I should have used a CGI script which randomized the order of the items each time you refreshed.

  • The Old New Thing

    Generating initials from a name is trickier than you think


    Even though I'm signed in, the page claims that anonymous comments are not allowed, so I'm reduced to posting my comment here and generating a trackback. Some time ago, Robert McLaws wrote a function that generates initials from a name. Let's set aside completely the issue of non-U.S. names; the function doesn't even handle U.S. names correctly.

    Given Cal Ripken, Jr., the function comes up with the initials JCR, which is decidedly suboptimal.

  • The Old New Thing

    Taxes: Files larger than 4GB


    Nowadays, a hard drive less than 20 gigabytes is laughably small, but it used to be that the capacity of a hard drive was measured in megabytes, not gigabytes. Today, video files and databases can run to multiple gigabytes in size, and your programs need be prepared for them.

    This means that you need to use 64-bit file offsets such as those used by the function SetFilePointerEx (or SetFilePointer if you're willing to fight with the somewhat roundabout way it deals with the high 32 bits of the offset). It also means that you need to pay attention to the nFileSizeHigh of the WIN32_FIND_DATA structure. For example, if your program rejects files smaller than a minimum size, and I give you a file that is exactly four gigabytes, and you check only the nFileSizeLow, then you will think that the file is too small even though it is actually enormously huge.

    More indirectly, it means that you can't blindly map an entire file into memory. Many programs simplify file parsing by mapping the entire file into memory and then walking around the file using pointers. This breaks down on 32-bit machines once the file gets to be more than about a gigabyte and a half in size, since the odds of finding that much contiguous free address space is pretty low. You'll have to map it in pieces or use some other parsing method entirely.

  • The Old New Thing

    Bait and switch literally applied to fish


    The Saint Petersburg Times purchased fish from several local restaurants and found that nearly half of the time, the fish they got wasn't what they ordered. A state DNA lab came to the same conclusion.

  • The Old New Thing

    Clean-up functions can't fail because, well, how do you clean up from a failed clean-up?


    Commenter Matt asks how you're supposed to handle failures in functions like fclose or CloseHandle. Obviously, you can't. If a clean-up function fails, there's not much you can do because, well, how do you clean up from a failed clean-up?

    These clean-up functions fall into the category of "Must not fail for reasons beyond the program's control." If a program tries to close a file and it gets an error back, what can it do? Practically speaking, nothing. The only way a clean-up function can fail is if the program fundamentally screws up, say by attempting to close something that was never open or otherwise passing an invalid parameter. It's not like a program can try to close the handle again (or worse go into loop closing the handle repeatedly until it finally closes).

    Remember this when writing your own clean-up functions. Assuming the parameters are valid, a clean-up function must succeed.

    (I will now ruin my rhetorical flourish by yammering about the fclose function because if I don't, people will bring it up in the comments anyway. The fclose function does extra work before closing, and that extra work may indeed run into problems, but the important thing is that when fclose returns, the stream is well and truly closed.)

    Addendum: Once again I wish to emphasize that while it may be possible for functions like fclose to run into errors while they are closing the stream, the point is that the result of the call to fclose is always a closed stream. I think most of the comments are losing sight of the point of my article and rat-holding on the various ways fclose can run into errors. That's not the same as failing. It never fails; it always succeeds, but possibly with errors.

Page 3 of 4 (35 items) 1234