中文亮度
本地双语对照页 · 非官方 · 译文:claude-fable-5 · effort max · 260724 · 原文

The Rise of Worse is Better

"更差即更好"的崛起
Richard P. Gabriel · Lucid, Inc(Lisp 大家,本文节选自其 1991 年名文《Lisp: Good News, Bad News, How to Win Big》§2.1)
1991 年

I and just about every designer of Common Lisp and CLOS has had extreme exposure to the MIT/Stanford style of design.

我,以及几乎每一位 Common Lisp 与 CLOS 的设计者,都深度浸泡过 MIT/斯坦福式的设计风格。

The essence of this style can be captured by the phrase the right thing.

这种风格的精髓可以用一个词概括:the right thing("正确的事")。

To such a designer it is important to get all of the following characteristics right:

对这样的设计者来说,以下每一项特质都必须做对:

Simplicity — the design must be simple, both in implementation and interface. It is more important for the interface to be simple than the implementation.

简单(Simplicity)——设计必须简单,实现与接口皆然。接口的简单比实现的简单更重要。

Correctness — the design must be correct in all observable aspects. Incorrectness is simply not allowed.

正确(Correctness)——设计在一切可观察的方面都必须正确。不正确是根本不被允许的。

Consistency — the design must not be inconsistent. A design is allowed to be slightly less simple and less complete to avoid inconsistency. Consistency is as important as correctness.

一致(Consistency)——设计不得自相矛盾。为避免不一致,允许牺牲一点简单和一点完备。一致与正确同等重要。

Completeness — the design must cover as many important situations as is practical. All reasonably expected cases must be covered. Simplicity is not allowed to overly reduce completeness.

完备(Completeness)——设计必须覆盖实践中尽可能多的重要情形。所有合理可预期的情况都必须覆盖到。不允许为了简单而过度削减完备性。

I believe most people would agree that these are good characteristics.

我相信多数人会同意这些都是好品质。

I will call the use of this philosophy of design the MIT approach. Common Lisp (with CLOS) and Scheme represent the MIT approach to design and implementation.

我把奉行这套设计哲学称为 MIT 路线。Common Lisp(含 CLOS)和 Scheme 是 MIT 路线在设计与实现上的代表。

The worse-is-better philosophy is only slightly different:

而"更差即更好"(worse-is-better)哲学,只差了那么一点点:

Simplicity — the design must be simple, both in implementation and interface. It is more important for the implementation to be simple than the interface. Simplicity is the most important consideration in a design.

简单——设计必须简单,实现与接口皆然。但实现的简单比接口的简单更重要。简单是设计中压倒一切的考量。

Correctness — the design must be correct in all observable aspects. It is slightly better to be simple than correct.

正确——设计在一切可观察的方面都必须正确。但简单比正确还要略胜半筹。

Consistency — the design must not be overly inconsistent. Consistency can be sacrificed for simplicity in some cases, but it is better to drop those parts of the design that deal with less common circumstances than to introduce either implementational complexity or inconsistency.

一致——设计不得过分不一致。某些情况下可以为简单牺牲一致;但与其引入实现复杂性或不一致,不如干脆砍掉设计中处理罕见情形的那些部分。

Completeness — the design must cover as many important situations as is practical. All reasonably expected cases should be covered. Completeness can be sacrificed in favor of any other quality. In fact, completeness must be sacrificed whenever implementation simplicity is jeopardized. Consistency can be sacrificed to achieve completeness if simplicity is retained; especially worthless is consistency of interface.

完备——设计应覆盖实践中尽可能多的重要情形,合理可预期的情况都该照顾到。但完备可以为其他任何品质让路;事实上,一旦实现的简单受到威胁,完备就必须被牺牲。若能保住简单,一致也可以为完备让路——尤其一文不值的,是接口的一致性。

Early Unix and C are examples of the use of this school of design, and I will call the use of this design strategy the New Jersey approach.

早期的 Unix 和 C 就是这一设计流派的产物。我把这套设计策略称为新泽西路线(New Jersey approach,因贝尔实验室在新泽西)。

