Raymond Chen's lessons

2014-04-25

A random collection of wisdom from Raymond Chen and The Old New Thing. I plan to keep this updated as I discover/remember more of them.

Windows doesn’t have an expert mode because you are not an expert.
This is just the Dunning-Kruger effect in play: people who are not experts pretty much by definition lack the ability to judge whether they are experts or not. “Expert users” using the advanced features of Windows invariably make feature requests that are equivalent to the beginner feature that already exists.

The hatchway is still secure, even if you opened it with the key.
It’s not a security bug if the user has to first give permission to elevate. Bogus security reports of this nature generally go like this:

  1. Do something that requires elevation, such as replacing an application’s DLL with a malicious copy.
  2. Run the application.
  3. YOU HAVE NOW COMPROMISED THE USER’S COMPUTER.

Except, it’s not a security bug because step 1 required elevation, and therefore an administrator’s consent.

Eventually, nothing is special any more.
If you create special functions or flags in your API to give them extra functionality, they will in practice become the defaults over time, as programmers cargo-cult their way through programming. Eventually people find that the regular function “doesn’t work” (for various definitions of “work”), and that the special function does.
https://blogs.msdn.com/b/oldnewthing/archive/2008/10/06/8969399.aspx

Providing compatibility overrides is basically the same is not deprecating a behavior.
“If you provide an administrative override to restore earlier behavior, then you never really removed the earlier behavior. Since installers run with administrator privileges, they can go ahead and flip the setting that is intended to be set only by system administrators.”

Appearing to succeed is a valid form of undefined behavior.
Undefined means anything can happen, including: returning success, nothing, formatting your system drive, playing music, etc. So it is futile to ask “if the documentation says doing x results in undefined behavior, why does it appear to work?” Also, one cannot rely on a specific form of undefined behavior; relying on it implies the behavior is defined and contractual.

The registry is superior to config files.
Config and .ini files are deprecated in favor of the registry because:

  1. ini files do not support unicode.
  2. Security is not granular (how do you restrict a group from editing a certain part of the file?)
  3. Atomicity issues with multiple threads/processes can lead to data loss on the flat file (the registry is a database).
  4. Denial of service issues – someone could just take an exclusive lock on your config to screw with you.
  5. ini can store strings only, so if you need to store binary you’d have to encode it as a string.
  6. Parsing files is slower, and writing settings would require loading and reparsing the whole file.
  7. Central administration via group policy would be exceedingly difficult compared to a registry.

Computer science: do not confuse the means with the ends.
It is often said that the purpose of garbage collection is to reclaim unused memory, but this is incorrect. The purpose of garbage collection is to simulate infinite memory. Reclamation is just the process by which this is achieved. For example, a null garbage collector is provably correct if you have more physical memory than your program needs. Similarly, allocating a value type on the stack is an implementation detail. It’s not a requirement that it is on the stack, only that it is always passed by value.
https://blogs.msdn.com/b/oldnewthing/archive/2010/08/09/10047586.aspx

Open source isn’t a compatibility panacea.
You don’t get rid of compatibility problems by publishing source code; in fact that makes it easier to introduce compatibility issues because it exposes all the internal undocumented behaviors that aren’t contractual.
https://blogs.msdn.com/b/oldnewthing/archive/2014/04/11/10516280.aspx

You can’t satisfy everyone about where to put advanced settings.
This is a specific case of not being able to delight all the people all the time when the audience is measured in billions. Most people prefer advanced settings in one of five categories (quoting Raymond):

  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.

Each item is approximately an order of magnitude harder than the last, and the final one is objectively user-hostile. Whatever you decide to implement, the other five groups will call you an idiot.
https://blogs.msdn.com/b/oldnewthing/archive/2008/01/14/7103585.aspx

Cleanup must never fail.
Low level cleanup functions don’t have very many options for recovering from failure, so they must always succeed (they may succeed with errors, but that is not the same as failing).
https://blogs.msdn.com/b/oldnewthing/archive/2008/01/07/7011066.aspx

Don’t use a global solution to a local problem.
Since an operating system is a shared playground, you can’t just run around changing global settings because that’s how you like it. If two applications with opposing preferences tried this, one or both of them would break; the correct approach is to change the setting in a local scope to avoid breaking other applications.

A platform must support broken apps; otherwise you’re just punishing the user.
Compatibility with apps, including incorrectly written apps, is crucial for platforms because users expect programs to work between versions of Windows. It is tempting to be a purist and declare that the apps should break, which will force the developers to fix them. In practice, the developers either don’t care, no longer exist, or don’t have the source code any more. Users will instead blame the platform and/or not upgrade.

Users hate it when they can’t cancel.
If you have a long running operation or some multi-step wizard, the user should be able to cancel. It should be clear what will and will not be saved or committed when they cancel.
https://blogs.msdn.com/b/oldnewthing/archive/2006/03/08/546177.aspx

Geopolitics is serious business.
It can be illegal to have a map with incorrect labels or borders (the correctness of which depends on who is looking), or to call disputed territories (such as Taiwan) countries in some places.
https://blogs.msdn.com/b/oldnewthing/archive/2003/08/22/54679.aspx

The USB stack is dumb because it’s dealing with dumb manufacturers.
Some USB devices have identical serial numbers which can cause non-deterministic behavior and arbitrary settings assignment, so Windows has no choice but to pretend every device is unique. This is why if you unplug/re-plug a device into a different USB port, Windows treats it like a new device and forgets all your settings. More generally, Windows could be smarter, but then things would break.
https://blogs.msdn.com/b/oldnewthing/archive/2004/11/10/255047.aspx

Avoid Polling
Polling prevents the hot code and all code leading up to it from being paged out, prevents the CPU from halting to a lower power state, and wastes CPU.
https://blogs.msdn.com/b/oldnewthing/archive/2006/01/24/516808.aspx