本译文取自浙大BBS飘渺水云间,原文地址;译者pegasus的BBS帐号已注销,无法联络,本转载未征得原译者同意,仅供学习参考。

【 以下文字转载自 LinuxApp 讨论区 】 【 原文由 pegasus 所发表 】 试着翻译一个小节,不足之处希望多提建议。如果各位能容忍在下的翻译风格:)多多鼓励哦!!!!

第二章 人类的一小步

概述

大约在30年以前,当美国人一边驾驶着大型汽车,一边享受着各国的羡慕目光的时候,大众公司(Volkswagen)却在美国展开一场广告战,主题为“浓缩就是精品”(small is beautiful)。在那个时候,这家德国汽车制造商似乎很不合时宜。大众甲壳虫虽然在欧洲风靡一时,但是如果把它放在美国这块土地上却得有点滑稽,那简直是巨人堆里的侏儒。然而,大众仍然坚持让小型车留了下来。

然后没有预料到的事情发生了:中东石油巨头们向世界表明,他们完全可以在某些事情上达成协议──而这里的“某些事”就是指大幅抬高石油价格。通过顽固地保留大量的原油,他们倾斜了供求平衡关系使之有利于供给方。汽油的价格猛涨至一美元每加仑。一时间输油管随处可见,因为石油巨头们手持匕首威胁着世界的命脉。

长期以嗜好大型汽车闻名的美国人,也开始意识到“浓缩”确实是“精品”。他们向汽车制造商定购小型汽车以缓解日渐空虚的钱囊,而大众公司就成了他们的恩人。昔日“可笑的小车”如今摇身一变成了“别致的必需品”。

久而久之,人们发现小型汽车比起大型汽车来,拥有一些特殊的优势。除了耗油量的减少,他们还开始喜欢小车的驾驶方式:更像英国跑车而不是长了轮子的大型油轮。把小车塞进拥挤的车库里也是一件轻松的事情。它们的简单使之容易保养维护。

几乎在美国人开始热衷小车的同时,一群在新泽西AT&T贝尔实验室的研究人员也发现,小程序拥有某些优势。他们发觉小程序像小车一样,比起大程序来更容易控制,更容易修改,更容易维护。这引导我们进入Unix哲学的第一条宗旨。

2.1 宗旨1:浓缩就是精品

假如你要写一个程序,一开始就要设计得小巧,而且要保持它得小巧。不管你是在设计一个简单得过滤程序,还是一个图形包,或者是一个大型数据库,你应该努力把这个程序写到最小。不要忍不住诱惑把它写得庞大无比,努力使之简洁。

传统的程序员内心里面都暗藏编写“大美国”程序的冲动。当他们开始开发项目时,他们似乎希望花费数星期,数月,甚至数年的时间来编写一个能够解决世界上所有问题的程序。这种作法不仅在商业的眼光看来是昂贵的,更重要的是它忽视了现实。

在现实世界里,假如把一些小巧的解决方法组合起来,没有几个问题是不能解决的。我们之所以选择那些庞大的作法解决问题,是因为我们不完全理解那个问题。

科幻小说家Theodore Sturgeon曾经写道:“百分之九十的科幻小说是垃圾。但是百分之九十的任何东西都是垃圾。”传统的软件也是这样的情况。任何某个程序中的很大一部分代码,都是用来做一些与这个程序的功能毫不相干的事情。

你在怀疑吗?让我们来看一个例子。假如你要写一个程序来复制文件A到文件B,下面这些是一个典型复制程序要做的步骤。

1. 要求用户输入源文件名称
2. 检查源文件是否存在
3. 如果源文件不存在,提醒用户
4. 要求用户输入目的文件名称
5. 检查目的文件是否存在
6. 如果目的文件已经存在,询问用户是否要覆盖
7. 打开源文件
8. 告诉用户源文件是否为空。如果必要的话可以退出
9. 打开目的文件
10. 把数据从源文件复制到目的文件
11. 关闭源文件
12. 关闭目的文件

注意:在第10步文件才被复制。其他的步骤虽然需要,但是与复制文件毫不相干。要是进一步仔细观察,你会发现剩余的步骤除了在复制文件里用到,在其他很多任务中都会被使用到。它们碰巧在这里被使用到,但是它们不是真正的任务组成部分。

一个优秀的Unix程序应该提供步骤10的功能,也应该仅仅提供步骤10的功能。更进一步说,一个严格遵守Unix哲学的程序应该是,在被调用之初已经获取了合法的源文件名和目的文件名。它应该只负责复制数据。显然,假如一个程序所做的只是复制数据,它就真的是一个很小的程序。

这就给我们留下了一个问题:合法的源文件名和目的文件名从那里来?答案很简单:从其它的小程序来。这些其它的程序实现这些功能,诸如获取文件名,检查文件是否存在,还有判断文件是否非空。

“等等。”你也许会想。我们是不是在说Unix包含一些只是检查文件存在性的程序?是的!标准的Unix发行版本内置了数以百计的小指令和小应用程序,而它们本身做很少的工作。一些指令,比如test指令,只实现看起来很单调的功能,譬如检查文件是否可读等等。如果这样听起来不是很重要,你就要意识到test指令是Unix最频繁用到的指令之一(注1)。

小程序自身并没有做很多事情。它们通常仅仅只实现一个或者两个功能。但是把它们结合起来的话,你会感觉到真正的强大。整体功能会大于局部功能的简单加合。一些大型的复杂的问题可以迎刃而解。通过简单地把它们敲到命令行里面,你就可以编写新地应用程序。

注1:一些Unix/Linux的shell(命令解释器),譬如bash,已经把test指令内嵌到shell里面,这样做可以不需要调用新的进程来执行这个指令,因此也就节省了开销。这样做的缺点在于,如果你一直不停地往shell加入指令,由于Unix/Linux产生新进程的方式,最终会导致非shell指令的执行会耗费很大的开销。所以一种更好的方式是:相信经常用到的命令已经驻留在shell的缓冲区里。这样的话就不需要从磁盘读出这些命令,否则会有极其昂贵的时间开销。

Translated by Pegasus 23-Feb-2004