← Paul Graham

Programming Bottom-Up

自下而上编程
 ·  Paul Graham  ·  原文

1993 (This essay is from the introduction to On Lisp .) Arc 's name.--> It's a long-standing principle of programming style that the functional elements of a program should not be too large.

1993 (这篇文章摘自 On Lisp 的简介。) Arc 的名字。--> 程序的函数式元素不应该太大,这是编程风格的一个长期存在的原则。

If some component of a program grows beyond the stage where it's readily comprehensible, it becomes a mass of complexity which conceals errors as easily as a big city conceals fugitives.

如果程序的某些组成部分超出了易于理解的阶段,它就会变得非常复杂,很容易隐藏错误,就像大城市隐藏逃犯一样。

Such software will be hard to read, hard to test, and hard to debug.

这样的软件将难以阅读、难以测试、并且难以调试。

In accordance with this principle, a large program must be divided into pieces, and the larger the program, the more it must be divided.

按照这个原则,一个大的程序必须被分成很多块,并且程序越大,必须被分割得越多。

How do you divide a program?

如何划分一个程序?

The traditional approach is called top-down design: you say "the purpose of the program is to do these seven things, so I divide it into seven major subroutines.

传统的方法叫做自上而下的设计:你说“程序的目的是做这七件事,所以我把它分成七个主要的子程序。

The first subroutine has to do these four things, so it in turn will have four of its own subroutines," and so on.

第一个子例程必须执行这四件事,因此它又将有四个自己的子例程,”等等。

This process continues until the whole program has the right level of granularity-- each part large enough to do something substantial, but small enough to be understood as a single unit.

这个过程一直持续到整个程序具有正确的粒度——每个部分都足够大,可以做一些实质性的事情,但又足够小,可以被理解为一个单元。

Experienced Lisp programmers divide up their programs differently.

经验丰富的 Lisp 程序员以不同的方式划分他们的程序。

As well as top-down design, they follow a principle which could be called bottom-up design -- changing the language to suit the problem.

除了自上而下的设计之外,它们还遵循一个可以称为自下而上的设计的原则——改变语言以适应问题。

In Lisp, you don't just write your program down toward the language,

在 Lisp 中,你不只是根据语言编写程序,

you also build the language up toward your program.

您还可以根据您的程序构建语言。

As you're writing a program you may think "I wish Lisp had such-and-such an operator." So you go and write it.

当您编写程序时,您可能会想“我希望 Lisp 有这样那样的运算符”。所以你去写吧。

Afterward you realize that using the new operator would simplify the design of another part of the program, and so on.

后来您意识到使用 new 运算符可以简化程序另一部分的设计,等等。

Language and program evolve together.

语言和程序一起发展。

Like the border between two warring states, the boundary between language and program is drawn and redrawn,

就像两个交战国之间的边界一样,语言和程序之间的边界被划定并重新划定,

until eventually it comes to rest along the mountains and rivers, the natural frontiers of your problem.

直到最终它沿着山脉和河流停歇,这是你问题的自然边界。

In the end your program will look as if the language had been designed for it.

最终你的程序看起来就像是专门为它设计的语言。

And when language and program fit one another well, you end up with code which is clear, small, and efficient.

当语言和程序完美契合时,您最终会得到清晰、小巧且高效的代码。

It's worth emphasizing that bottom-up design doesn't mean just writing the same program in a different order.

值得强调的是,自下而上的设计并不意味着仅仅以不同的顺序编写相同的程序。

When you

当你

work bottom-up, you usually end up with a different program.

自下而上工作,你通常会得到不同的程序。

Instead of a single, monolithic program, you will get a larger language with more abstract operators, and a smaller program written in it.

您将获得一种具有更多抽象运算符的更大语言以及用它编写的更小的程序,而不是单个整体程序。

Instead of a lintel, you'll get an arch.

你会得到一个拱门,而不是门楣。

In typical code, once you abstract out the parts which are merely bookkeeping, what's left is much shorter; the higher you build up the language, the less distance you

在典型的代码中,一旦你抽象出仅仅是簿记的部分,剩下的就会短得多;你的语言积累得越高,你的距离就越短

will have to travel from the top down to it.

必须从上到下到达它。

This brings several advantages: By making the language do more of the work, bottom-up design yields programs which are smaller and more agile.

这带来了几个优点:通过让语言完成更多的工作,自下而上的设计产生更小、更敏捷的程序。

A shorter program doesn't have to be divided into so many components, and fewer components means programs which are easier to read or modify.