I have intentionally caricatured the worse-is-better philosophy to convince you that it is obviously a bad philosophy and that the New Jersey approach is a bad approach.

我刚才故意把"更差即更好"漫画化了,好让你相信它显然是个坏哲学、新泽西路线是条坏路线。

However, I believe that worse-is-better, even in its strawman form, has better survival characteristics than the-right-thing, and that the New Jersey approach when used for software is a better approach than the MIT approach.

然而我相信:即便是这个稻草人版本的"更差即更好",其生存特性也优于"正确的事";用在软件上,新泽西路线就是比 MIT 路线更好的路线。

The story / 一个故事:PC loser-ing 问题

Let me start out by retelling a story that shows that the MIT/New-Jersey distinction is valid and that proponents of each philosophy actually believe their philosophy is better.

先讲个故事,说明 MIT 与新泽西之分确有其事,且两派信徒都真心认为自家哲学更优。

Two famous people, one from MIT and another from Berkeley (but working on Unix) once met to discuss operating system issues.

两位名人,一位来自 MIT,另一位来自伯克利(但在做 Unix),有次碰面讨论操作系统问题。

The person from MIT was knowledgeable about ITS (the MIT AI Lab operating system) and had been reading the Unix sources.

MIT 那位精通 ITS(MIT 人工智能实验室的操作系统),并且一直在读 Unix 的源码。

He was interested in how Unix solved the PC loser-ing problem.

他好奇 Unix 是怎么解决 "PC loser-ing" 问题的。

The PC loser-ing problem occurs when a user program invokes a system routine to perform a lengthy operation that might have significant state, such as IO buffers.

这个问题发生在:用户程序调用一个系统例程去做耗时操作,操作可能携带可观的状态(比如 IO 缓冲区)。

If an interrupt occurs during the operation, the state of the user program must be saved.

若操作中途来了中断,用户程序的状态必须被保存。

Because the invocation of the system routine is usually a single instruction, the PC of the user program does not adequately capture the state of the process.

而由于系统例程的调用通常只是一条指令,用户程序的程序计数器(PC)不足以充分刻画进程的状态。

The system routine must either back out or press forward.

系统例程要么退回来,要么硬着头皮做完。

The right thing is to back out and restore the user program PC to the instruction that invoked the system routine so that resumption of the user program after the interrupt, for example, re-enters the system routine.

"正确的事"是退回来:把用户程序的 PC 恢复到调用系统例程的那条指令上,这样中断之后程序一恢复,就会重新进入系统例程。

It is called PC loser-ing because the PC is being coerced into loser mode, where loser is the affectionate name for user at MIT.

之所以叫 "PC loser-ing",是因为 PC 被强制进入 "loser 模式"——loser 是 MIT 对 user(用户)的爱称。

The MIT guy did not see any code that handled this case and asked the New Jersey guy how the problem was handled.

MIT 那位没在源码里看到处理这种情况的代码,就问新泽西那位这问题是怎么解决的。

The New Jersey guy said that the Unix folks were aware of the problem, but the solution was for the system routine to always finish, but sometimes an error code would be returned that signaled that the system routine had failed to complete its action.

新泽西那位说,Unix 的人知道这个问题,但解法是让系统例程总是返回——只不过有时会返回一个错误码,表示例程没能完成它的动作。

A correct user program, then, had to check the error code to determine whether to simply try the system routine again.

于是,一个"正确的"用户程序必须检查错误码,来决定要不要把系统例程再调一遍。

The MIT guy did not like this solution because it was not the right thing.

MIT 那位不喜欢这个解法,因为这不是"正确的事"。

The New Jersey guy said that the Unix solution was right because the design philosophy of Unix was simplicity and that the right thing was too complex.

新泽西那位说 Unix 的解法才是对的:Unix 的设计哲学是简单,而"正确的事"太复杂。

Besides, programmers could easily insert this extra test and loop.

再说,程序员很容易自己补上这个检查加重试循环。

The MIT guy pointed out that the implementation was simple but the interface to the functionality was complex.

MIT 那位指出:实现是简单了,但功能的接口复杂了。

