Effortless UI, Part 1
No tyranny is so irksome as petty tyranny: the officious demands of policemen, government clerks, and electromechanical gadgets. -- Edward Abbey
Jeff Atwood writes about making software “considerate,” which lists thirteen different attributes of considerate software. It’s a nice read. In the post, he writes that considerate software …
- takes an interest
- is deferential
- uses common sense
- is forthcoming
- anticipates needs
- is conscientious
- doesn’t burden you with its personal problems
- keeps you informed
- is perceptive
- is self-confident
- doesn’t ask a lot of questions
- takes responsibility
- knows when to bend the rules
Most of these attributes are the same ones that I look to when developing “smart software.” Here’s one instance where I make my software more considerate.
Early on, I realized that there was some non-trivial mental effort required to use my software. Once a bug was reported, the developer would have to mentally navigate through multiple branches of code and functions to spot the error.
An important factor in the success of my program is how easily and effortless it is to use. If the output of my program is instantaneously understandable, users are more likely to use it from the start. On the other hand, if significant thinking is involved, users are more likely to dread my software and use it as a last option. In a usability lecture, Mark Miller, of Dev Express (maker of Refactor Pro), observed how instanteneity (measured by minimal use of mouse travel and keystrokes) contributes to the user’s “euphoric high” and enjoyment of the program.
My first attempts at alleviating mental effort was to include a assumptions and locals window, mirroring the same windows found in Visual Studio. I also considered a watch and immediate window in which expressions could be entered and functions could be executed. These windows help by providing context.
Here’s the code from Rotor that we will be looking at. I inserted an explicit null dereference at line 240. (Note that I entered a carriage return on line 231 to wrap the condition to the next line for the screen capture, so all line offsets after 230 are off by one in the various windows.)
Below is my first attempt at a “Locals” window.
Noticed how the “Locals” window requires a master’s degree to decipher. The values displayed appear in lengthy, cryptic symbolic forms. Parameter values take the name of the parameter passed in, appended with a backquote. Fields and properties values can change over time, and methods can return different values per call, so they are all tagged with unique ids such as “#74” for each unique value.
Here’s how complicated these symbolic expressions can appear using the assumptions window for another function.
These expressions are likely to hurt the usability of my product, so I decided to display the values in terms of current assignments. For the code above, here’s how the new “Locals” windows appear.
The “Locals” window is now friendlier and instantly readable as is the “Assumptions” window below.