史上最伟大的两个软件系统:一个靠260人,一个靠1个人
人类写过的软件里,有两个可以被称为”最伟大”。
一个控制着120吨的机器,把人类送进太空。每秒做数百次决策。不允许崩溃。不允许一次。它运行了30年。
另一个是一个排版程序。一个人写的。起因是他觉得自己那本书的字间距不对。
两个都堪称人类做过的最好的软件。但它们背后的哲学,完全相反。
软件,永远不允许出错
1981年4月12日。哥伦比亚号航天飞机停在肯尼迪航天中心的发射台上。
空重120吨。燃料2000吨。两个人在上面。几分钟后,它将以每小时17500英里的速度冲向太空。
接下来发生的每一件事——点火顺序、姿态修正、数千个传感器的数据融合——全部由软件决定。每秒多次。
这个软件不能崩溃。不能中途重启。计时偏差哪怕三分之二秒,航天飞机就会偏离5公里。
写这些软件的工程师们坐在休斯顿的办公桌前,甚至没在看发射。因为他们已经知道它会正常工作。

1981年,首飞前五周的哥伦比亚号。五台计算机将控制接下来发生的每一毫秒。(NASA)
11个版本,17个Bug
航天飞机软件团队有260名工程师。没有明星,没有大牛。系统的设计从一开始就不依赖任何个人的天才。
他们靠的是一套流程。
以下数字几乎让人难以相信。
最后三个版本的飞行软件——每个42万行代码——每个版本恰好只有一个Bug。
连续11个版本。总共17个Bug。 同等复杂度的商业软件,通常发布时会带5000个。
这不是四舍五入的差异。这是两种文明的差异。
他们甘愿放弃什么
整个开发周期中,有三分之一的时间完全不写代码。
工程师和NASA的人坐在一起,把需求一条一条写下来。极其详尽,直到双方对每一句话都签字确认。没有双方的同意,什么都不改。
举一个例子:给航天飞机加GPS导航,改了6366行代码——只占程序的1.5%。但这个改动的文档:2500页。 每个分支、每个故障模式,在改一行代码之前就全部落在纸上了。
航天飞机软件系统的完整文档:30卷。40000页。

IBM AP-101飞行计算机。四台对每个决策投票,第五台跑着完全不同的软件,随时准备接管。(NASA)
团队还维护着两个数据库,充当集体记忆。
第一个追踪每一行代码——每个版本、每次修改、每次审批,追溯到最初。任何一行代码都能调出完整的历史。每一行都有自己的族谱。
第二个追踪发现过的每一个Bug,追溯将近20年。不只记录Bug是什么,还记录它是怎么被引入的——以及它是怎么穿过每一层审查最终才被逮住的。
第二个数据库不是用来追责的。它是用来找流程漏洞的。每个漏网的Bug触发根因分析。每个根因触发流程更新。
一个版本接一个版本,网越收越紧。直到Bug基本跑光了。
有人问这个团队:这种程度的纪律会扼杀创造力吗?
回答很直白:是的。
工程师按手册走。有人监督你按手册走。你不能即兴发挥。
但创造力没有消失——它去了别的地方。你不能在软件上发挥创造力,但你可以在流程上发挥创造力。
他们做到了。软件工程研究所后来把自己的一些标准,直接照着这个团队的做法建模。航天飞机团队没有采纳最佳实践——他们本身就是最佳实践。
因为字间距不对就停下来的人

Donald Knuth,2005年。他暂停了自己一生中最重要的工作,去修一个排版问题。(Jacob Appelbaum / CC BY-SA 2.5)
1974年,Donald Knuth获得了图灵奖——计算机科学的最高荣誉。那年他36岁。他正在写《计算机程序设计艺术》,一套七卷本的著作,同行们已经把它当圣经。三卷已经完成。
ACM等不及了。没写完就把奖颁给了他。
然后,几年后,Knuth停笔了。
出版社换成了数字排版。他收到了第二卷第二版的校样。他看了看那些页面。数学公式看起来不对。不是灾难性的——大多数读者根本不会注意到。但字间距是偏的。符号之间的空隙有微妙的问题。原来金属活字印刷的美感,没了。
对大多数人来说,这是一个小烦恼。注意到了,也就过去了。
Donald Knuth不是大多数人。
他决定,在继续写自己一生中最重要的著作之前,先把排版问题解决。不是抱怨,是自己动手,从零开始。
他请了假。接下来十年,他造了TeX。
版本号向π收敛
TeX一夜之间改变了学术出版。物理学家、数学家、计算机科学家——任何需要在印刷品中表达精确符号的人——都开始用它。45年后,它仍然是标准。过去40年里你读过的任何一篇严肃的数学或物理论文,几乎都是TeX排版的。
但TeX真正厉害的不是长寿。而是它的版本号所蕴含的自信。
大多数软件:1.0、2.0、3.0。有的用年份。TeX都不用。
TeX的版本号是π的逼近。
3 → 3.1 → 3.14 → 3.141 → 3.1415 → 3.14159…

每次发布多一位数字。TeX向着完美收敛,就像π向着一个永远无法完全抵达的常数收敛:总是更近,永远没到。
Knuth宣布,他去世后,版本号将永久设为π。所有残余的Bug将被重新分类为特性。
他不是在开玩笑。
发不出去的Bug赏金
为了兑现这份自信,Knuth设立了一个Bug赏金。
在TeX中找到一个真正的Bug:2.56美元。 赏金每年翻倍——5.12、10.24、20.48、40.96……
Knuth一辈子都在研究增长函数。他比任何人都清楚指数翻倍意味着什么。但他还是开出了这个条件。
赏金最终涨到了327.68美元——然后停了。不是他关掉了。是因为Bug跑光了。

拿到支票的人没有去银行。他们把它框起来挂墙上。一张Donald Knuth签名的支票——证明你找到了他没发现的东西——作为纪念品的价值远超面额。
每天五分钟
Alan Kay——面向对象编程的发明者、2003年图灵奖得主——讲过一个故事。
60年代末,硅谷每年感恩节有个编程比赛。出题的是人工智能之父John McCarthy。奖品是一只火鸡。
Knuth参赛那年,他赢了所有人。执行时间最快,算法效率最高。而他用的是全场最慢的机器——一台批处理计算机,不是交互式的,只能按周期返回结果。
Kay问他怎么做到的。
“我学编程那会儿,每天能有五分钟的上机时间就很高兴了。我必须让程序第一次就跑对。没有调试。从一开始就用最好的算法。”
每天五分钟。第一次就对。没有迭代。
稀缺变成了一种能力。几十年的限制在他身上刻出了一个标准——那些在快速、宽容的机器上长大的人,从未被迫培养过这种标准。当他最终坐下来写TeX时,这个标准写进了每一行代码。
两条路,同一个终点
两种截然相反的哲学。同一个目的地:软件完美到差距几乎是哲学层面的。
此后再也没有被复制过。
夜雨聆风