The Unix Philosophy
Argos Open Tech
The Unix Philosophy The Unix Philosophy is a system design philosophy of using minimalist composable components.
As a software development style the Unix Philosophy advocates building small tools that communicate over a universal interface to create larger systems. Higher level functionality then emerges from the combination of these composable tools instead of from a monolithic program.
Formulations Peter Salus Write programs that do one thing and do it well. Write programs to work together. Write programs to handle text streams, because that is a universal interface. Doug Mcllroy Make each program do one thing well. To do a new job, build afresh rather than complicate old programs by adding new "features". Expect the output of every program to become the input to another, as yet unknown, program. Don't clutter output with extraneous information. Avoid stringently columnar or binary input formats. Don't insist on interactive input. Design and build software, even operating systems, to be tried early, ideally within weeks. Don't hesitate to throw away the clumsy parts and rebuild them. Use tools in preference to unskilled help to lighten a programming task, even if you have to detour to build the tools and expect to throw some of them out after you've finished using them. This is the Unix philosophy: Write programs that do one thing and do it well. Write programs to work together. Write programs to handle text streams, because that is a universal interface.
The notion of "intricate and beautiful complexities" is almost an oxymoron. Unix programmers vie with each other for "simple and beautiful" honors — a point that's implicit in these rules, but is well worth making overt.
Do One Thing and Do It Well The central idea of the Unix Philosophy is to build composable components that do one thing well. Small minimalist components are easier to understand and modify which allows for faster experimentation. New features are added by connecting to existing components or creating a new component. Higher order functionality then emerges from the connections between components.
In Unix style development developers build tools to solve problems instead of using outside help. The limiting factor in software development is typically developer understanding. When modifying a system a developer often spend most of their time trying to understand the system, and a small amount of time making the relevant change. By scaling a single developer with tools they understand communication and understanding burdens are decreased. The volume of internal communication scales O(n3) with the number of developers while their surface area of useful work with the outside world scales O(n2). The modularity and composibility of the Unix Philosophy increases what individual developers can accomplish and makes it easier for developers to share code and work in parallel.
Everything is a File Unix operating systems are based around files. Data is stored in files, configuration is done with files, logs are saved as files, and OS services like input output and communication with other processes is exposed through a file interface.
Examples This is an example of reading and searching a log file with Unix tools.
$ cat logs.txt info: Startup info: Load data info: Processing error: Divide by zero line 42 warning: Calculation failed info: Exiting
$ grep error logs.txt error: Divide by zero line 42
Possible Improvements The Unix Philosophy has traditionally been based around the universal text interface which works well but connecting components with a scripting language or structured data format has many advantages.
A disadvantage of the text interface is that it is difficult to pass data structures or advanced functionality between components which can be done easily using scripting languages like Python and data formats like JSON.
For example, if a programmer wanted to pass a list of dictionaries between two components through a text interface it would require complex parsing. However, this is easily accomplished by passing a JSON object.
[ { "P.J.": 10, "Brian": 6 }, { "Peter": 8 } ]
17016376 Bytes