Mike Gancarz published a little book on this in 1995:
The UNIX Philosophy
Digital Press, Newton, MA 1995, 151 pp., $19.95, ISBN 1-55558-123-4
He has two lists of tenets: 9 main ones and 10 lesser ones.
Here are some examples:
- Small is beautiful.
- Make each program do one thing well.
- Build a prototype as soon as possible.
The full list, with commentary by Simon Dobson, taken from http://www.cs.tcd.ie/Simon.Dobson/teaching/unix-philosophy.html :
The major tenets
- Small is beautiful. Small things have tremendous advantages over their larger counterparts. Among these is the ability to combine with other small things in unique and useful ways.
- Make each program do one thing well. By focusing on a single task, a program can eliminate much extraneous code that often results in excess overhead, unnecessary complexity, and a lack of flexibility.
- Build a prototype as soon as possible. Most users looking for a new piece of software won't know what they really want until they see it, so requirements documents are often misleading about the users' real needs. The Unix design philosophy makes prototyping a central part of the methodology: give the user something, anything, up-front to criticise, and work from there.
- Choose portability over efficiency. If today's hardware just about runs a program with just about adequate efficiency, tomorrow's will run it with power to spare. So the developer's task is to make sure his program will run on that new hardware with minimal effort.
- Store data and configuration info in flat ASCII files. Valuable data will generally out-live any one program, machine, programming language or use. Data is only useful as long as it's being used, and flat files help ensure that data is usable for the longest possible time. For complex data structures where flat text really isn't appropriate, use a structured text format like XML instead: you can always strip-out the mark-up to get at the raw data.
- Use software leverage to your advantage. Many programmers have only a superficial understanding of the importance of re-usable code modules. Code re-use helps one take advantage of software leverage, a powerful concept that some Unix developers use to create numerous applications in a comparatively short time.
- Use shell scripts to increase leverage and portability. Scripts generate huge leverage - every line of script can invoke several "proper" programs each with several thousand lines of code. A programmer who can't re-use other programs is condemned to re-write them.
- Avoid captive user interfaces. A program which prevents to user using any other commands for the duration "captures" the user and prevents him from taking advantage of other commands. A program should be usable in many modalities to maximise its usefulness.
- Make every program a filter. The fundamental nature of all software programs is that they can only modify data, never create it. Therefore they should be written to function as filters since they are filters.
The minor tenets
- Allow the user to tailor the environment. No single decision will suit all users - so don't force one upon them. The more tailorable an environment is, the more users can match it to their needs and the more they'll like it.
- Make operating system kernels small and lightweight. Despite the never-ending push for new features, Unix developers prefer to keep the most central part of the operating system small. They don't always succeed at this, but this is their goal.
- Use lower case and keep it short. Using the lower case is a tradition in the Unix environment that has persisted long after the reason for doing so (that it's easier to read text with descenders on a teletype) disappeared.
- Save trees. Data committed to paper is essentially dead. There are good reasons for keeping all text on-line and using powerful tools to manipulate it.
- Silence is golden. A silent command is often more usable, providing the function asked for and nothing more. You can always provide wrappers for people who prefer a more conversational tone. (See RuleOfSilence, compare with SilentFailureNoisySuccess)
- Think parallel. Most tasks are composed of sub-tasks which may be attacked in parallel. This also applies to user interactions. Parallelism can save a great deal of time and frustration.
- The sum of the parts is greater than the whole. A large application built from a collection of smaller programs is more flexible and hence more useful than a single large program. The same functional capability may exist in both solutions, but the collection-of-small-programs approach is the more forward-looking of the two.
- Look for the 90% solution. Doing 100% of anything is difficult. Doing only 90% is far more efficient and cost-effective. Handle the 90% and let the 10% fend for themselves - often they'll handle their own special requirements far better than you would anyway. (EightyTwentyRule)
- Worse is better. That which is cheap but effective is far more likely to proliferate than that which is high quality and expensive. The PC-compatible world borrowed this idea and made quite a go of it....
- Think hierarchically. Hierarchies allow tasks and attributes to be applied uniformly across nested elements. This is a powerful idea that encourages decomposition and modularity. (Counterview: LimitsOfHierarchies)
And some, equally important ones, not normally voiced.
- Implementation simplicity is more important that interface simplicity.
- Not even jwz formulated it thus, IIRC. It was "simplicity of implementation instead of simplicity of using code" or something thereabouts. Unix interfaces are not particularly complicated; they just force extra work upon the user.
- I would be interested in seeing an example of this design choice.
- CeeLanguage, perhaps? EdIsTheStandardTextEditor might be even more apt. The original shell (pre-Bourne, even) was quite primitive and not especially good as an interactive shell.
- That misses the mark. The v6 shell was simple, certainly, but it was better than most, perhaps even better than all, other CLIs on small computers at the time (16 bit minicomputers, not larger e.g. 36 bit computers), and in that sense, was neither primitive nor bad as an interactive shell.
- Well, the Unix filesystem API is "simple" (open, read, write, seek, close, link, unlink, ...) but no system call is guaranteed to succeed (not even close(), pun intended) and few are guaranteed to either do something totally or nothing at all.
- Make it run on the cheapest/slowest hardware
- Doesn't this conflict with "Choose portability over efficiency" above?
- Not really, since low-end hardware seems to reliably take over the market after a few iterations. Look at how many high-end systems are x86-based these days, and how few people cared when SGI died and took their shiny Indy boxes with them. For older examples, DigitalEquipmentCorporation's MiniComputers? were pretty pitiful in 1960 but a decade or so later Unix (another low-end solution that won big) was able to ride them into a respectably dominant marketshare. Then DEC itself was killed from below when the x86 machines got interesting...
SGI: I'm not dead yet!
NASDAQ: Here -- he says he's not dead!
CUSTOMER: Yes, he is.
SGI: I'm not!
NASDAQ: He isn't.
CUSTOMER: Well, he will be soon, he's very ill.
SGI: I'm getting better!
CUSTOMER: No, you're not -- you'll be stone dead in a moment.
NASDAQ: Oh, I can't trade him like that -- it's against
regulations.
SGI: I don't want to be delisted!
CUSTOMER: Oh, don't be such a baby.
NASDAQ: I can't take him...
SGI: I feel fine!
SGI: I think I'll go for a walk.
SGI (singing): I feel happy... I feel happy.
CUSTOMER: You're not fooling anyone y'know.
[with apologies to Monty Python and the Holy Grail]
See SmallIsBeautiful, DoOneThingAndOneThingOnly, EarlyPrototyping, PowerOfPlainText, IncrementalUnixShellDevelopment, PipesAndFilters, ManPage, RuleOfSilence, WorseIsBetter.