The New Jersey guy said that the right tradeoff has been selected in Unix — namely, implementation simplicity was more important than interface simplicity.

新泽西那位答:Unix 选的正是那个对的取舍——实现的简单比接口的简单更重要。

The MIT guy then muttered that sometimes it takes a tough man to make a tender chicken, but the New Jersey guy didn't understand (I'm not sure I do either).

MIT 那位于是嘟囔了一句"有时候得靠硬汉才能炖出嫩鸡"(美国老广告梗),新泽西那位没听懂(我也不确定我懂了)。

Why worse is better / 为什么"更差"反而更好

Now I want to argue that worse-is-better is better.

现在我要论证:更差即更好,真的更好。

C is a programming language designed for writing Unix, and it was designed using the New Jersey approach.

C 是为写 Unix 而设计的语言,走的正是新泽西路线。

C is therefore a language for which it is easy to write a decent compiler, and it requires the programmer to write text that is easy for the compiler to interpret.

因此 C 是一门容易为之写出像样编译器的语言,它要求程序员写出编译器容易理解的文本。

Some have called C a fancy assembly language.

有人管 C 叫"高级一点的汇编"。

Both early Unix and C compilers had simple structures, are easy to port, require few machine resources to run, and provide about 50%-80% of what you want from an operating system and programming language.

早期的 Unix 和 C 编译器结构都简单、易于移植、运行只需很少的机器资源,并提供你对操作系统和编程语言想要的东西的大约 50%–80%。

Half the computers that exist at any point are worse than median (smaller or slower). Unix and C work fine on them.

任一时刻,世上一半的计算机都比中位数差(更小或更慢)。Unix 和 C 在它们上面照样跑得好好的。

The worse-is-better philosophy means that implementation simplicity has highest priority, which means Unix and C are easy to port on such machines.

"更差即更好"意味着实现的简单享有最高优先级,也就意味着 Unix 和 C 在这类机器上极易移植。

Therefore, one expects that if the 50% functionality Unix and C support is satisfactory, they will start to appear everywhere. And they have, haven't they?

于是可以预期:只要 Unix 和 C 提供的那 50% 功能够用,它们就会开始出现在所有地方。事实不正是如此吗?

Unix and C are the ultimate computer viruses.

Unix 和 C,是终极的计算机病毒。

A further benefit of the worse-is-better philosophy is that the programmer is conditioned to sacrifice some safety, convenience, and hassle to get good performance and modest resource use.

"更差即更好"的又一好处:程序员被驯化得愿意牺牲一些安全、便利、省心,去换取好性能和克制的资源占用。

Programs written using the New Jersey approach will work well both in small machines and large ones, and the code will be portable because it is written on top of a virus.

用新泽西路线写的程序,小机器大机器都跑得好,而且代码天然可移植——因为它写在一个病毒之上。

It is important to remember that the initial virus has to be basically good. If so, the viral spread is assured as long as it is portable.

要记住关键一条:初始病毒必须基本上是好的。只要如此,再加上可移植,病毒式传播就是板上钉钉。

Once the virus has spread, there will be pressure to improve it, possibly by increasing its functionality closer to 90%, but users have already been conditioned to accept worse than the right thing.

病毒传开之后,自然会有改进它的压力,功能可能被推到接近 90%——但此时用户早已被驯化,接受了比"正确的事"更差的东西。

Therefore, the worse-is-better software first will gain acceptance, second will condition its users to expect less, and third will be improved to a point that is almost the right thing.

所以"更差即更好"的软件三步走:先赢得接纳,再驯化用户降低期待,最后被改进到几乎就是"正确的事"。

In concrete terms, even though Lisp compilers in 1987 were about as good as C compilers, there are many more compiler experts who want to make C compilers better than want to make Lisp compilers better.

具体说:尽管 1987 年的 Lisp 编译器已和 C 编译器不相上下,想把 C 编译器做得更好的专家,远多于想把 Lisp 编译器做得更好的。

The good news is that in 1995 we will have a good operating system and programming language; the bad news is that they will be Unix and C++.

