Sun Jul 16 11:38:03 BST 2006
Eric Raymond's book "The Art of Unix Programming" is a great explanation of the Unix programming philosophy (and Zen), as well as a guide for writing good programs. In Chapter 11 he discusses a set of common Unix interface Design Patterns, ie how the program interacts with the user. The key points about Unix are that everything is a file, and ideally all data is stored in plain text files. This means that data can be processed using a number of different programs, rather than the specific program that was originally used to produce the data.
The design patterns are:
- Filter. The program receives data on standard input, does something to it and returns the result to standard output. The user can use shell redirection to read from or write to a file instead of stdin/stdout. Filters can be chained together.
- Cantrip. Invoke the command and it does something, with no input or output required by the user. An example is the "makeblog" shell script file that I use to run my blogging program, move the output to another directory, change to that directory, run Markdown on the result and move the result of that to a final directory.
- Source. Filter-like pattern that doesn't require input, gives output dependent on configuration parameters. For example ls, who.
- Sink. Consumes input, doesn't output anything. A less common pattern, examples are lpr for printing or mail for sending mail.
- Compiler. Takes in file names as input, does something depending on the content of the files and writes output to other files, with names depending on the input file. For example laTex converting formatted text into a postscript file.
- ed. Takes a filename as an argument, then a set of editing commands on stdin that make changes to the file.
- Rougelike pattern. Originally from the game Rouge, the output is a GUI written in text characters, input is single-character commands from the keyboard (or a special command to bring up a command line). Examples are vim or emacs although these appear to have quite different user interfaces. Vim is a modal editor, so what a key does depends on what mode the editor is in eg edit versus insert. Emacs is a modeless editor and commands are entered as chords ie a sequence of ctrl-(key1) ctrl-(key2) etc after each other.
- "Separated Engine and Interface" pattern. Program complexity is
reduced by separating the engine that actually does stuff from the
interface. Model-view-controller programming paradigm. There are a
number of variants of this pattern:
- Configurator/Actor. Separate program to set the configuration parameters of a daemon program, for example the web interface to a CUPS server.
- Spooler/Daemon. Spooler serialises communication to the Daemon, eg for printing there is a spool directory that stores documents to be printed, and the Daemon periodically checks this directory.
- Driver/Engine. Similar to Configurator/Actor but more tightly coupled ie there is dataflow back from the engine to the driver.
- CLI server pattern. When the program is in the foreground it has a CLI reading from stdin and writing to stdout, as well as having internal state (so it is not just a simple filter). When made into a background process it is tied to specific ports to receive input and write output.
- Language-Based interface patterns. Scripting languages to control programs. For example script-fu in Gimp.