UNIX Philosophy

在很多场合都有人提到UNIX哲学,此前了解Linux时注意到UNIX系统的很多设计哲学都影响深远,便小小搜集一下

Views

这里摘录自 Basics of the Unix Philosophy

下面是汇编了不同人所总结的UNIX哲学

Doug McIlroy, the inventor of Unix pipes and one of the founders of the Unix tradition, had this to say at the time

(i) Make each program do one thing well. To do a new job, build afresh rather than complicate old programs by adding new features.

这就是所谓的KISS原则吧,Keep It Simple, Stupid. 也可以参照面向对象中的单一职责原则,一个部件(工具)只负责处理一个问题,把工具设计地尽量简单(真的吗?),当遇到新的问题时尝试设计新的工具而非向已有工具添加功能. 其他情况则倾向于组合使用不同的工具进行处理

(ii) 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.

这条原则是丰富多彩的Linux命令行世界构建的基础指导原则. 尤其是管道符 | 的发明组合起了各种各样的简单命令,使其共同发挥无限可能的作用,极大地丰富了命令的功能和广度. 这样令所有程序的输出都可以成为另一个程序的输入的设想是超越时代的大胆尝试,事实证明了这种设计的优秀.

(iii) 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.

这个更像是敏捷开发过程?先写出能跑的程序,然后再优化。敢于删掉繁重的代码

(iv) 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.

这条原则使UNIX的使用具有稳定的系统性,我想提出这条原则一定是有原因的,希望能了解到其背后的故事

The Bell System Technical Journal. Bell Laboratories. M. D. McIlroy, E. N. Pinson, and B. A. Tague. “Unix Time-Sharing System Forward”. 1978. 57 (6, part 2). p. 1902.

He later summarized it this way

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.

[Salus] Peter H. Salus. A Quarter-Century of Unix. Addison-Wesley. 1994. ISBN 0-201-54777-5.


Rob Pike, who became one of the great masters of C, offers a slightly different angle in Notes on C Programming

Rule 1. You can’t tell where a program is going to spend its time. Bottlenecks occur in surprising places, so don’t try to second guess and put in a speed hack until you’ve proven that’s where the bottleneck is.

Rule 2. Measure. Don’t tune for speed until you’ve measured, and even then don’t unless one part of the code overwhelms the rest.

Rule 3. Fancy algorithms are slow when n is small, and n is usually small. Fancy algorithms have big constants. Until you know that n is frequently going to be big, don’t get fancy. (Even if n does get big, use Rule 2 first.)

这条规则大概是说不要一味寻求更优的算法,因为复杂度中的n通常是很小的。就算n会变大,也应该先measure

Rule 4. Fancy algorithms are buggier than simple ones, and they’re much harder to implement. Use simple algorithms as well as simple data structures.

更优的算法可能也比简单算法更容易出bug并且更难实现。使用更简单的算法和数据结构

Rule 5. Data dominates. If you’ve chosen the right data structures and organized things well, the algorithms will almost always be self-evident. Data structures, not algorithms, are central to programming.

Data structures matter !

Rule 6. There is no Rule 6.


Ken Thompson, the man who designed and implemented the first Unix, reinforced Pike’s rule 4 with a gnomic maxim worthy of a Zen patriarch:

When in doubt, use brute force.

好!

Summarize

