User options considered harmful


A lesson I had to learn several times when I worked in video games is that the addition of user options has to be consciously resisted. The desire to add a user option often indicates that you have skimped on a important piece of usability work and are trying to put off doing it. Now, you’re probably already saying, “but what about—” at this point, so I need to clarify what I’m talking about. User options fall into four groups:

  1. options that improve accessibility, for example, language, volume, subtitles, rumble;
  2. options that allow the user to express their creativity and personality, for example by customizing their character’s name, appearance and equipment;
  3. options that are necessary in order to interact with features of the environment that can’t be automatically detected, for example the aspect ratio of a connected television screen; and
  4. options that control game behaviour, for example camera controls and difficulty level.

It’s the fourth group of options that I’m talking about. And I’m not saying that this group of options are always bad, I’m saying that the desire to add options in this group is all too often a sign that the developers are facing a problem that they find difficult to solve, and it’s becoming tempting for them to avoid the work involved in solving it by passing the buck to the player.

For example, in the screenshot at right (from the Mass Effect 3 beta) there’s an option for “auto level up”. This controls what happens to your characters’ skills when you reach a new level. With the option turned off, you choose which skills to improve: this suits players who like to fiddle with stats. With the option turned on, the game chooses for you: this suits players who prefer to get on quickly with the game. But what about people who sometimes like to fiddle and sometimes like to play on? Or who start out not caring about the skills system, but gradually want to get into it? I think that with some thought about the way skills work, and some redesign of the interface, this option could be removed. One simple idea would be for the game to assign points to skills automatically when you level up (to suit the impatient players), while allowing these points to be reassigned between skills at any time before the next level up (to suit the fiddlers).

The “autosave” option, on the other hand, is simply puzzling. Why would someone want to play with it turned off? Why would the game allow them to do so given that they might end up losing progress? I can only guess that there was some kind of unresolved bug with the autosave, such as a pause or a risk of corrupted save files, and adding the option was a way for the developers to wash their hands of responsibility for fixing the bug.

This temptation to pass the buck needs to be resisted: many users aren’t expert enough to find and use the options (especially when first encountering the game), and these users are precisely the ones who need the program to do the right thing. The users who are capable of benefitting from options are generally expert enough to do without them. Also, options add considerable testing burden: for example a choice between two camera algorithms would ideally require the whole game to be played through twice on each testing run in order to ensure that one of the cameras didn’t go wrong in some location. Or if you couldn’t afford to double the amount of testing then the risk of missing a camera bug would be much increased.

So I think that a useful heuristic when joining a project is to look at the user options. Each one must have been added by the developers to compensate for some problem, and maybe some of the problems are in fact of the developers’ own making. In the case of p4.el, here’s an analysis of the user options that I found when I started work, showing the high proportion of them that were covering up or compensating for defects:

  1. One of the pressing problems that led me to take on the project was the fact that whenever you open a file in Emacs, p4.el ran a check to see if the file is under Perforce control, and this check ran synchronously with respect to the user interface, so that when the network connection to the Perforce server was unavailable, opening a file caused Emacs to hang until the network connection timed out. The awfulness of the synchronous mode check led to an accretion of features designed to maintain the same information without having to actually run Perforce to get a definitive answer. So there was the user option p4-use-p4config-exclusively, which attempted to replicate the Perforce P4CONFIG logic and so discover if a file is under Perforce control without having to run Perforce. There was a mechanism for periodically refreshing files known to be under Perforce control and a user option p4-file-refresh-timer-time for controlling the interval at which these files were refreshed. When I made the mode check run asynchronously the need for these options disappeared.

  2. The user option p4-default-depot-completion-prefix contained a “Prefix to be used for completion prompt when prompting user for a depot file” with default value "//depot/". This seemed to be a workaround for the fact that completion on Perforce depots had not been implemented. With that bug fixed, the user option did more harm than good: if the Perforce server doesn’t have a depot named “depot” (or if it did but the user wanted some other depot) then it would just get in the way. So I removed it.

  3. The user option p4-colorized-diffs controlled whether diffs were displayed in colour. This was a workaround for the fact that Emacs used not to have universal control over fontification: the addition of global-font-lock-mode in Emacs 22.1 made it superfluous and I removed it.

  4. The user options p4-my-clients and p4-strict-complete are there to allow users to quickly switch between Perforce client workspaces by setting the P4CLIENT environment variable. But in release 98.2, Perforce added the P4CONFIG setting which provides an automatic and more reliable way to do this. (I’ve left the user options in place in case people are dependent on them for their workflow, but really they should have switched to using P4CONFIG long ago.)

  5. The user options p4-cleanup-time and p4-cleanup-cache are trying to balance two competing requirements concerning completion lists (the choices you get when you type TAB in the minibuffer). On the one hand, you’d like the completion list to be as current as possible (and so fetched recently from the server). On the other, you want the completion list to become available as soon as possible (and so fetched from the cache rather than getting them again from the server). But these user options don’t solve the problem, because they don’t actually control the variable you’re interested in (that is, how long the completions take to appear), and because the bandwidth and latency to the server can vary over time (you might be on a laptop on a train) or even from one file to another (if you are working on files checked out from two or more servers). Some kind of per-server response time measurement is needed. I haven’t fixed this.

  6. The user option p4-exec-arg-len-max allowed the user to specify the maximum length of a Perforce command line. But the Perforce client has always allowed you to pass it arguments via standard input rather than the command line, so after fixing the code to do that, I was able to remove the option.

  7. The user option p4-verbose supposedly allowed you to specify whether to “pop up an output buffer with the result of the command”. But in fact it no longer had any effect: this change had broken the feature but left the user option in place.

  8. The user options p4-sendmail-program, p4-user-email and p4-notify controlled the behaviour of the “notify” feature. This was a kind of basic change review system, but it had long since been obsoleted by Perforce’s own review daemon system.

  9. The user option p4-window-config-stack-size specified the maximum size of the stack of window configurations. This was added because Emacs is not a modal editor, so that when you display a buffer in a window, there are many ways for the user to leave that buffer, and no guarantee that your stack of windows will get popped. So unless a limit is placed on the size of the stack, it will grow without limit. But then why have a stack at all? I got rid of the stack and replaced the p4-pop-window-config command with the built-in quit-window.

  10. Finally, the user options p4-executable (the location of the Perforce client program) and p4-default-diff-options (the style of diff output you get by default) are genuine options that don’t seem to be working around bugs. The former is a feature of the environment that we can’t detect automatically (in the case that the Perforce client is not on your PATH), and the latter seems like it might be a genuine personal preference.

Every useful heuristic is capable of being turned into a rule and applied thoughtlessly, so let me repeat: the idea of looking suspiciously at a user option is not just to remove it, but to identifying the underlying defect, fix it, and only then remove it.