软件工程 — Unix 编程艺术

Unix 编程艺术 这本书主要介绍了 Unix 系统领域的一些文化和设计哲学,本书最初在2006 年出版,译者在序言里也说发现本书作者 ESR(Eric S·Raymond)是个美国愤青,所以书中的内容也肯定不是教科书的论调,很多观点随着时间发展到现在,需要读者自己思考并做出判断。

哲学 #

Unix 倾向于提供机制,而不是策略。从长远考虑,策略相对短寿,而机制才会长存。

程序得以形成严丝合缝的工具套装,而不是应景的解决对策。

Unix 具有从头到脚的灵活性。

Unix 哲学是自下而上,而不是自上而下的。

Unix 哲学是这样的:一个程序只做一件事,并做好。程序要能协作。程序要能处理文本流,因为这是最通用的接口。

原则 #

Unix 管道的发明人、Unix 传统的奠基人之一 Doug McIlroy 曾经说过:

  • 让每个程序就做好一件事。如果有新任务,就重新开始,不要往原程序中加入新功能而搞得复杂。
  • 假定每个程序的输出都会成为另一个程序的输入,哪怕那个程序还是未知的。输出中不要有无关的信息干扰。避免使用严格的分栏格式和二进制格式输入。不要坚持使用交互式输入。
  • 尽可能早地将设计和编译的软件投入试用,哪怕是操作系统也不例外,理想情况下,应该是在几星期内。对拙劣的代码别犹豫,扔掉重写。
  • 优先使用工具而不是拙劣的帮助来减轻编程任务的负担。工欲善其事,必先利其器。

Rob Pike,最伟大的C语言大师之一,在《Notes on C Programming》中从另一个稍微不同的角度表述了 Unix 的哲学:

  1. 原则1:你无法断定程序会在什么地方耗费运行时间。瓶颈经常出现在想不到的地方,所以别急于胡乱找个地方改代码,除非你已经证实那儿就是瓶颈所在。
  2. 原则2:估量。在你没对代码进行估量,特别是没找到最耗时的那部分之前,别去优化速度。
  3. 原则3:花哨的算法在n很小时通常很慢,而n通常很小。花哨算法的常数复杂度很大。除非你确定n总是很大,否则不要用花哨算法(即使n很大,也优先考虑原则2)。
  4. 原则4:花哨的算法比简单算法更容易出bug、更难实现。尽量使用简单的算法配合简单的数据结构。
  5. 原则5:数据压倒一切。如果已经选择了正确的数据结构并且把一切都组织得井井有条,正确的算法也就不言自明。编程的核心是数据结构,而不是算法。
  6. 原则6:没有原则6。

Unix 哲学中更多的内容不是这些先哲们口头表述出来的,而是由他们所作的一切和 Unix 本身所作出的榜样体现出来的。从整体上来说,可以概括为以下几点:

  1. 模块原则:使用简洁的接口拼合简单的部件。
  2. 清晰原则:清晰胜于机巧。
  3. 组合原则:设计时考虑拼接组合。
  4. 分离原则:策略同机制分离,接口同引擎分离。
  5. 简洁原则:设计要简洁,复杂度能低则低。
  6. 吝啬原则:除非确无它法,不要编写庞大的程序。
  7. 透明性原则:设计要可见,以便审查和调试。
  8. 健壮原则:健壮源于透明与简洁。
  9. 表示原则:把知识叠入数据以求逻辑质朴而健壮。
  10. 通俗原则:接口设计避免标新立异。
  11. 缄默原则:如果一个程序没什么好说的,就沉默。
  12. 补救原则:出现异常时,马上退出并给出足够错误信息。
  13. 经济原则:宁花机器一分,不花程序员一秒。
  14. 生成原则:避免手工hack,尽量编写程序去生成程序。
  15. 优化原则:雕琢前先要有原型,跑之前先学会走。
  16. 多样原则:决不相信所谓“不二法门”的断言。
  17. 扩展原则:设计着眼未来,未来总比预想来得快

模块原则 #

汇编语言、编译语言、流程图、过程化编程、结构化编程、所谓的人工智能、第四代编程语言、面向对象、以及软件开发的方法论,不计其数的解决之道被抛售者吹得神乎其神。但实际上这些都用处不大,原因恰恰在于它们“成功”地将程序的复杂度提升到了人脑几乎不能处理的地步。

要编制复杂软件而又不至于一败涂地的唯一方法就是降低其整体复杂度——用清晰的接口把若干简单的模块组合成一个复杂软件。如此一来,多数问题只会局限于某个局部,那么就还有希望对局部进行改进而不至牵动全身。

清晰原则 #

优雅而清晰的代码不仅不容易崩溃——而且更易于让后来的修改者立刻理解。这点非常重要,尤其是说不定若干年后回过头来修改这些代码的人可能恰恰就是你自己。

永远不要去吃力地解读一段晦涩的代码三次。第一次也许侥幸成功,但如果发现必须重新解读一遍——离第一次太久了,具体细节无从回想——那么你该注释代码了,这样第三次就相对不会那么痛苦了。—Henry Spencer

组合原则 #

如果程序彼此之间不能有效通信,那么软件就难免会陷入复杂度的泥淖。

优化原则 #

我最有成效的一天就是扔掉了 1000 行代码。—Ken Thompson

先制作原型,再精雕细琢。

优化之前先确保能用。

先能走,再学跑。

先求运行,再求正确,最后求快。

97% 的时间里,我们不应考虑蝇头小利的效率提升:过早优化是万恶之源。(这句话在这本书里说了四遍)。

多样原则 #

对于软件设计和实现来说,Unix 传统有一点很好,即从不相信任何所谓的“不二法门”。Unix 奉行的是广泛采用多种语言、开放的可扩展系统和用户定制机制。

拓展原则 #

所有的Unix哲学浓缩为一条铁律,那就是各地编程大师们奉为圭臬的 “KISS” 原则。

kiss

态度 #

看到该做的就去做 —— 短期来看似乎是多做了,但从长期来看,这才是最佳捷径。如果不能确定什么是对的,那么就只做最少量的工作,确保任务完成就行,至少直到明白什么是对的。

要良好地运用Unix哲学,你应该珍惜你的时间决不浪费。一旦某人已经解决了某个问题,就直接拿来利用,不要让骄傲或偏见拽住你又去重做一遍。永远不要蛮干;要多用巧劲,省下力气到需要的时候再用,好钢用在刀刃上。善用工具,尽可能将一切都自动化。

要良好地运用Unix哲学,你需要具备(或者找回)这种态度。你需要用心。你需要去游戏。你需要乐于探索。

历史 #

对比 #

模块性 #

文本化 #

透明性 #

多道程序设计 #

微型语言 #

生成 #

配置 #

接口 #

优化 #

复杂度 #

语言 #

工具 #

重用 #

可移植性 #

文档 #

开放源码 #

未来 #

参考 #

理查德·马修·斯托曼(Richard Matthew Stallman,简称RMS)是 GCC、GDB、Emacs 的作者,同时是 GUN 宣言的发起人,他的个人网站是 https://stallman.org/

作者 ESR 的另一本书 大教堂与集市 提到了大教堂开发模式与集市模式。

本文共 2411 字,上次修改于 Nov 2, 2022
相关标签: 软件工程, 读书笔记, Linux