Eric S. Raymond则在The Art of Unix Programming中总结了17条

  1. Rule of Modularity: Write simple parts connected by clean interfaces.

    简单!

  2. Rule of Clarity: Clarity is better than cleverness.

    不要自作聪明

  3. Rule of Composition: Design programs to be connected to other programs.

  4. Rule of Separation: Separate policy from mechanism; separate interfaces from engines.

    机制与策略分离,接口与“引擎”分离

  5. Rule of Simplicity: Design for simplicity; add complexity only where you must.

  6. Rule of Parsimony: Write a big program only when it is clear by demonstration that nothing else will do.

    简洁、小而美

  7. Rule of Transparency: Design for visibility to make inspection and debugging easier.

  8. Rule of Robustness: Robustness is the child of transparency and simplicity.

  9. Rule of Representation: Fold knowledge into data so program logic can be stupid and robust.

    认知转化为数据

  10. Rule of Least Surprise: In interface design, always do the least surprising thing.

  11. Rule of Silence: When a program has nothing surprising to say, it should say nothing.

    没啥要说的就别说了

  12. Rule of Repair: When you must fail, fail noisily and as soon as possible.

    把问题充分、尽早暴露

  13. Rule of Economy: Programmer time is expensive; conserve it in preference to machine time.

    真的吗

  14. Rule of Generation: Avoid hand-hacking; write programs to write programs when you can.

    避免重复劳动,不要手动写重复的代码

  15. Rule of Optimization: Prototype before polishing. Get it working before you optimize it.

    让程序先跑起来再去优化,Make it run, then make it right, then make it fast

  16. Rule of Diversity: Distrust all claims for “one true way”.

    No one true way

  17. Rule of Extensibility: Design for the future, because it will be here sooner than you think.

这些原则一直围绕simple、connect、small、clarity、

“One of my most productive days was throwing away 1,000 lines of code.”

KEN THOMPSON

ppp

综上,UNIX哲学对软件和编程有很多内容,但实际上中心思想非常明确,就是simple,这里的simple应该是足够简洁,不复杂,而不是easy的简单。写尽量小的程序和工具,明确地完成特定的任务,Make each program do one thing well.

和面向对象很相似的一点在于,UNIX也强调隔离与通过接口连接(separation&connection),接口要明确,并且与实现分离。同上面的,每个程序都只做一件事,很容易联想到现实中的只完成特定功能的工具实体。区别在于,UNIX强调通信的数据格式。接口之间用文本格式进行数据通信,因为文本格式是最容易处理、最通用的格式。数据信息也应该存储在文本文件中。尽量不要使用二进制数据进行通信,不要把二进制内容作为输出和输入。

从优化的角度来讲,UNIX的大佬们认为程序员的时间远比机器的时间更宝贵,因此应该先写出能够运行的代码,然后考虑能够实现must do的功能。能实现90%的主要功能,总比尽量不要使用二进制数据进行通信,不要把二进制内容作为输出和输入。。所以,先做出原型,然后列出要实现的功能,把那些功能分成两类:“必须有(Must Have)”和“可以有(Nice-to-Have)。Must have的功能自然不会太多。

不过,这里的简单也要从新的角度来看。UNIX时代尚无如今这么复杂的机器集群,在当时的单机系统中各软件的规模都不算大。现代的互联网公司的大型服务器集群以及上面运行的庞大数量的软件的管理等工作都相当复杂。当时这里仍然强调“简单”,就是要求每个阶段、每个步骤、每个子任务尽量采用最简单的解决方案,这是由于大规模系统内在的不确定性导致的复杂性决定的

Links

系统设计黄金法则:简单之美

Basics of the Unix Philosophy

The Rise of ``Worse is Better’’

Make each program do one thing well.

Scalability lessons from Google, YouTube, Twitter, Amazon, eBay, Facebook and Instagram

总结了Google、YouTube、Twitter、Amazon、eBay、Facebook、Instagram在设计后台数据中心所遇到的教训

Keep it simple - complexity will come naturally over time.

Automate everything, including failure recovery.

Iterate your solutions - be prepared to throw away a working component when you want to scale it up to the next level.

Use the right tool for the job, but don’t be afraid to roll your own solution.

Use caching, where appropriate.

Know when to favor data consistency over data availability, and vice versa.

Achieving Rapid Response Times in Large Online Services(Jeffrey Dean Talk given at Berkeley AMPLab Cloud Seminar, March 26, 2012 (2012))