好消息是:到 1995 年我们会拥有一个好操作系统和一门好语言;坏消息是:它们将是 Unix 和 C++。

There is a final benefit to worse-is-better.

"更差即更好"还有最后一个好处。

Because a New Jersey language and system are not really powerful enough to build complex monolithic software, large systems must be designed to reuse components.

因为新泽西式的语言和系统实在不够强大,撑不起复杂的单体软件,大型系统就必须按组件复用来设计。

Therefore, a tradition of integration springs up.

于是,一种集成的传统应运而生。

How does the right thing stack up? / "正确的事"的下场如何?

There are two basic scenarios: the big complex system scenario and the diamond-like jewel scenario.

有两种基本剧本:大复杂系统剧本,和钻石宝珠剧本。

The big complex system scenario goes like this: First, the right thing needs to be designed. Then its implementation needs to be designed. Finally it is implemented.

大复杂系统剧本是这样的:先要把"正确的事"设计出来,再设计它的实现,最后才动手实现。

Because it is the right thing, it has nearly 100% of desired functionality, and implementation simplicity was never a concern so it takes a long time to implement.

既然是"正确的事",它拥有近 100% 的期望功能;实现的简单从来不在考虑之列,所以实现耗时漫长。

It is large and complex. It requires complex tools to use properly.

它庞大而复杂,用好它还得配上复杂的工具。

The last 20% takes 80% of the effort, and so the right thing takes a long time to get out, and it only runs satisfactorily on the most sophisticated hardware.

最后 20% 的功能吃掉 80% 的工夫,于是"正确的事"迟迟出不了门,而且只在最精良的硬件上才跑得像样。

The diamond-like jewel scenario goes like this: The right thing takes forever to design, but it is quite small at every point along the way.

钻石宝珠剧本则是:设计"正确的事"耗时无穷,但它在过程中的每一刻都小巧玲珑。

To implement it to run fast is either impossible or beyond the capabilities of most implementors.

而要把它实现得跑得快,要么不可能,要么超出多数实现者的能力。

The two scenarios correspond to Common Lisp and Scheme.

这两个剧本,分别对应 Common Lisp 和 Scheme。

The first scenario is also the scenario for classic artificial intelligence software.

第一个剧本,也正是经典人工智能软件的剧本。

AI 接点 · 这句 1991 年的旁白在今天读来意味深长:经典(符号主义)AI 走的正是 MIT 路线——先设计出"正确的"知识表示与推理,再漫长实现,最后困在最后 20% 里。而后来赢下 AI 的深度学习恰是新泽西路线:先拿出只解决 50% 问题、但简单可扩展(可移植到 GPU 集群)的方法,病毒式铺开,再被算力和数据推向 90%。Sutton 的《The Bitter Lesson》可视为本文预言在 AI 领域的三十年验尸报告。

The right thing is frequently a monolithic piece of software, but for no reason other than that the right thing is often designed monolithically. That is, this characteristic is a happenstance.

"正确的事"常常是一坨单体软件——但除了"它总是被单体式地设计"之外别无原因。换言之,这一特征纯属偶然。

The lesson / 教训

The lesson to be learned from this is that it is often undesirable to go for the right thing first.

该学到的教训是:一上来就奔着"正确的事"去,往往并不可取。

It is better to get half of the right thing available so that it spreads like a virus.

更好的做法是先把"正确的事"的一半拿出来用,让它像病毒一样传播。

Once people are hooked on it, take the time to improve it to 90% of the right thing.

等人们上了钩,再花时间把它改进到"正确的事"的九成。

A wrong lesson is to take the parable literally and to conclude that C is the right vehicle for AI software.

错误的教训则是把这则寓言当字面真理,得出"C 是 AI 软件的正确载体"的结论。

The 50% solution has to be basically right, and in this case it isn't.

那 50% 的解必须基本上是对的——而在这件事上,C 并不是。

But, one can conclude only that the Lisp community needs to seriously rethink its position on Lisp design. I will say more about this later.

只能得出一个结论:Lisp 社区需要严肃地重新思考它在 Lisp 设计上的立场。这一点我后面还会再谈。