较短的程序不必划分为如此多的组件,较少的组件意味着程序更易于阅读或修改。

Fewer components also means fewer connections between components, and thus less chance for errors there.

更少的组件也意味着组件之间的连接更少,从而减少出现错误的机会。

As

作为

industrial designers strive to reduce the number of moving parts in a machine, experienced Lisp programmers use bottom-up design to reduce the size and complexity of their programs.

工业设计师努力减少机器中移动部件的数量,经验丰富的 Lisp 程序员使用自下而上的设计来减少程序的大小和复杂性。

Bottom-up design promotes code re-use.

自下而上的设计促进代码重用。

When you write two or more programs, many of the utilities you wrote for the first program will also be useful in the succeeding ones.

当您编写两个或多个程序时,为第一个程序编写的许多实用程序也将在后续程序中有用。

Once you've acquired a large substrate of utilities, writing a new program can

一旦您获得了大量的实用程序基础,编写一个新程序就可以

take only a fraction of the effort it would require if you had to start with raw Lisp.

如果您必须从原始 Lisp 开始,那么只需花费一小部分精力即可。

Bottom-up design makes programs easier to read.

自下而上的设计使程序更易于阅读。

<!-- %It yields the same result as top-down design %with foresight---the foresight to arrange the branches near the %root of the tree so that among the leaves there is as little %duplication of effort as possible.

<!-- %它与自上而下的设计产生相同的结果 %有远见——有远见地将树枝安排在树的 %根附近,以便在叶子之间有尽可能少的 %重复工作。

--> An instance of this type of abstraction asks the reader to understand a general-purpose operator;

--> 这种抽象类型的实例要求读者理解通用运算符;

an instance of functional abstraction asks the reader to understand a special-purpose subroutine.

函数抽象的实例要求读者理解专用子例程。

[1] Because it causes you always to be on the lookout for patterns in your code, working bottom-up helps to clarify your ideas about the design of your program.

[1] 因为它使您始终在代码中寻找模式,所以自下而上的工作有助于澄清您对程序设计的想法。

If two distant components of a program are similar in form, you'll be led to notice the similarity and perhaps to redesign the program in a simpler way.

如果程序的两个相距较远的组件在形式上相似,您将注意到这种相似性,并可能以更简单的方式重新设计程序。

Bottom-up design is possible to a certain degree in languages other than Lisp.

自下而上的设计在一定程度上在 Lisp 以外的语言中是可能的。

Whenever you see library functions, bottom-up design is happening.

每当你看到库函数时,就会发生自下而上的设计。

However, Lisp gives you much broader powers in this department, and augmenting the language plays a proportionately larger role in Lisp style-- so much so that Lisp is not just a different language, but a whole different way of programming.

然而,Lisp 在这方面赋予了你更广泛的能力,并且增强语言在 Lisp 风格中扮演着相应更大的角色——以至于 Lisp 不仅是一种不同的语言,而且是一种完全不同的编程方式。

It's true that this style of development is better suited to

确实,这种开发方式更适合

programs which can be written by small groups.

可以由小组编写的程序。

However, at the same time, it extends the limits of what can be done by a small group.

然而,与此同时,它扩展了小团体所能做的事情的极限。

In The Mythical Man-Month , Frederick Brooks proposed that the productivity of a group of programmers does not grow linearly with its size.

Frederick Brooks 在《人月神话》中提出,程序员群体的生产力并不随其规模线性增长。

As the size of the group increases, the productivity of individual programmers goes down.

随着团队规模的增加,单个程序员的生产力会下降。

The experience of Lisp programming suggests a more cheerful way

Lisp 编程的经验提出了一种更愉快的方式

to phrase this law: as the size of the group decreases, the productivity of individual programmers goes up.

用这个定律来说:随着团队规模的缩小,程序员个体的生产力就会提高。

A small group wins, relatively speaking, simply because it's smaller.

相对而言,小团体获胜只是因为规模较小。

When a small group also takes advantage of the techniques that Lisp makes possible, it can win outright .

当一个小组也利用 Lisp 所提供的技术时,它就可以彻底获胜。

New: Download On Lisp for Free .

新功能:免费下载 On Lisp。

[1] "But no one can read the program without understanding all your new utilities."

[1]“但是,如果不了解所有新实用程序,就没有人能够阅读该程序。”

To see why such statements are usually mistaken, see Section 4.8.

要了解为什么此类陈述通常是错误的,请参阅第 4.8 节。

中文为机器翻译,仅供参考。