Opinion:Smart Software is Stupid Software
In the face of ambiguity, refuse the temptation to guess.
– Tim Peters, The Zen of Python
A lot of software tries to be smart. This seems like a good thing, but usually it is not.
Software which tries to be smart usually takes a lot of input and makes an educated guess about some parameter. For example, a file viewer might examine the contents of a file, and based on properties decide how to display it (is it a text file or a binary file). While this seems useful, it is not. If it usually goes right, other software may start to rely on the behaviour. However, as soon as the previous assumptions fail, it is usually very difficult or outright impossible to work around it. Because of that, the smart software often only causes more trouble for the user, not less.
Computers are great in doing dull, mind-boring tasks, while humans are great in handling complexity. Smart software tries to be intelligent, and usually fails miserably.
The situation might not be bad if some software makes just one guess, which is easy to override. The problem come when it is not obvious how to override the default. A few examples to illustrate.
|"Smart" behaviour||Better behaviour|
|Software may guess your location based on IP address or GPS data, and from that determine your time zone or preferred language. That choice might be wrong. Not every person living in France speaks French.||Good software would probe the user preferences from the OS to determine the preferred locale settings. A web application may let the user store his or her settings, but usually it is just easier to provide two different URLs. www.google.fr could be in French and www.google.de in German. For advanced options, www.google.de/fr would have a French interface, but search websites in Germany.|
|A boot systems may determine all file systems on disks, and decides to boot in Windows, BSD or Linux by default.||An unconfigured boot system should provide a menu with all bootable disks found, and boot from the first after a few seconds. Only when the user specifically configured the boot loader to boot from a certain disk, should it do so.|
|A software repository may display XML or base64 encoded file as text.||-||A tool may determine the environment to determine what to do with log message (write to disk, show on screen or pipe to stderr).||Nearly all platforms have a standard log facility, and most software have a good log package (log4j for Java, logging for Python, etc.). Those should be used.|
|A package installer may probe for the best mirror site by determining the nearest mirror using round trip time, ignoring bandwidth constraints.||Actually, this behaviour isn't so bad, as long as it is customizable by the user, and the behaviour is clear to the user.|
|A software installer may determine some missing dependencies and start downloading and installing them by itself, overriding a package manager.||Depending on the OS, the installer can either include the dependencies in the installer, and provide an option to install them, or (for most Unix systems), it could simply report the missing dependencies. Standard configure scripts are a prime example: they make guesses, report those to the user, and allow easy overrides by users.|
|An device with embedded unix writes all config files in a standard format (so the webinterface can read and write it), and provides a wrapper around each deamon that creates the actual config file on the fly.||This is not customizable. Unfortunately, there is no solution that allows a user to both use the webinterface and do manual configuration. However, in this case, the user does not have the option to do manual configuration. It is better to make a wrapper that changes the config files as soon as it is changed, not as soon as the daemon is started.|
Each individual guess may not seem bad, but the problem arises when all these tools and applications start working together, and they do. A simple app on a computer involves not only the application, but also the operating system, a whole bunch of libraries, the network and computers at the other end of the network. If all these tools start guessing, the result is unpredictable.
This is not to say that every smart behaviour is wrong. Software may very well apply smart algorithms (in fact, a lot of software does so), but those algorithms must be well understood, and in case of the heuristic algorithms in the above examples, they are often not understood.
So what is the answer? Of course, we don't want to ask the user every time some input is unknown or unclear.
The above examples give a hint at the solution. If the program interfaces to another program, demand strict input. If the program interfaces to the user, let the user fill in the preferences. Ask the OS for the preferred language, don't mix current location and language preferences, pick the boot system from a preference file, wait for user input (and store that result) if no choice was made. Look up the file type from whatever means is custom on the OS (file type attribute, file name extension or provided mime-type), asks the OS for the location of temporary files. log to a standard logging facility. Try mirror in a determined order, provided in a config file.
The smart part of the software comes from providing sound defaults when the user chooses the settings the first time. Not from guessing each and every time. In fact, the best programs are not smart in how they interpret the input, but smart how to deal with unusual situations. For example, how they deal with a broken network connection or deal with an OS which does not provide a given functionality.
We can make the life of a user easier by providing common functionality (such as location services, or a file type API) in the OS. Making smart guesses about these properties in each individual application is not the answer.
Computers are great in doing dull, mind-boring tasks. Humans are great in handling complexity. So let's design software on this principle, and not try to outsmart the user.