Holy cow, I wrote a book!
A common obstacle when trying to help people solve their problems
is that what people ask for and what they actually want are not
always the same thing.
For technical problems, you often get a question that
makes you shake your head in disbelief,
but upon closer questioning, you find that the person really
doesn't want what they're asking for.
What they really want is something else, but they've
already "solved" half of the problem and only need your help
with the other half—the half that doesn't make any sense.
For example, the literal answer to
"How do I write a regular expression that matches
everything except XYZ" is often a horrible mess,
but if you dig deeper, you'll find that they really don't need
a regular expression that matches everything except XYZ;
they just simplified their problem to
"I know, I'll use regular expressions"
ended up creating a bigger problem.
(The best solution is often a mix of regular expressions and
simple program logic.)
This problem also exists in user interface design.
Rick Schaut describes one case where a user asked for a feature,
when what they really wanted was an entirely different feature.
Understanding the customer's problem is the first step towards solving it.
One of my colleagues pointed out a sign at an automobile tire center
where they use lead weights for balancing wheels.
It read (paraphrased):
Lead has been known to cause cancer.
Ensure that you wash your hands before eating or smoking.
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
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
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
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.
Since the lines at warehouse-style stores are always ridiculously long,
I like to pass the time by checking out the legally required postings of
food-handling and related licenses.
Usually, two or three of their licenses have expired.
It could be their seafood license,
or their raw meat license,
or their bakery license,
it's always a surprise each time I visit.
When I point this out to someone, they usually just say,
"Oh, um, you'll have to ask the main office."
And when I ask the main office, they usually say,
"Um, everything is just fine.
The store was just slow to post the new licenses."
In other words, nobody wants to take responsibility for
breaking the law.
Maybe I should just report them to the health department.
Or get some tips from
Mind you, the bulletin board in our building hasn't
updated its license to employ minors since it expired in 2000.
I've pointed this out multiple times to our personnel
department, and they assure me that they'll get right on it
and post the new license,
but it has yet to happen.
When I sent them a reminder a few days ago,
the response was disbelief, because some other "they"
was supposed to have taken care of it.
We'll see if anything changes.
Windows File Protection works by replacing files after they have
Why didn't Windows just apply ACLs to deny write permission to the
We tried that.
It didn't work.
Programs expect to be able to overwrite the files.
A program's setup would run and it decided that it needed to "update"
some system file and attempt to overwrite it.
If the system tried to stop the file from being overwritten,
the setup program would halt and report that it was unable
to install the file.
Even if the operating system detected that somebody was trying
to overwrite a system file and instead gave them a handle to
those programs would nevertheless notice that they had been
hoodwinked because as a "verification" step,
they would open the file they had just copied
and compare it against the "master copy"
on the installation CD.
The solution was to let the program think it had won,
and then, when it wasn't looking,
put the original back.
Now that Windows File Protection has been around for a few years,
software installers have learned that it's not okay to overwrite
system files (and trying to do it won't work anyway),
so starting in Windows Vista,
the Windows File Protection folks have started taking stronger
steps to protect system files,
and this includes using ACLs to make the files harder to replace.
Presumably, they will have compatibility plans in place to
accomodate programs whose setup really wants to overwrite a file.
There are some basic ground rules that apply to all system programming,
so obvious that most documentation does not bother explaining them
because these rules should have been internalized by practitioners
of the art to the point where they need not be expressed.
In the same way that when plotting driving directions
you wouldn't even consider taking a shortcut through somebody's
backyard or going the wrong way down a one-way street,
and in the same way that an experienced chess player doesn't even consider
illegal moves when deciding what to do next,
an experienced programmer doesn't even consider violating the following
basic rules without explicit permission in the documentation to the contrary:
(Remember, every statement here is a basic ground rule, not an
absolute inescapable fact. Assume every sentence here is
prefaced with "In the absence of indications to the contrary".
If the caller and callee have agreed
on an exception to the rule, then that exception applies.
a pointer is prototyped as volatile
is explicitly marked as "This value can change from another thread,"
so the rule against modifying function parameters does not apply to
such a pointer.)
Coming up with this was hard,
in the same way it's hard to come up with a list of
illegal chess moves.
The rules are so automatic that they aren't really rules
so much as things that simply are and it would be crazy
even to consider otherwise.
As a result, I'm sure there are other "rules so obvious they need
not be said" that are missing.
(For example, "You cannot terminate a thread while it is inside
somebody else's function.")
One handy rule of thumb for what you can do to a function call
is to ask, "How would I like it if somebody did that to me?"
(This is a special case of the "Imagine if this were possible" test.)
Speculate all you want about what users expect,
what they want,
what they care about.
There's no substitute for actually running experiments to find out.
Those who haven't already been following
really ought to be,
because he talks about user interface design in a highly
Consider this entry on
deciding how the ribbon should behave:
These rules came directly out of watching people
use the product in the labs over the last few years.
Other rules we thought would be important
(such as always collapsing from right to left)
turned out to not matter at all.
Or this one on
the special rule for lingering:
What we found was that an extremely common scenario involved people
using an object,
clicking away from it to make the selection handles go away
(to get a better look at it)
and then clicking right back on the object to continue formatting it.
Notice that prior to discovering and then implementing the "lingering"
rule, users who used Contextual Tabs were frequently confused.
But once the rule was created, the usability results are solid.
Methodology explained earlier.
As I noted yesterday, the final will be very close,
with George Washington University edging out Villanova by two
months, 1988.08.01 to 1988.10.05.
Other people have come up with their own systems.
The person a few doors down from me chose an algorithm that
can be captured in three words:
"Shorter name wins".
But my favorite is somebody whose highly scientific method
is "The team that pays its basketball coach more."
Many people have noticed that the animation bar control
in version 6 of the common controls no longer uses a background
thread to draw the animation.
Instead, it acts as if the ACS_TIMER style is always
set, even if the caller didn't pass it.
Why is that?
The first reason is that the background thread didn't actually help any.
In order to draw transparent animations, the painting loop needs to
query the animation control's parent to obtain the background color,
and that query entails sending a message to the main UI thread.
Consequently, the main UI thread must remain responsive to messages
in order for the animation to render properly.
If the main UI thread stopped responding to messages,
the WM_CTLCOLORSTATIC message sent to obtain the
background color would hang, and painting would wedge.
Therefore, the UI thread had to remain responsive to messages.
And if that's the case, then there's no need for the background
thread after all.
The UI thread can just run a timer and draw the frames in response
to the timer message.
The second reason for getting rid of the background thread is that
it actually made things worse.
Another thread means more context switches and more memory pressure,
since the additional thread needs a stack and other supporting
Admittedly, this is a comparatively weak reason.
The third reason is that using a background thread for painting
simply encouraged bad code.
Using a background thread for painting meant that the UI thread
could stop responding to messages for long periods of time
and usually get away with it because the query for the background
color comes early in the animation cycle when the main UI thread
most likely has not yet gotten into the part of the long-running
procedure that stops responding to messages.
As a result, the background thread encouraged programs to stop
pumping messages on UI threads because "it seems to work fine".
The result is programs that fail to maintain a responsive UI,
periodic mysterious hangs in the window manager
when another program tries to broadcast a message and gets wedged
up behind the unresponsive window.
This leads to increased frustration for the end user and
a general feeling that "Windows sucks".
By making the suckage obvious, programmers will be more likely
to notice that they are doing something bad and do something to
Masking the problem with a background animation thread merely
allows the problem to persist.
Okay, somebody handed me a NCAA Men's Basketball Bracket to fill out.
I don't know squat about college sports,
so I decided that I would fill in the bracket based on the following
The school whose President (or Chancellor)
has served longer will win the match-up.
(Not counting the first-round games of the top five seeds in each bracket,
just to avoid some wild upsets.)
At least I thought that was simple.
Filling out the bracket given this rule turns out to be rather difficult,
because I have yet to find a web site that has links to
all the schools represented in this year's tournament.
(I guess college athletics isn't about the academics,
because if it were, then certainly people would be falling over
themselves to extol the fantastic educational opportunities at
the schools represented.)
And it's not exactly easy to figure out the school's web site from
the bracket sheet.
There is for example a team labelled simply "Texas".
Do I want "The University of Texas at Austin"?
Do I want "The University of Texas at Dallas"?
Do I want "The University of Texas at Arlington"?
"Texas State University"?
I'm guessing it's the University of Texas at Austin,
though I might be wrong.
And then there's another box labelled "California".
Which of the many California schools is that supposed to be?
I don't even know what question to enter into a search engine to find out.
(Turns out it's the University of California at Berkeley.)
Even after I hunt around to figure out which of the dozen universities
named "Texas" I think I really want, I then have to find out who
their President is and when they assumed office.
Finding the President's page (or Chancellor's page) sometimes takes work,
and even if you find it, it's sometimes wrong.
For example, the first thing that I noticed on
the page for Syracuse University's
Chancellor Nancy Cantor is that it says
"Learn about Chancellor-Elect Nancy Cantor".
(If you don't see that phrase on the page,
turn on your screen reader or disable images, or just
hover over the "Inside the Chancellor's Site" link.)
"Well, great," I thought.
"She's Chancellor-Elect, but who's the current
Turns out that Nancy Cantor is the current chancellor.
She was inaugurated two years ago.
The "Chancellor-Elect" text is badly out of date.
Even when I can find the site of the university's President/Chancellor
it's sometimes quite a bit of work to find out when they took office.
For example, go back to Nancy Cantor's page and try to figure out
when she was inaugurated.
You have to click on "Soul of Syracuse", then go
to the News page, then scroll down to the article titled,
"Amid grand community celebration, conversation and art,
SU inaugurates Cantor as 11th Chancellor and President",
click through to the article and read the dateline.
November 5, 2004.
That was a lot of work for a tiny bit of information that
you think would be easily accessible on a biography page.
Good luck finding the home page of the president of
Utah State University; and if you manage to find the date
at which he became president,
then I tip my hat to you,
because as far as I can tell they
don't list that information on their web site.
(By the way, according to my highly scientific method,
the final game between Villanova and George Washington
University will be extremely close, with GWU eking out
a victory by just two months, August 1, 1988 to October 5, 1988.)