Question

In Richard Gabriel's famous essay The Rise of Worse is Better, he contrasts caricatured versions of the MIT/Stanford (Lisp) and New Jersey (C/Unix) design philosophies along the axes of simplicity, correctness, consistency, and completeness. He gives the example of the "PC loser-ing problem" (discussed elsewhere by Josh Haberman) to argue that Unix prioritizes simplicity of implementation over simplicity of interface.

One other example I've come up with is the different approaches to numbers. Lisp can represent arbitrarily large numbers (up to the size of memory), while C limits numbers to a fixed number of bits (typically 32-64). I think this illustrates the correctness axis.

What are some examples for consistency and completeness? Here are all of Gabriel's descriptions (which he admits are caricatures):

The MIT/Stanford approach

  • Simplicity -- the design must be simple, both in implementation and interface. It is more important for the interface to be simple than the implementation.
  • Correctness -- the design must be correct in all observable aspects. Incorrectness is simply not allowed.
  • Consistency -- the design must not be inconsistent. A design is allowed to be slightly less simple and less complete to avoid inconsistency. Consistency is as important as correctness.
  • Completeness -- the design must cover as many important situations as is practical. All reasonably expected cases must be covered. Simplicity is not allowed to overly reduce completeness.

The New Jersey Approach

  • Simplicity -- the design must be simple, both in implementation and interface. It is more important for the implementation to be simple than the interface. Simplicity is the most important consideration in a design.
  • Correctness -- the design must be correct in all observable aspects. It is slightly better to be simple than correct.
  • Consistency -- the design must not be overly inconsistent. Consistency can be sacrificed for simplicity in some cases, but it is better to drop those parts of the design that deal with less common circumstances than to introduce either implementational complexity or inconsistency.
  • Completeness -- the design must cover as many important situations as is practical. All reasonably expected cases should be covered. Completeness can be sacrificed in favor of any other quality. In fact, completeness must be sacrificed whenever implementation simplicity is jeopardized. Consistency can be sacrificed to achieve completeness if simplicity is retained; especially worthless is consistency of interface.

Please note I am not asking whether Gabriel is right (which is a question not appropriate for StackExchange) but for examples of what he might have been referring to.

Was it helpful?

Solution

The question's title suggests that some basic user interface inconsistencies may interest you:

Unix commands don't follow any particular syntax for specifying options and flags. For example, most commands use single letters preceded by '-' as flag: cat -n some_file, but exceptions like tar tf some_file.tar and dd in=some_file out=some_other_file count=2 exist in commonly used commands.

Unix and its descendants and relatives have multiple slightly different regular expression syntaxes. Shells use "*" where other programs (grep, egrep, vi) use '.*'. egrep has '+' and '|' as operators, grep does not.

The basic "everything is a file" system call interface could be viewed as incomplete: read/write/seek/close doesn't fit every I/O device. Badly needed exceptions get lumped into "ioctl" calls, but devices like sound cards don't even fit that very well.

OTHER TIPS

Consistency

Lisp has a very consistent syntax, all language extensions can be embedded naturally via macros and such. C, on the other hand, has a rather code syntax, which allows one to take some "shortcuts", so in some cases C code actually look simplier.

Completeness

In Lisp, if you do not have a specific language feature you need, you can implement it yourself with macros. C too has preprocessor, but it is rather perplexing.

C's strings cannot contain character 0 and its library functions are unsuitable for dealing with binary data.

Filenames on Unix systems cannot contain character 0 or character 47 (the slash).

In the original implementation of Unix, filenames were limited to 14 characters. Later versions only relaxed this limitation; they did not eliminate it.

Added: The E2BIG system error condition, when one tried to exec with an argument list that had too many arguments, or occupied too much memory, or an environment that was too big.

Unix is notorious for this sort of arbitrary limitation. Until the advent of Perl in 1987, handling large data sets, or data sets with long records, or binary data, was extremely unreliable.

IIRC my teacher said the inability to use char * variables in switch statements in C is a matter of inconsistency, but for me that was generality (completeness) issue. I think it's better to use "consistency" just in your algorithms or software design not in programming language itself (at least not in languages like C. maybe a buggy language has consistency issue), because programming languages have solid standards that define domain of rules and work by applying input to rules. So if something is not allowed in language, it planned to not being allowed and is not inconsistency in language, IMHO.


  1. I've used generality as completeness. i think they are same thing. maybe I'm wrong.
  2. This is Not an answer. maybe suggestion or my opinion.

The best example I have is the poor user who had a file named .. -r and typed in rm *.

Whether this story is true or not, it's become a Unix hater's classic.

See The Unix-Haters Handbook, which has an introduction by Dennis Ritchie himself, for lots of these examples.

I'll add furthermore that avoiding these types of problems was a major force in the design of Microsoft's Power Shell.

  • Certainly the myriad meanings of the same (short) flags to commands is an inconsistency.
  • Each program that uses regular expressions has it's own syntax for them
  • Configuration files for services are all different syntax (that can be forgiven in part, your mailer daemon has little in common with your webserver or system startup, but still)
  • There are different editors! Users use different shells!! Why are there so many desktop environments?!?

OTOH, the fact that the shell expands globs, and not the progam, eliminates a lot of irritating inconsistencies present in other systems. Ditto the fact that you can use the same command to copy a file from one place to the other in the filessytem, to a diskette or from a Zip disk to tape.

So, yes, Unix is inconsistent. So are the other systems, just differently ;-)

LISP supporting infinite precision numbers versus C supporting only machine integers is not an example of language 'correctness'. It is a simple matter arising from the fact that the languages had very different design goals.

The point of C was to be a language close to the machine that could be used to implement operating systems. Machines (mostly) don't support infinite-precision decimal numbers. Machines (mostly) do have integers of fixed bit-lengths.

Licensed under: CC-BY-SA with attribution
Not affiliated with cs.stackexchange
scroll top