把程序装入头脑:程序员深度工作的艺术
本文是保罗·格雷厄姆的一篇经典文章,探讨程序员如何像数学家一样将整个程序“装入头脑”,从而能够灵活操控和理解问题空间。他列出了八条实用建议:避免干扰、长时间连续工作、使用简洁的语言(如脚本语言和自底向上编程)、不断重写代码、编写可重读的代码(侧重密度而非排版)、小团队工作、避免多人编辑同一段代码、从小开始。文章指出,许多组织流程(如会议、多人协作、规范文档)恰恰破坏了这种深度思考状态,而优秀的程序员往往通过“反叛”这些流程来取得成果。对于初创公司而言,这恰恰是攻击大公司弱点——无法让单个程序员发挥创造力——的切入点。


A good programmer working intensively on his own code can hold it in his mind the way a mathematician holds a problem he's working on. Mathematicians don't answer questions by working them out on paper the way schoolchildren are taught to. They do more in their heads: they try to understand a problem space well enough that they can walk around it the way you can walk around the memory of the house you grew up in. At its best programming is the same. You hold the whole program in your head, and you can manipulate it at will.
That's particularly valuable at the start of a project, because initially the most important thing is to be able to change what you're doing. Not just to solve the problem in a different way, but to change the problem you're solving.
Your code is your understanding of the problem you're exploring. So it's only when you have your code in your head that you really understand the problem.
优秀程序员在密集编写自己的代码时,能像数学家思考问题一样,将整个程序牢记于心。数学家不像学生那样在纸上演算答案,他们更多地在脑中完成:努力理解问题空间,直至能像漫步于童年故居的记忆中那样自由探索。编程的最高境界也是如此——你脑中装着整个程序,可以随心所欲地操控它。
这在项目初期尤为宝贵,因为最初最重要的就是能随时调整方向。不仅是换种方式解决问题,更是改变所解决的问题本身。
你的代码是你对所探索问题的理解。因此,只有当代码装入脑海时,你才算真正理解了问题。
It's not easy to get a program into your head. If you leave a project for a few months, it can take days to really understand it again when you return to it. Even when you're actively working on a program it can take half an hour to load into your head when you start work each day. And that's in the best case. Ordinary programmers working in typical office conditions never enter this mode. Or to put it more dramatically, ordinary programmers working in typical office conditions never really understand the problems they're solving.
Even the best programmers don't always have the whole program they're working on loaded into their heads. But there are things you can do to help:
把程序装进脑袋并不容易。如果离开项目几个月,重新上手时可能需要好几天才能真正理解。即使你正在积极开发,每天开工时也需要半小时才能将程序加载到脑中——这还是最好的情况。普通程序员在典型办公条件下从未进入这种状态;更直白地说,他们从未真正理解自己正在解决的问题。
即便最优秀的程序员也并非总能完整加载正在开发的程序。但有一些方法可以帮忙:
Avoid distractions. Distractions are bad for many types of work, but especially bad for programming, because programmers tend to operate at the limit of the detail they can handle.
The danger of a distraction depends not on how long it is, but on how much it scrambles your brain. A programmer can leave the office and go and get a sandwich without losing the code in his head. But the wrong kind of interruption can wipe your brain in 30 seconds.
Oddly enough, scheduled distractions may be worse than unscheduled ones. If you know you have a meeting in an hour, you don't even start working on something hard.
避免干扰。干扰对许多工作都有害,但对编程尤其严重,因为程序员往往在脑力极限附近工作。
干扰的危险不在于持续时间,而在于它对大脑的扰乱程度。程序员可以离开办公室去买个三明治而不会丢失脑中的代码,但错误类型的打断能在30秒内清空你的大脑。
奇怪的是,有计划的干扰可能比无计划的更糟。如果你知道一小时后有个会,你甚至不会开始处理困难的工作。
Work in long stretches. Since there's a fixed cost each time you start working on a program, it's more efficient to work in a few long sessions than many short ones. There will of course come a point where you get stupid because you're tired. This varies from person to person. I've heard of people hacking for 36 hours straight, but the most I've ever been able to manage is about 18, and I work best in chunks of no more than 12.
The optimum is not the limit you can physically endure. There's an advantage as well as a cost of breaking up a project. Sometimes when you return to a problem after a rest, you find your unconscious mind has left an answer waiting for you.
长时间连续工作。由于每次启动编程都有固定成本,少数长时段比许多短时段更高效。当然,你会因疲惫而变迟钝,这因人而异。我听说过有人连续编程36小时,但我自己最多只能撑18小时,而且最佳工作块不超过12小时。
最佳时长并非体能的极限。中断项目既有成本也有收益——有时休息后回到问题,你会发现潜意识已经为你留下了答案。
Use succinct languages. More powerful programming languages make programs shorter. And programmers seem to think of programs at least partially in the language they're using to write them. The more succinct the language, the shorter the program, and the easier it is to load and keep in your head.
You can magnify the effect of a powerful language by using a style called bottom-up programming, where you write programs in multiple layers, the lower ones acting as programming languages for those above. If you do this right, you only have to keep the topmost layer in your head.
使用简洁的语言。更强大的编程语言能让程序更短。程序员思考程序时,至少部分地使用他们编写时所使用的语言。语言越简洁,程序越短,也就越容易加载并保持在大脑中。
你可以通过一种称为“自底向上编程”的风格来放大强大语言的效果:将程序写成多层,下层作为上层的编程语言。如果做得好,你只需将最顶层保持在脑中。
Keep rewriting your program. Rewriting a program often yields a cleaner design. But it would have advantages even if it didn't: you have to understand a program completely to rewrite it, so there is no better way to get one loaded into your head.
不断重写你的程序。重写通常能带来更干净的设计,但即使没有,它也有一个好处:要重写你必须完全理解程序,所以这是将程序装入头脑的最佳方法。
Write rereadable code. All programmers know it's good to write readable code. But you yourself are the most important reader. Especially in the beginning; a prototype is a conversation with yourself. And when writing for yourself you have different priorities. If you're writing for other people, you may not want to make code too dense. Some parts of a program may be easiest to read if you spread things out, like an introductory textbook. Whereas if you're writing code to make it easy to reload into your head, it may be best to go for brevity.
编写可重读的代码。所有程序员都知道可读性好很重要,但你自己才是最重要的读者。尤其是在项目初期,原型是你与自己的对话。当为自己编写时,你的优先级不同:如果是为他人编写,你可能不希望代码太密集,而应像入门教科书一样展开;但如果是为了便于重新加载到脑中,则最好追求简洁。
Work in small groups. When you manipulate a program in your head, your vision tends to stop at the edge of the code you own. Other parts you don't understand as well, and more importantly, can't take liberties with. So the smaller the number of programmers, the more completely a project can mutate. If there's just one programmer, as there often is at first, you can do all-encompassing redesigns.
小团队工作。当你在脑中操作程序时,你的视野往往止于自己代码的边界。其他部分你理解得不够,更重要的是不能随意改动。因此,程序员越少,项目就能越彻底地演变。如果只有一个人——就像项目初期常见的那样——你可以进行全方位的重新设计。
Don't have multiple people editing the same piece of code. You never understand other people's code as well as your own. No matter how thoroughly you've read it, you've only read it, not written it. So if a piece of code is written by multiple authors, none of them understand it as well as a single author would.
And of course you can't safely redesign something other people are working on. It's not just that you'd have to ask permission. You don't even let yourself think of such things. Redesigning code with several authors is like changing laws; redesigning code you alone control is like seeing the other interpretation of an ambiguous image.
If you want to put several people to work on a project, divide it into components and give each to one person.
避免多人编辑同一段代码。你永远不会像理解自己的代码那样理解别人的代码。无论你读得多仔细,你只是读过,而不是写过。因此,如果一段代码由多人编写,没有人能像单一作者那样理解它。
当然,你无法安全地重新设计别人正在工作上的代码。不仅需要征得许可,你甚至不允许自己思考这种事情。与多位作者一起重写代码就像修改法律;而独自控制的代码重写则像看到一幅歧义图的另一种解读。
如果你想用多个人做一个项目,把它分成组件,每个组件交给一个人。
Start small. A program gets easier to hold in your head as you become familiar with it. You can start to treat parts as black boxes once you feel confident you've fully explored them. But when you first start working on a project, you're forced to see everything. If you start with too big a problem, you may never quite be able to encompass it. So if you need to write a big, complex program, the best way to begin may not be to write a spec for it, but to write a prototype that solves a subset of the problem. Whatever the advantages of planning, they're often outweighed by the advantages of being able to keep a program in your head.
从小处开始。随着你对程序变得熟悉,它更容易保持在脑中。一旦你确信已经充分探索了某部分,就可以将其视为黑盒。但当你刚开始一个项目时,你必须看到一切。如果一开始的问题太大,你可能永远无法完全掌握它。因此,如果你需要编写一个庞大复杂的程序,最好的开始方式可能不是写规格说明,而是写一个解决子问题的原型。无论规划有多少好处,能保持程序在脑中的优势往往更大。
It's striking how often programmers manage to hit all eight points by accident. Someone has an idea for a new project, but because it's not officially sanctioned, he has to do it in off hours—which turn out to be more productive because there are no distractions. Driven by his enthusiasm for the new project he works on it for many hours at a stretch. Because it's initially just an experiment, instead of a "production" language he uses a mere "scripting" language—which is in fact far more powerful. He completely rewrites the program several times; that wouldn't be justifiable for an official project, but this is a labor of love and he wants it to be perfect. And since no one is going to see it except him, he omits any comments except the note-to-self variety. He works in a small group perforce, because he either hasn't told anyone else about the idea yet, or it seems so unpromising that no one else is allowed to work on it. Even if there is a group, they couldn't have multiple people editing the same code, because it changes too fast for that to be possible. And the project starts small because the idea is small at first; he just has some cool hack he wants to try out.
Even more striking are the number of officially sanctioned projects that manage to do all eight things wrong. In fact, if you look at the way software gets written in most organizations, it's almost as if they were deliberately trying to do things wrong. In a sense, they are.
令人惊讶的是,程序员常常无意中做到全部八点。某人有了一个新项目想法,但因为不被正式认可,他只能在业余时间做——结果反而更高效,因为没有干扰。出于热情,他连续工作数小时。最初只是实验,他用的是“脚本语言”而非“生产语言”,而脚本语言实际上强大得多。他多次彻底重写;这在正式项目中不合理,但这是热爱之劳,他要做到完美。由于只有他自己看,他省略了除给自己看的笔记之外的所有注释。他被迫在小团体中工作,因为要么还没告诉别人,要么想法太不靠谱没人允许参与。即使有团队,也不可能多人编辑同一段代码,因为变化太快。项目从小开始,因为想法最初也很小;他只想尝试某个酷炫的黑客技术。
更引人注目的是,有多少正式项目反而把八点全部做错。事实上,观察大多数组织中软件编写的方式,几乎就像他们故意做错一样——从某种意义上说,的确如此。
One of the defining qualities of organizations since there have been such a thing is to treat individuals as interchangeable parts. This works well for more parallelizable tasks, like fighting wars. For most of history a well-drilled army of professional soldiers could be counted on to beat an army of individual warriors, no matter how valorous. But having ideas is not very parallelizable. And that's what programs are: ideas.
It's not merely true that organizations dislike the idea of depending on individual genius, it's a tautology. It's part of the definition of an organization not to. Of our current concept of an organization, at least.
Maybe we could define a new kind of organization that combined the efforts of individuals without requiring them to be interchangeable. Arguably a market is such a form of organization, though it may be more accurate to describe a market as a degenerate case—as what you get by default when organization isn't possible.
自组织存在以来,其定义性特征之一就是将个体视为可互换的零件。这对于更可并行的任务(如战争)很有效。历史上,训练有素的职业军队总能击败勇猛的个人战士。但产生想法并不太可并行,而程序正是想法。
组织不喜欢依赖个人天才,这不仅是事实,更是同义反复——这是当前组织概念的定义中一部分。
或许我们可以定义一种新型组织,既能结合个体努力,又不需要他们可互换。市场可以说是一种这样的组织,尽管更准确的说法是,市场是一种退化形式——当组织不可能时默认得到的东西。
Probably the best we'll do is some kind of hack, like making the programming parts of an organization work differently from the rest. Perhaps the optimal solution is for big companies not even to try to develop ideas in house, but simply to buy them. But regardless of what the solution turns out to be, the first step is to realize there's a problem. There is a contradiction in the very phrase "software company." The two words are pulling in opposite directions. Any good programmer in a large organization is going to be at odds with it, because organizations are designed to prevent what programmers strive for.
Good programmers manage to get a lot done anyway. But often it requires practically an act of rebellion against the organizations that employ them. Perhaps it will help if more people understand that the way programmers behave is driven by the demands of the work they do. It's not because they're irresponsible that they work in long binges during which they blow off all other obligations, plunge straight into programming instead of writing specs first, and rewrite code that already works. It's not because they're unfriendly that they prefer to work alone, or growl at people who pop their head in the door to say hello. This apparently random collection of annoying habits has a single explanation: the power of holding a program in one's head.
可能最好的办法是一种 hacking 式的修正,比如让组织中的编程部分以不同于其他部分的方式运作。也许大型公司的最优解甚至不是内部开发想法,而是直接购买。但无论解决方案是什么,第一步是意识到问题存在。“软件公司”这个词本身就存在矛盾:两个词在互相对抗。大型组织中的任何优秀程序员都会与之冲突,因为组织的设计就是为了防止程序员所追求的东西。
优秀程序员仍然设法做了很多事,但常常需要近乎叛逆地反抗雇佣他们的组织。如果更多人能理解,程序员的行为方式是由工作需求驱动的,可能会有所帮助。他们长时间连续工作、推掉所有其他义务、直接开始编程而不先写规格、重写已经能运行的代码——这些不是因为不负责任。他们喜欢独自工作、对探头进来说“你好”的人怒吼——也不是因为不友好。这一系列看似随机的烦人习惯只有一个解释:将程序保持在脑海中的力量。
Whether or not understanding this can help large organizations, it can certainly help their competitors. The weakest point in big companies is that they don't let individual programmers do great work. So if you're a little startup, this is the place to attack them. Take on the kind of problems that have to be solved in one big brain.
理解这一点是否能帮助大型组织尚未可知,但肯定能帮助它们的竞争对手。大公司最薄弱之处在于,它们不允许个体程序员做出伟大的工作。所以,如果你是一个小初创公司,这就是攻击它们的切入点——接手那些必须由一个大脑袋来解决的问题。
Thanks to Sam Altman, David Greenspan, Aaron Iba, Jessica Livingston, Robert Morris, Peter Norvig, Lisa Randall, Emmett Shear, Sergei Tsarev, and Stephen Wolfram for reading drafts of this.
感谢 Sam Altman、David Greenspan、Aaron Iba、Jessica Livingston、Robert Morris、Peter Norvig、Lisa Randall、Emmett Shear、Sergei Tsarev 和 Stephen Wolfram 阅读本文的草稿。