关于中国IT企业的一些思考

中国的IT企业,现在真正做的好的也就那么几家,大家成长起来的模式差不多,但后续发展方向不同,致使现在命运也有较大区别。

大家统一的发展模式为:快速山寨国外产品-》低价推广迅速占领市场-》打击小竞争对手,巩固霸主地位-》增加自己特色,继续吸引用户

但实际上,第一步大家都差不多,到了第二步就差了比较大了,比如:

1、华为的成长,主要依靠政府政策扶植,有了钱以后,在研发投入比例还算比较高的,然后反过来进入国际市场,从这方面来说,是一个很成功的典型
2、淘宝的成长,主要依靠融资和免费,初中期有效的打击了竞争对手。同时,提升服务质量,进行研发投入,赢得了差异化竞争,同时大力发展了支付宝,为迅速膨胀提供了充分的能量。后来半垄断以后,将这笔免费的钱,都收了回去,呵呵。现在依靠支付宝,在一定意义上,震撼了国内的金融市场,颠覆了行业规则,佩服佩服。
3、腾讯的成长,主要依靠初期没有任何竞争对手,占领了大量的用户群。腾讯最大的资产,现在便是这庞大的用户群体。依靠这个用户群,腾讯干掉了不知多少竞争对手。腾讯的好处是,山寨并超越了不止n家竞争对手。同时,腾讯还是很有危机感的,很舍得在研发上投入的。

另一方面,国内还有几家诡异的IT企业:
1、百度,百度沾了GFW太多的光,而且说到底,百度给大家的印象仍然很负面,还就是一山寨广告公司。其实大家可以看到,百度搜索,从开始至今,没有太多实质性进步,尤其是多个关键词一起搜索时,给人的感觉是就sql的like加union,然后根据广告规则拍拍名,呵呵。其实百度还是在进步的,但除了广告,实在是没有其他差异化核心业务,鬼知道他能走多远。
2、小米,小米至今还是在饥饿营销,然后国人真心爱这一套。说实话,小米由于商店中太多的山寨货,吸引了大量国内用户,也导致了很多高端用户的鄙视,加之硬件集成做的很差,最终沦为屌丝,呵呵。小米好的地方是MIUI可以不断的进步,迎合用户需求,这是其他厂商所欠缺的。但说实话,小米也是这些厂商中,最难脱离山寨这个词的,包袱太重了。
3、360,360同样打出了免费的牌,迅速占领了市场。虽然至今名声不好,而且所有人都知道为什么,但用户还是很实际的啦。其实,360还是做了一些好事的,比如偷偷为用户升级了IE,导致IE6加速退出了国内市场。关键问题是,如何摆脱这个坏名声吧。

先写这么多吧。

Stiff 对九位卓越程序员的采访


Stiff 对九位卓越程序员的采访
作者:Stiff
译者:flynetcn

前言:2006 年,波兰程序员Jaroslaw “sztywny” Rzeszótko (亦称 Stiff)写了一篇文章《Stiff asks, great programmers answer》,不过原英文链接已挂。Dodgy Coder 的博主近期从 Stiff 那得到允许,把文章转发布在他的博客中《Q&A With Nine Great Programmers》。以下为全文:

在一个炎热无聊的下午, 我突发奇想。 我通过公众可以取得的电子邮件地址列表, 向一干牛人们提了 10 个问题, 他们都是我认为很有趣, 而且很佩服的人, 都干了很多大事。 我只用了 5 分钟来准备这些问题 — 这些问题是我打算私底下如果有机会和牛人们说话, 就说谈个 10 分钟吧, 就会问到的, 那时候我也不会有时间去想那么多。 最后的两个问题其实跟编程无关, 只是我碰到谁都会问他的, 算是我个人的爱好好了。 不是人人都想回答这些问题, 没有关系。 这是我第一次”采访”别人, 难免犯了一些小错, 当别人开始回答问题时, 我自己却跑开了…… 但先别管这个, 我从这些东东里学到很多东西, 这绝对是一次价值非凡的体验。

不是每个人都答复了我的邮件, 也不是所有的人都想回答这些问题的, 可能以后我还会收到, 但我实在等不及了, 现在发表的这些可能随时都会更新的哦。(更新:Bjarne Stroustrup 的回复内容于 03.08.2006 补上 —— Jaroslaw)

明星阵容:
●Linus Torvalds :Linux kernel作者。
●Dave Thomas:《Pragmatic Programmer | 程序员修炼之道》和《Programming Ruby》和其他优秀书籍的作者。 你可以到这里来了解他的编程思想。
●David Heinemeier Hansson:写了 Rails Framework- 新鲜热辣的 web 开发框架。他的博客在这里。
●Steve Yegge:可能是最不为人所知的, 但也是回答得最有趣的一个, 他的博客很有名, 也是关于编程的。 他也是游戏 “Wyvern” 的作者。
●Peter Norvig:Google 的研究部主管, 著名的 Lisper, 写过很著名的 (至少在某些圈子里) AI 方面的书。 他的博客。
●Guido Van Rossum:Python发明者。
●Bjarne Stroustrup:C++ 之父,个人主页。
●James Gosling:Java 之父。(个人博客)
●Tim Bray:XML 与 Atom 规范缔造者之一,他的博客。

现在上主菜了:

1. 您如何学的编程? 上过什么学校? 有用吗? 还是您根本就不鸟学校的事 :) ?

Steve Yegge:

我自己在一台 HP 计算器上开始编程的, 用他们的 RPN 堆栈语言, 当时 17 岁。 之前也学过几次编程, 但都没有真正去学。 HP 的 28c 和 48g 科学计算器性能强劲, 文档也齐全。 我在 48g 上写了一个 3D 线框查看器 — 我有一本 3D 图形编程的书, Pascal 的, 花了好大力气把书里的例程转成 RPN 堆栈语言。 最后它成功运行了, 真是甜蜜的回忆。 之后我就买了一台 PC 还有 Turbo Pascal, 努力地学习编程。 当我去大学读 CS 时我已经是个象模象样的程序员了。 (注意: CS 不是 Counter-Strike)

后来我去了 University of Washington 并在那里得到 CS 学位。 这是绝对值得努力的, 我建议所有的程序员在条件允许的情况下都要尽力攻读 CS 学位。

Linus Torvalds:

我没在学校里学编程, 大部分是我自己看书然后就动手干了起来(一开始在 Commodore VIC-20 上, 后来在 Sinclair QL 上)。

这么说吧, 我尤其认为大学是非常有用的。 我没有选择上技工学校, 而是上了 Helsinki University, 那里偏重理论, 所以那里的教学并不集中在编程上面(编程只是一小部份, 总之我算是很”不务正业”的), 大部分课程集中在基本概念和诸如复杂度分析上面。

那些东西看起来很闷甚至是在浪费精神, 但我认为很有用, 我非常喜欢它们。 我认为我可能是那方面会做的更好。

David Heinemeier Hansson:

我从建立自己的个人主页开始学习编程。 后来我又想增加一些动态的内容, 就先学了 ASP 再后来学了 PHP。 当我知道怎样编程以后, 我就去攻读一个计算机科学与工商管理的交叉学位。

Peter Norvig:

我在高中和大学里都学过编程, 但总觉得自己是自学的多。

Dave Thomas:

读中学时我在当地一间专科学院上过电脑课。 我整个儿被迷住了: 我爱上了编程, 并四处找开设有软件课程的学校。 后来我上了 Imperial College, London University 的分部。 当时他们才刚开设软件课程第二年, 说起来很难相信: 教职员工和和学生们一起工作, 把那些东西弄好, 大家从中都获益匪浅。 在那里读的本科课程给我打下了强大的软件开发基础。 我本想呆到博士毕业, 但还没等到开始读博士就被人挖走了。

但是问题的重点是”你怎样学的编程?” 真正的答案是”我还在学编程。” 我想优秀的开发者整个生涯都不断在学习。 这可不仅是学习新语言和新库的问题: 优秀的开发者经年不断的磨练自己的技术, 提升自己的体验。

Guido Van Rossum:

我上了大学, 那里有一台大型主机, 很多计算机课程。 这(上学校)很重要。

James Gosling:

最初我是自学的。 上大学之前我就得到第一份编程工作了。 但我很高兴我上了(大学)。 其乐无穷。 我一直读到拿到了博士学位。

Bjarne Stroustrup:

现在?Aarhus ,后去了剑桥大学。学校教给我很多实用的东西,包括我未来工作中用到的基础。此外,我也从为钱而编程中学到东东,理解了现实世界中的问题,正确性、可维护性、实时交付等等。

Tim Bray:

我原来想当数学教师来着。 数学教学大纲里要求学生研修几门计算机课程。 (结果就糊里糊涂成了计算机科学家?)

2. 您认为程序员最应该拥有什么样的技能?

Steve Yegge:

笔头和口头沟通的技能。 除非你事先把自己的意见清楚地传达给每一个人, 否则当程序员们开始工作时, 你说什么他们都听不见。 程序员应该不倦阅读, 赋诸文字, 上写作课, 甚至学会公开演讲。

Linus Torvalds:

是那种我称之为”品味”的东西。

我向来不以”有多专业”为标准来评价与我共事的人: 有的人很会写代码, 一下就能弄出一大坨, 但他们给别人代码造成的影响则还要大坨, 而这显然是由他们自己的代码风格, 和他们选择的解决方法所造成的。 这就能告诉我他们有没有”品味”, 而真相就是, 没”品味”的人通常也不太好让他去判断别人代码的好坏, 而他自己的代码到最后也不会是十分的好。

但是, 还有。 有一件事非常重要, 特别是在开源的项目里, 那就是沟通好你想干什么, 怎么干的能力。 向别人解释清楚你为什么非要用某种方式干某些事情的能力十分重要, 并非人人有这个能力。

这么说吧, 到最后也会有人搞出好的代码来。 他们可能解释能力不行, 也没什么品味, 但是代码是可以正常工作的。 这是你往往会需要另一个人(一个”品味”特殊的人)去整理那些代码, 使它的适用范围更广, 而仅仅是写出干净的代码, 解决难题不过是作为程序员必需有的最基本的能力而已。

David Heinemeier Hansson:

强烈的价值观。 有能力问自己: 我做的事情有价值吗? 太多太多的程序员把太多太多的精力浪费在无关痛痒的事情上面。 却忽略了那些真正重要的事情。

Peter Norvig:

我觉得没有, 专注算是吧。

Dave Thomas:

激情。

Guido Van Rossum:

你的问题问得太泛, 无法回答。 :-) 我想有能力煮个鸡蛋当早餐就是无价。

James Gosling:

会自我鞭策。 想真正做得好, 你得热爱你所做的东西。

Bjarne Stroustrup

清晰思考的能力:一个程序员必须理解问题并表述解决方案。

Tim Bray:

以事实为依据, 不跟着感觉走。

3. 您觉得数学和物理对程序员重要吗? 为什么?

Steve Yegge:

数学上有一个分支对程序员非常重要, 它叫”离散数学”或”具体数学”。 包括概率学, 组合学, 图论, 归纳证明和其它有用的东西。 我会鼓励所有程序员去学离散数学, 无论他们能学多少。 即使一点点也比完全不会强。

至于传统数学, 我倒不常用到, 但当我需要用到它就会很方便。 举例来说, 之前我只在工作中用到过一次微积分。 我必需为某个服务从象正弦波那样的曲线图中计算出每日交通高峰期负载。 最简单的方法就是求出特定时间内 1/24 曲线的积分。 如果我不懂微积分, 我就做不出合理正确的估算。

在我写 Wyvern 游戏的时候, 我扎实的平面几何知识作用极大。 日常基本工作中用得更多的是代数和线性代数。 但是很少用到三角学和微分方程, 微积分也很少用。

我会说我的数学基础带给我 5% 至 10% 的进步。 如果我懂的更多, 毫无疑问我会变得更好, 所以每个星期我都抽出几个钟头来学习数学。

我喜欢物理, 毕生都在探索尝试掌握量子力学的基本结构。 但我没觉得物理对我作为一个程序员的工作有任何帮助。 当然了, 如果我在物理领域工作, 象 3D 游戏编程, 或某种类型的模拟, 那就不同了。

Linus Torvalds:

我个人认为扎实的数学基础是好事情。 我不大清楚物理会如何, 但我深信懂数学, 有良好的数学基础有助于使你成为更好的程序员。 如果只是因为它们的思维模式相近似 — 你可以建立起自己想要的法则, 但它必须和自我一致。

David Heinemeier Hansson:

一点用都没有。 至少在商业目的的 web 编程上。 我考虑一个人的笔头功夫好会比这重要的多。

Peter Norvig:

是的, 电脑的很多方面来自数学: 归纳, 递归, 逻辑等。

Dave Thomas:

也许吧。 但是老实说, 我没见到他们之间有多大的关联。

然而, 我的的确确发现一个人的音乐才华与他的编程技能有很大的关联。 我也不知道为什么, 我怀疑大脑的某个区域在提升你音乐才能的同时也会提升你的软件开发技巧。

Guido Van Rossum:

数学, 是的(是一部分; 我不管微分方程, 但是代数和逻辑就很重要)。 物理嘛, 我认为没有, 但保持对不同事物的兴趣是一件好事。

James Gosling:

是的! 它们教会你逻辑和推理。。。 。 拥有火眼金睛。 在分析算法时数学无物可替。

Bjarne Stroustrup:

这取决于程序员和编程工作。某些形式的数学分类还是非常有用,物理用的少,但学习物理是学习实用数学的最佳方法之一。

Tim Bray:

就我个人来说, 我几乎从没用过我大学学到的数学知识。

4. 您认为计算机编程的下一个热点是什么? 面向 X 编程, y 语言, 量子计算机, 还是?

Steve Yegge:

我认为 web 应用正逐渐在变成最重要的客户端形式。 它将会逐步淘汰其它的客户端技术: GTK, Java Swing/SWT, Qt, 当然还有 Cocoa 和 Win32/MFC/等那些依赖平台的技术。

这不会在一夜之间发生。 它会在今后十年里慢慢地朝那个方向前进, 可能到 web 应用完全”取得胜利”之前还需要另一个十年。 工具, 语言, API, 协议, 浏览器技术的发展会远远超过今天你所用到的。 这个差距每年都在缩小, 而我则决定从现在起把我所有的开发工作转移到浏览器上来。

Microsoft 和 Apple 当然不愿意看到这些了, 所以至关重要的第一步就是要使一个象 Firefox 那样的开源浏览器取得统治性的市场份额, 然后还需要一些 Firefox-only 的杀手级应用。 (杀手级应用会象 iTunes, 人人都想用它, 会为了它去下载 Firefox。)

Linus Torvalds:

我不认为会有什么”巨大的飞跃”。 我们已经看到很多可以帮助我们减轻日常工作压力的工具 — 高阶语言或者把简单数据库集成到语言里面可能会是主要的一个。 但大部分喋喋不休基本上没起什么作用。

举例来说, 我个人相信 “Visual Basic” 比”面向对象语言”作用更大。 虽然人们嘲笑 VB, 说它是烂语言, 而他们谈论 OO 语言谈了几十年。

是的, VB 不是很好的语言, 但是我认为象 VB 集成的简单 DB 接口基本上比面向对象重要得多。

所以我想会有很多逐步的改进, 硬件性能的提升也会有助于编程, 但我不指望有什么东西会使生产力大幅度提升或者出现什么革命。

至少当真正的 AI 出现时, 我不认为真正的 AI 还需要你去搞什么编程。

David Heinemeier Hansson:

我尽量不去预言未来。 也不怎么相信运气。 预见未来的最好方法就是实现它。

Peter Norvig:

大规模分布式计算。

Dave Thomas:

电脑编程的下一个热点会被下下一个热点吞掉, 周而复始。 我对不停地寻找热点有点反感, 因为当这样会使人们忘记真正的重点: 打好基础。 我们必需更好地和我们的客户交流, 关注所提供的价值, 并为此而自豪。 做到了这些那开发者就能提供更好的软件更好的工具, 而不需要去担心自己是否跟得上潮流。

Guido Van Rossum:

Sorry, 我对水晶球不敏感。 我曾经在 CGI 发明的 5 年后预言了它。 :-)

James Gosling:

我最关心的两件事是并行复制和复杂度。

Bjarne Stroustrup:

我不知道,我不喜欢猜测。

Tim Bray:

不知道。

5. 如果您有三个月去学一门新技术, 您会选什么?

Steve Yegge:

我刚好有 3 个月时间(作兼职), 我正在学 Dojo (http://dojotoolkit。org ) 和高级 AJAX 和DHTML。 我在做一个巨 NB 的 web 应用, 边做边学。 Dojo 真的很酷, 它也一定会与时俱进。

Linus Torvalds:

唔,我真的很喜欢 FPGA 的, 就是一直没有时间坐下来好好地学。 我喜欢直接和硬件对话的感觉: 这说明我为什么最后选择了做 OS, 因为那样(和编译器呆在一起)和硬件的距离最近, 就差你不能亲自去设计和制造它了。

David Heinemeier Hansson:

Mac 上的 Cocoa 编程。

Peter Norvig:

我想多学一点 Javascript。 还有 Flash。

Dave Thomas:

如果”新”指的是 Dave Thomas 的新, 我想去上高强度的钢琴课。

如果”新”指那些技术玩意, 我会选择可帮助残疾人的相关技术。

Guido Van Rossum:

滑雪。

James Gosling:

为了乐趣, 我想学最新的 3D 渲染技术。 我可能会写一个照片-地图渲染器。

Bjarne Stroustrup

在三个月之内,很重要值得学习的东西不多。我认为应当考虑好好完善某个领域的训练。

Tim Bray:

安全, 加密, 数字签名, 身份验证等。 麻烦的是这些东东我从来没学过。

6. 您认为是什么使得有的程序员比别人高效 10 倍甚至 100 倍?

Steve Yegge:

我想如果你停下来想一下为什么运动员不是都一样好的话, 你就会知道答案的。 爱迪生关于天才的那段话也会给你启示。

Linus Torvalds:

我真的不知道。 我想有些人就是能够更好地把精力集中在那些有用的事情上, 我想他们天生就是会这样。 我认识的很多程序员从小就这样。

David Heinemeier Hansson:

把难题转化成”易”题的能力。

Peter Norvig:

调整头脑去适应问题的能力。

Dave Thomas:

他们关心自己所做的。

Guido Van Rossum:

遗传性头脑结构差异。

James Gosling:

他们深思熟虑。 他们不会仓促行事, 七拼八凑。 他们对结果胸有成竹。

Bjarne Stroustrup:

首先,缺乏专业且足够的训练,导致基础太差。第二,有些人有“智慧”(清晰思考和直达事物本质的能力)、经验和工具知识。编程在这些方面有很大空间,因为编程是理论和实践的结合,二者都离不开领域知识。

Tim Bray:

人类思维的多样性令人惊异。

7. 您最喜爱的工具(操作系统, 编程/脚本语言, 编辑器, 版本控制系统, shell, 数据库引擎, 其它您赖以生存的工具)以及您喜欢它们的理由?

Steve Yegge:
操作系统: Unix! 我用 Linux, cygwin, 现在也用经常用 darwin。 它是无法代替的生产工具。 每个程序员必须学会用 /bin 和 /usr/bin 目录里的所有工具。

脚本语言: Ruby。 我精通所有主流脚本语言: Perl, Python, Tcl, Lua, Awk, Bash, 还有一些已经忘了。 但我是个懒人, 而 Ruby 是目前为止最轻松的, 这是天堂里才有的比赛。

编程语言: 没有我最喜爱的; 它们都不好。 我会选择 Java, 因为它强壮, 可移植, 有好工具和库。 但 Java 不进化就得死; 照现在的样子它不足以长期掌握领导地位。

编辑器: Emacs, 因为当前没用比它更好的。

版本控制: SVN。 Perforce 更好, 但很贵。

Shell: Bash, 因为我实在懒得去学其它的。

数据库引擎: 当然是 MySQL, 没有更合适的了。

其它: 我发现 GIMP 无法评价, 它的不直观也令人抓狂。 我用它多年却总是干不成什么。 但我又离不开它, 真是讽刺。

Firefox 是我工具库阵容中日益重要的一员。 当不得已去用 IE 或 Safari 时我会觉得自己就快死了。

注意这些工具(Unix, Emacs, Firefox, GIMP, MySQL, Bash, SVN, Perforce)都有一个共同点: 它们可以扩展; 也就是, 它们都有 API 可以编程。 优秀的程序员懂得如何给它们的工具编程, 而不仅是用它们。

Linus Torvalds:

实际上我没用那么多工具, 我花了些时间写了我自己的工具。 操作系统这块最大, 还有我自己的版本控制系统(Git), 我用的编辑器(micro-emacs)也是经过我定制和扩展的。

除了那三块, 我最关心的是邮件阅读器。 我一直用 Pine — 不是因为它最好, 而是因为我习惯了, 它也提供了我所需要的一切而且没什么毛病。

David Heinemeier Hansson:

OS X, TextMate, Ruby, Subversion, MySQL。 这就是我当前的组合。 我喜欢那些漂亮而且专注于自己职责的那些工具。

Peter Norvig:

不喜欢全部主流的 OS – Windows, Mac, Linux。 喜欢 Python, Lisp 和 Emacs。

Dave Thomas:

用了 Linux 10 年, 几年前改用 Macs 了。 工具不需要好到特别好, 但不能是需要经常去维护的, 而必须是能让人用的。

我不会永远只用一种工具: 我经常尽可能地切换不同的工具以获得更好的体验。 目前我用的是 OSX, Emacs, TextMate, Rails, Ruby, SVN, CVS, Rake, make, xsltproc, TeX, MySQL, Postgres, 还有一大堆小工具。 谁知道明年我会用什么。

Guido Van Rossum:

Unix/Linux, Python, vi+emacs, Firefox。

James Gosling:

这些天来我住在 NetBeans 里面。 他帮我做了我想要的一切, 非常清晰直接和有效。 这是我住过的最舒服的环境。

Bjarne Stroustrup:

Unix、sam(一个极简的文本编辑器),当然还得有一个出色的 C++ 编译器。

Tim Bray:

我喜欢类 Unix 操作系统, 象 Python 和 Ruby 那样的动态语言跟象 Java 那种静态类型语言(特别是 Java 的 API), Emacs, 随便, bash, 随便, NetBeans。

8. 您最喜爱的电脑编程方面的书是哪一本?

Steve Yegge:

老兄, 这问题真要命。 也许是 GEB(《哥德尔、艾舍尔、巴赫书:集异璧之大成》) 吧, 虽然这本书不是严格的编程类书籍。 如果你特指”最喜爱的编程书”, 那也许就是 SICP (mitpress。mit。edu/* sicp*/) 了。

Linus Torvalds:

呃。 我最近喜欢读幻想小说, 或非电脑类的书(旧书一本: Richard Dawkins 的 “The Selfish Gene”)

说到编程方面, 跃然脑海的唯一真正编程书就是 Kernighan 和 Ritchie 经典的 “The C Programming Language”, 因为它实在是太有用了, 而且又薄又耐读。 想想你基本能从这本书中学会我们这个时代最重要的编程语言之一, 而它又是那么薄那么耐读, 这不能不说是一个奇迹。

还有很多我喜爱的书是跟编程本身无关的, 而是关于计算机结构和硬件方面的。 这里面当然有 Patterson 和 Hennessy 关于计算机结构的书, 对我个人而言可能还应该包括 Crawford 和 Gelsinger 的 “Programming the 80386″, 它是我刚开始 Linux 时的工具书。

基于相同的原因, 我还喜欢 Andrew Tanenbaum 的 “Operating Systems: Design and Implementation”。

David Heinemeier Hansson:

我喜欢 《Extreme Programming Explained | 解析极限编程》, 因为它反传统的思想; 《Patterns of Enterprise Application Architecture》, 因为它打破抽象与具体之间的平衡。

Peter Norvig:

《Structure and Interpretation of Computer Programs | 计算机程序的构造和解释》

Dave Thomas:

这取决于你如何定义”最喜爱”。 可能这方面我读过的最好的书是 IBM 的 “IBM/360 Principles of Operation”。

Guido Van Rossum:

Neil Stephenson 的 “Quicksilver”。

James Gosling:

Jon Bentley 写的《编程珠玑》。

Bjarne Stroustrup:

K&R 的《C程序设计语言》

Tim Bray:

Bentley 的《编程珠玑》

9. 您最喜爱的非电脑编程类书籍?

Steve Yegge:

只有一本? 这不可能。 太多了, 太难选。

这个月我读过的好书有 “Stardust” (Neil Gaiman) 和 “The Mind’s I” (Hofstadter/Dennet)。

我最喜爱的作家是 Kurt Vonnegut, Jr。 和 Jack Vance。

Linus Torvalds:

嗯, 我已经提到过 Dawkins 的 “The Selfish Gene”。 在幻想小说方面, 我读过很多, 都很好, 但是很少有称得上”最喜爱的”。 我很少再去读读过的书, 选择也会随时间改变。 多数是科幻类的, 象 Heinlein 的 “Stranger in a Strange Land” 就是我少年时期最喜爱的, 但现在也渐渐淡忘了……

David Heinemeier Hansson:

“1984″, George Orwell。

Guido Van Rossum:

Neil Stephenson 的 “Quicksilver”。

James Gosling:

“Guns, Germs & Steel”, Jared Diamond

Bjarne Stroustrup:

一直在变化。目前喜欢?O’Brian’s Aubrey/Maturin 系列书

Tim Bray:

Ivan Denisovich 的 “One Day in the Life”

10. 您最喜爱的乐队/歌手/组合?

Steve Yegge:

最喜爱种类: 古典, 动漫音乐, 游戏音乐
最喜爱作曲家: Rachmaninoff, Chopin, Bach
最喜爱歌手/演奏家: David Russell (classical guitar), Sviatoslav Richter(piano)
最喜爱动漫音乐: Last Exile, Haibane Renmei

Linus Torvalds:

我不常听音乐, 要是听的话, 我会听老摇滚歌曲, 范围从 Pink Floyd 到 Beatles 到 Queen 到 The Who。

David Heinemeier Hansson:

种类很多。 Beth Orton, Aimee Mann, Jewel, Lauryn Hill。 其实, 你看看我举的例子她们都是弹吉他的女孩 ;)。

Guido Van Rossum:

Philip Glass。

James Gosling:

我比较喜欢民谣歌手: Christine Lavin, Woody Guthrie, Pete Seeger…

Bjarne Stroustrup:

乐队: The Dixie Chicks;作曲家:贝多芬

Tim Bray:

去看我的博客。

注:原文中有些链接已经失效了,如果大家对大神的博客感兴趣的话,自己google一下吧,很容易找到的。如果对原文感兴趣的话,可以点击下面的地址哦。
英文原文
译文原文

十年编程无师自通


十年编程无师自通
作者:Peter Norvig
翻译:郭晓刚(foosleeper@163.net)
最后修订日期:2004-3-19

为什么每个人都急不可耐?

走进任何一家书店,你会看见《Teach Yourself Java in 7 Days》(7天Java无师自通)的旁边是一长排看不到尽头的类似书籍,它们要教会你Visual Basic、Windows、Internet等等,而只需要几天甚至几小时。我在Amazon.com上进行了如下搜索:pubdate: after 1992 and title: days and (title: learn or title: teach yourself)(出版日期:1992年后 and 书名:天 and (书名:学会 or 书名:无师自通))我一共得到了248个搜索结果。前面的78个是计算机书籍(第79个是《Learn Bengali in 30 days》,30天学会孟加拉语)。我把关键词“days”换成“hours”,得到了非常相似的结果:这次有253本书,头77本是计算机书籍,第78本是《Teach Yourself Grammar and Style in 24 Hours》(24小时学会文法和文体)。头200本书中,有96%是计算机书籍。

结论是,要么是人们非常急于学会计算机,要么就是不知道为什么计算机惊人地简单,比任何东西都容易学会。没有一本书是要在几天里教会人们欣赏贝多芬或者量子物理学,甚至怎样给狗打扮。

让我们来分析一下像《Learn Pascal in Three Days》(3天学会Pascal)这样的题目到底是什么意思:

• 学会:在3天时间里,你不够时间写一些有意义的程序,并从它们的失败与成功中学习。你不够时间跟一些有经验的程序员一起工作,你不会知道在那样的环境中是什么滋味。简而言之,没有足够的时间让你学到很多东西。所以这些书谈论的只是表面上的精通,而非深入的理解。如Alexander Pope(译注:英国诗人、作家,1688-1744)所言,一知半解是危险的(a little learning is a dangerous thing)。

• Pascal:在3天时间里你可以学会Pascal的语法(如果你已经会一门类似的语言),但你无法学到多少如何运用这些语法。简而言之,如果你是,比如说一个Basic程序员,你可以学会用Pascal语法写出Basic风格的程序,但你学不到Pascal真正的优点(和缺点)。那关键在哪里?Alan Perlis(译注:ACM第一任主席,图灵奖得主,1922-1990)曾经说过:“如果一门语言不能影响你对编程的想法,那它就不值得去学”。另一种观点是,有时候你不得不学一点Pascal(更可能是Visual Basic和JavaScript之类)的皮毛,因为你需要接触现有的工具,用来完成特定的任务。但此时你不是在学习如何编程,你是在学习如何完成任务。

• 3天:不幸的是,这是不够的,正如下一节所言。

十年编程无师自通

一些研究者(Hayes、Bloom)的研究表明,在许多领域,都需要大约10 年时间才能培养出专业技能,包括国际象棋、作曲、绘画、钢琴、游泳、网球,以及神经心理学和拓扑学的研究。似乎并不存在真正的捷径:即使是莫扎特,他4 岁就显露出音乐天才,在他写出世界级的音乐之前仍然用了超过13年时间。再看另一种音乐类型的代表–披头士,他们似乎是在1964年的Ed Sullivan节目中突然冒头的。但其实他们从1957年就开始表演了,即使他们很早就显示出了巨大的吸引力,他们第一次真正的成功之作《Sgt. Peppers》也要到1967年才发行。Samuel Johnson(译注:英国诗人)认为10 年还是不够的:“任何领域的卓越成就都只能通过一生的努力来获得;稍低一点的代价也换不来。”(Excellence in any department can be attained only by the labor of a lifetime; it is not to be purchased at a lesser price.) 乔叟(译注:Chaucer,英国诗人,1340-1400)也抱怨说:“生命如此短暂,掌握技艺却要如此长久。”(the lyf so short, the craft so long to lerne.)

下面是我在编程这个行当里获得成功的处方:

• 对编程感兴趣,因为乐趣而去编程。确定始终都能保持足够的乐趣,以致你能够将10年时间投入其中。

• 跟其他程序员交谈;阅读其他程序。这比任何书籍或训练课程都更重要。

• 编程。最好的学习是从实践中学习。用更加技术性的语言来讲,“个体在特定领域最高水平的表现不是作为长期的经验的结果而自动获得的,但即使是非常富有经验的个体也可以通过刻意的努力而提高其表现水平。”(p. 366),而且“最有效的学习要求为特定个体制定适当难度的任务,有意义的反馈,以及重复及改正错误的机会。”(p. 20-21)《Cognition in Practice: Mind, Mathematics, and Culture in Everyday Life》(在实践中认知:心智、数学和日常生活的文化)是关于这个观点的一本有趣的参考书。

• 如果你愿意,在大学里花上4年时间(或者再花几年读研究生)。这能让你获得一些工作的入门资格,还能让你对此领域有更深入的理解,但如果你不喜欢进学校,(作出一点牺牲)你在工作中也同样能获得类似的经验。在任何情况下,单从书本上学习都是不够的。“计算机科学的教育不会让任何人成为内行的程序员,正如研究画笔和颜料不会让任何人成为内行的画家”,Eric Raymond,《The New Hacker’s Dictionary》(新黑客字典)的作者如是说。我曾经雇用过的最优秀的程序员之一仅有高中学历;但他创造出了许多伟大的软件,甚至有讨论他本人的新闻组,而且股票期权让他达到我无法企及的富有程度(译注:指Jamie Zawinski,XEmacs和Netscape Navigator的作者)。

• 跟别的程序员一起完成项目。在一些项目中成为最好的程序员;在其他一些项目中当最差的一个。当你是最好的程序员时,你要测试自己领导项目的能力,并通过你的洞见鼓舞其他人。当你是最差的时候,你学习高手们在做些什么,以及他们不喜欢做什么(因为他们让你帮他们做那些事)。

• 接手别的程序员完成项目。用心理解别人编写的程序。看看在没有最初的程序员在场的时候理解和修改程序需要些什么。想一想怎样设计你的程序才能让别人接手维护你的程序时更容易一些。

• 学会至少半打编程语言。包括一门支持类抽象(class abstraction)的语言(如Java或C++),一门支持函数抽象(functional abstraction)的语言(如Lisp或ML),一门支持句法抽象(syntactic abstraction)的语言(如Lisp),一门支持说明性规约(declarative specification)的语言(如Prolog或C++模版),一门支持协程(coroutine)的语言(如Icon或Scheme),以及一门支持并行处理(parallelism)的语言(如Sisal)。

• 记住在“计算机科学”这个词组里包含“计算机”这个词。了解你的计算机执行一条指令要多长时间,从内存中取一个word要多长时间(包括缓存命中和未命中的情况),从磁盘上读取连续的数据要多长时间,定位到磁盘上的新位置又要多长时间。(答案在这里。)

• 尝试参与到一项语言标准化工作中。可以是ANSI C++委员会,也可以是决定自己团队的编码风格到底采用2个空格的缩进还是4个。不论是哪一种,你都可以学到在这门语言中到底人们喜欢些什么,他们有多喜欢,甚至有可能稍微了解为什么他们会有这样的感觉。

• 拥有尽快从语言标准化工作中抽身的良好判断力。

抱着这些想法,我很怀疑从书上到底能学到多少东西。在我第一个孩子出生前,我读完了所有“怎样……”的书,却仍然感到自己是个茫无头绪的新手。30个月后,我第二个孩子出生的时候,我重新拿起那些书来复习了吗?不。相反,我依靠我自己的经验,结果比专家写的几千页东西更有用更靠得住。
Fred Brooks在他的短文《No Silver Bullets》(没有银弹)中确立了如何发现杰出的软件设计者的三步规划:

1. 尽早系统地识别出最好的设计者群体。
2. 指派一个事业上的导师负责有潜质的对象的发展,小心地帮他保持职业生涯的履历。
3. 让成长中的设计师们有机会互相影响,互相激励。

这实际上是假定了有些人本身就具有成为杰出设计师的必要潜质;要做的只是引导他们前进。Alan Perlis说得更简洁:“每个人都可以被教授如何雕塑;而对米开朗基罗来说,能教给他的倒是怎样能够不去雕塑。杰出的程序员也一样”。

所以尽管去买那些Java书;你很可能会从中找到些用处。但你的生活,或者你作为程序员的真正的专业技术,并不会因此在24小时、24天甚至24个月内发生真正的变化。

参考文献
Bloom, Benjamin (ed.) Developing Talent in Young People, Ballantine, 1985.
Brooks, Fred, No Silver Bullets, IEEE Computer, vol. 20, no. 4, 1987, p. 10-19.
Hayes, John R., Complete Problem Solver, Lawrence Erlbaum, 1989.
Lave, Jean, Cognition in Practice: Mind, Mathematics, and Culture in Everyday Life, Cambridge University Press, 1988.

答案
各种操作的计时,2001年夏天在一台典型的1GHz PC上完成:

执行单条指令 1 纳秒 = (1/1,000,000,000) 秒
从L1缓存中取一个字 2 纳秒
从主内存中取一个字 10 纳秒
从连续的磁盘位置中取一个字 200 纳秒
从新的磁盘位置中取一个字(寻址) 8,000,000纳秒 = 8毫秒

脚注
T. Capey指出Amazon上面《Complete Problem Solver》的页面中,《Teach Yourself Bengali in 21 days》和《Teach Yourself Grammar and Style》被列在了“购买此书的顾客还买了以下书籍”栏目里面。我猜其中一大部分察看这两本书的人都是从我这里过去的。

Teach Yourself Programming in Ten Years


Teach Yourself Programming in Ten Years
Peter Norvig

Why is everyone in such a rush?

Walk into any bookstore, and you’ll see how to Teach Yourself Java in 24 Hours alongside endless variations offering to teach C, SQL, Ruby, Algorithms, and so on in a few days or hours. The Amazon advanced search for [title: teach, yourself, hours, since: 2000 and found 512 such books. Of the top ten, nine are programming books (the other is about bookkeeping). Similar results come from replacing “teach yourself” with “learn” or “hours” with “days.”

The conclusion is that either people are in a big rush to learn about programming, or that programming is somehow fabulously easier to learn than anything else. Felleisen et al. give a nod to this trend in their book How to Design Programs, when they say “Bad programming is easy. Idiots can learn it in 21 days, even if they are dummies.” The Abtruse Goose comic also had their take.

Let’s analyze what a title like Teach Yourself C++ in 24 Hours could mean:
• Teach Yourself: In 24 hours you won’t have time to write several significant programs, and learn from your successes and failures with them. You won’t have time to work with an experienced programmer and understand what it is like to live in a C++ environment. In short, you won’t have time to learn much. So the book can only be talking about a superficial familiarity, not a deep understanding. As Alexander Pope said, a little learning is a dangerous thing.

• C++: In 24 hours you might be able to learn some of the syntax of C++ (if you already know another language), but you couldn’t learn much about how to use the language. In short, if you were, say, a Basic programmer, you could learn to write programs in the style of Basic using C++ syntax, but you couldn’t learn what C++ is actually good (and bad) for. So what’s the point? Alan Perlis once said: “A language that doesn’t affect the way you think about programming, is not worth knowing”. One possible point is that you have to learn a tiny bit of C++ (or more likely, something like JavaScript or Processing) because you need to interface with an existing tool to accomplish a specific task. But then you’re not learning how to program; you’re learning to accomplish that task.

• in 24 Hours: Unfortunately, this is not enough, as the next section shows.

Teach Yourself Programming in Ten Years

Researchers (Bloom (1985), Bryan & Harter (1899), Hayes (1989), Simmon & Chase (1973)) have shown it takes about ten years to develop expertise in any of a wide variety of areas, including chess playing, music composition, telegraph operation, painting, piano playing, swimming, tennis, and research in neuropsychology and topology. The key is deliberative practice: not just doing it again and again, but challenging yourself with a task that is just beyond your current ability, trying it, analyzing your performance while and after doing it, and correcting any mistakes. Then repeat. And repeat again. There appear to be no real shortcuts: even Mozart, who was a musical prodigy at age 4, took 13 more years before he began to produce world-class music. In another genre, the Beatles seemed to burst onto the scene with a string of #1 hits and an appearance on the Ed Sullivan show in 1964. But they had been playing small clubs in Liverpool and Hamburg since 1957, and while they had mass appeal early on, their first great critical success, Sgt. Peppers, was released in 1967.

Malcolm Gladwell has popularized the idea, although he concentrates on 10,000 hours, not 10 years. Henri Cartier-Bresson (1908-2004) had another metric: “Your first 10,000 photographs are your worst.” (He didn’t anticipate that with digital cameras, some people can reach that mark in a week.) True expertise may take a lifetime: Samuel Johnson (1709-1784) said “Excellence in any department can be attained only by the labor of a lifetime; it is not to be purchased at a lesser price.” And Chaucer (1340-1400) complained “the lyf so short, the craft so long to lerne.” Hippocrates (c. 400BC) is known for the excerpt “ars longa, vita brevis”, which is part of the longer quotation “Ars longa, vita brevis, occasio praeceps, experimentum periculosum, iudicium difficile”, which in English renders as “Life is short, [the] craft long, opportunity fleeting, experiment treacherous, judgment difficult.” Of course, no single number can be the final answer: it doesn’t seem reasonable to assume that all skills (e.g., programming, chess playing, checkers playing, and music playing) could all require exactly the same amount of time to master, nor that all people will take exactly the same amount of time. As Prof. K. Anders Ericsson puts it, “In most domains it’s remarkable how much time even the most talented individuals need in order to reach the highest levels of performance. The 10,000 hour number just gives you a sense that we’re talking years of 10 to 20 hours a week which those who some people would argue are the most innately talented individuals still need to get to the highest level.”

So You Want to be a Programmer

Here’s my recipe for programming success:

• Get interested in programming, and do some because it is fun. Make sure that it keeps being enough fun so that you will be willing to put in your ten years/10,000 hours.

• Program. The best kind of learning is learning by doing. To put it more technically, “the maximal level of performance for individuals in a given domain is not attained automatically as a function of extended experience, but the level of performance can be increased even by highly experienced individuals as a result of deliberate efforts to improve.” (p. 366) and “the most effective learning requires a well-defined task with an appropriate difficulty level for the particular individual, informative feedback, and opportunities for repetition and corrections of errors.” (p. 20-21) The book Cognition in Practice: Mind, Mathematics, and Culture in Everyday Life is an interesting reference for this viewpoint.

• Talk with other programmers; read other programs. This is more important than any book or training course.

• If you want, put in four years at a college (or more at a graduate school). This will give you access to some jobs that require credentials, and it will give you a deeper understanding of the field, but if you don’t enjoy school, you can (with some dedication) get similar experience on your own or on the job. In any case, book learning alone won’t be enough. “Computer science education cannot make anybody an expert programmer any more than studying brushes and pigment can make somebody an expert painter” says Eric Raymond, author of The New Hacker’s Dictionary. One of the best programmers I ever hired had only a High School degree; he’s produced a lot of great software, has his own news group, and made enough in stock options to buy his own nightclub.

• Work on projects with other programmers. Be the best programmer on some projects; be the worst on some others. When you’re the best, you get to test your abilities to lead a project, and to inspire others with your vision. When you’re the worst, you learn what the masters do, and you learn what they don’t like to do (because they make you do it for them).

• Work on projects after other programmers. Understand a program written by someone else. See what it takes to understand and fix it when the original programmers are not around. Think about how to design your programs to make it easier for those who will maintain them after you.

• Learn at least a half dozen programming languages. Include one language that emphasizes class abstractions (like Java or C++), one that emphasizes functional abstraction (like Lisp or ML or Haskell), one that supports syntactic abstraction (like Lisp), one that supports declarative specifications (like Prolog or C++ templates), and one that emphasizes parallelism (like Clojure or Go).

• Remember that there is a “computer” in “computer science”. Know how long it takes your computer to execute an instruction, fetch a word from memory (with and without a cache miss), read consecutive words from disk, and seek to a new location on disk. (Answers here.)

• Get involved in a language standardization effort. It could be the ANSI C++ committee, or it could be deciding if your local coding style will have 2 or 4 space indentation levels. Either way, you learn about what other people like in a language, how deeply they feel so, and perhaps even a little about why they feel so.

• Have the good sense to get off the language standardization effort as quickly as possible.

With all that in mind, its questionable how far you can get just by book learning. Before my first child was born, I read all the How To books, and still felt like a clueless novice. 30 Months later, when my second child was due, did I go back to the books for a refresher? No. Instead, I relied on my personal experience, which turned out to be far more useful and reassuring to me than the thousands of pages written by experts.

Fred Brooks, in his essay No Silver Bullet identified a three-part plan for finding great software designers:
1. Systematically identify top designers as early as possible.
2. Assign a career mentor to be responsible for the development of the prospect and carefully keep a career file.
3. Provide opportunities for growing designers to interact and stimulate each other.

This assumes that some people already have the qualities necessary for being a great designer; the job is to properly coax them along. Alan Perlis put it more succinctly: “Everyone can be taught to sculpt: Michelangelo would have had to be taught how not to. So it is with the great programmers”. Perlis is saying that the greats have some internal quality that transcends their training. But where does the quality come from? Is it innate? Or do they develop it through diligence? As Auguste Gusteau (the fictional chef in Ratatouille) puts it, “anyone can cook, but only the fearless can be great.” I think of it more as willingness to devote a large portion of one’s life to deliberative practice. But maybe fearless is a way to summarize that. Or, as Gusteau’s critic, Anton Ego, says: “Not everyone can become a great artist, but a great artist can come from anywhere.”

So go ahead and buy that Java/Ruby/Javascript/PHP book; you’ll probably get some use out of it. But you won’t change your life, or your real overall expertise as a programmer in 24 hours or 21 days. How about working hard to continually improve over 24 months? Well, now you’re starting to get somewhere…

________________________________________
References

Bloom, Benjamin (ed.) Developing Talent in Young People, Ballantine, 1985.
Brooks, Fred, No Silver Bullets, IEEE Computer, vol. 20, no. 4, 1987, p. 10-19.
Bryan, W.L. & Harter, N. “Studies on the telegraphic language: The acquisition of a hierarchy of habits. Psychology Review, 1899, 8, 345-375
Hayes, John R., Complete Problem Solver Lawrence Erlbaum, 1989.
Chase, William G. & Simon, Herbert A. “Perception in Chess” Cognitive Psychology, 1973, 4, 55-81.
Lave, Jean, Cognition in Practice: Mind, Mathematics, and Culture in Everyday Life, Cambridge University Press, 1988.
________________________________________
Answers

Approximate timing for various operations on a typical PC:

execute typical instruction 1/1,000,000,000 sec = 1 nanosec
fetch from L1 cache memory 0.5 nanosec
branch misprediction 5 nanosec
fetch from L2 cache memory 7 nanosec
Mutex lock/unlock 25 nanosec
fetch from main memory 100 nanosec
send 2K bytes over 1Gbps network 20,000 nanosec
read 1MB sequentially from memory 250,000 nanosec
fetch from new disk location (seek) 8,000,000 nanosec
read 1MB sequentially from disk 20,000,000 nanosec
send packet US to Europe and back 150 milliseconds = 150,000,000 nanosec

________________________________________
Appendix: Language Choice

Several people have asked what programming language they should learn first. There is no one answer, but consider these points:

• Use your friends. When asked “what operating system should I use, Windows, Unix, or Mac?”, my answer is usually: “use whatever your friends use.” The advantage you get from learning from your friends will offset any intrinsic difference between OS, or between programming languages. Also consider your future friends: the community of programmers that you will be a part of if you continue. Does your chosen language have a large growing community or a small dying one? Are there books, web sites, and online forums to get answers from? Do you like the people in those forums?

• Keep it simple. Programming languages such as C++ and Java are designed for professional development by large teams of experienced programmers who are concerned about the run-time efficiency of their code. As a result, these languages have complicated parts designed for these circumstances. You’re concerned with learning to program. You don’t need that complication. You want a language that was designed to be easy to learn and remember by a single new programmer.

• Play. Which way would you rather learn to play the piano: the normal, interactive way, in which you hear each note as soon as you hit a key, or “batch” mode, in which you only hear the notes after you finish a whole song? Clearly, interactive mode makes learning easier for the piano, and also for programming. Insist on a language with an interactive mode and use it.

Given these criteria, my recommendations for a first programming language would be Python or Scheme. Another choice is Javascript, not because it is perfectly well-designed for beginners, but because there are so many online tutorials for it, such as Khan Academy’s tutorial. But your circumstances may vary, and there are other good choices. If your age is a single-digit, you might prefer Alice or Squeak or Blockly (older learners might also enjoy these). The important thing is that you choose and get started.

________________________________________
Appendix: Books and Other Resources

Several people have asked what books and web pages they should learn from. I repeat that “book learning alone won’t be enough” but I can recommend the following:

• Scheme: Structure and Interpretation of Computer Programs (Abelson & Sussman) is probably the best introduction to computer science, and it does teach programming as a way of understanding the computer science. You can see online videos of lectures on this book, as well as the complete text online. The book is challenging and will weed out some people who perhaps could be successful with another approach.

• Scheme: How to Design Programs (Felleisen et al.) is one of the best books on how to actually design programs in an elegant and functional way.

• Python: Python Programming: An Intro to CS (Zelle) is a good introduction using Python.

• Python: Several online tutorials are available at Python.org.

• Oz: Concepts, Techniques, and Models of Computer Programming (Van Roy & Haridi) is seen by some as the modern-day successor to Abelson & Sussman. It is a tour through the big ideas of programming, covering a wider range than Abelson & Sussman while being perhaps easier to read and follow. It uses a language, Oz, that is not widely known but serves as a basis for learning other languages.

________________________________________
Notes

T. Capey points out that the Complete Problem Solver page on Amazon now has the “Teach Yourself Bengali in 21 days” and “Teach Yourself Grammar and Style” books under the “Customers who shopped for this item also shopped for these items” section. I guess that a large portion of the people who look at that book are coming from this page. Thanks to Ross Cohen for help with Hippocrates.

提问的智慧


提问的智慧
Eric Steven Raymond;Thyrsus Enterprises;esr@thyrsus.com
Rick Moen;respond-auto@linuxmafia.com
Copyright © 2001,2006,2014 Eric S. Raymond, Rick Moen
中文翻译:Ryan Wu

声明
许多项目在他们的使用协助/说明网页中链接了本指南,这么做很好,我们也鼓励大家都这么做。但如果你是负责管理这个项目网页的人,请在超链接附近的显着位置上注明:

本指南不提供此项目的实际支持服务!

我们已经深刻领教到少了上述声明所带来的痛苦。因为少了这点声明,我们不停地被一些白痴纠缠。这些白痴认为既然我们发布了这本指南,那么我们就有责任解决世上所有的技术问题。

如果你是因为需要某些协助而正在阅读这本指南,并且最后离开是因为发现从本指南作者们身上得不到直接的协助,那么你就是我们所说的那些白痴之一。别问我们问题,我们只会忽略你。我们在这本指南中是教你如何从那些真正懂得你所遇到软件或硬件问题的人取得协助,而99%的情况下那不会是我们。除非你确定本指南的作者之一刚好是你所遇到的问题领域的专家,否则请不要打扰我们,这样大家都会开心一点。

简介

在黑客的世界里,当你拋出一个技术问题时,最终是否能得到有用的回答,往往取决于你所提问和追问的方式。本指南将教你如何正确的提问以获得你满意的答案。

不只是黑客,现在开放源代码(Open Source)软件已经相当盛行,你常常也可以由其他有经验的使用者身上得到好答案,这是件**好事**;使用者比起黑客来,往往对那些新手常遇到的问题更宽容一些。然而,将有经验的使用者视为黑客,并采用本指南所提的方法与他们沟通,同样也是能从他们身上得到满意回答的最有效方式。

首先你应该明白,黑客们喜爱有挑战性的问题,或者能激发我们思维的好问题。如果我们并非如此,那我们也不会成为你想询问的对象。如果你给了我们一个值得反复咀嚼玩味的好问题,我们自会对你感激不尽。好问题是激励,是厚礼。好问题可以提高我们的理解力,而且通常会暴露我们以前从没意识到或者思考过的问题。对黑客而言,”好问题!”是诚挚的大力称赞。

尽管如此,黑客们有着蔑视或傲慢面对简单问题的坏名声,这有时让我们看起来对新手、无知者似乎较有敌意,但其实不是那样的。

我们不讳言我们对那些不愿思考、或者在发问前不做他们该做的事的人的蔑视。那些人是时间杀手 -– 他们只想索取,从不付出,消耗我们可用在更有趣的问题或更值得回答的人身上的时间。我们称这样的人为 失败者(撸瑟) (由于历史原因,我们有时把它拼作 lusers)。

我们意识到许多人只是想使用我们写的软件,他们对学习技术细节没有兴趣。对大多数人而言,电脑只是种工具,是种达到目的的手段而已。他们有自己的生活并且有更要紧的事要做。我们了解这点,也从不指望每个人都对这些让我们着迷的技术问题感兴趣。尽管如此,我们回答问题的风格是指向那些真正对此有兴趣并愿意主动参与解决问题的人,这一点不会变,也不该变。如果连这都变了,我们就是在降低做自己最擅长的事情上的效率。

我们(在很大程度上)是自愿的,从繁忙的生活中抽出时间来解答疑惑,而且时常被提问淹没。所以我们无情的滤掉一些话题,特别是拋弃那些看起来像失败者的家伙,以便更高效的利用时间来回答赢家(winner)的问题。

如果你厌恶我们的态度,高高在上,或过于傲慢,不妨也设身处地想想。我们并没有要求你向我们屈服 — 事实上,我们大多数人非常乐意与你平等地交流,只要你付出小小努力来满足基本要求,我们就会欢迎你加入我们的文化。但让我们帮助那些不愿意帮助自己的人是没有效率的。无知没有关系,但装白痴就是不行。

所以,你不必在技术上很在行才能吸引我们的注意,但你必须表现出能引导你变得在行的特质 — 机敏、有想法、善于观察、乐于主动参与解决问题。如果你做不到这些使你与众不同的事情,我们建议你花点钱找家商业公司签个技术支持服务合同,而不是要求黑客个人无偿地帮助你。

如果你决定向我们求助,当然你也不希望被视为失败者,更不愿成为失败者中的一员。能立刻得到快速并有效答案的最好方法,就是像赢家那样提问 — 聪明、自信、有解决问题的思路,只是偶尔在特定的问题上需要获得一点帮助。

(欢迎对本指南提出改进意见。你可以 email 你的建议至 esr@thyrsus.com 或 respond-auto@linuxmafia.com。然而请注意,本文并非网络礼节的通用指南,而我们通常会拒绝无助于在技术论坛得到有用答案的建议。)

在提问之前

在你准备要通过电子邮件、新闻群组或者聊天室提出技术问题前,请先做到以下事情:
1. 尝试在你准备提问的论坛的旧文章中搜索答案。
2. 尝试上网搜索以找到答案。
3. 尝试阅读手册以找到答案。
4. 尝试阅读常见问题文件(FAQ)以找到答案。
5. 尝试自己检查或试验以找到答案
6. 向你身边的强者朋友打听以找到答案。
7. 如果你是程序开发者,请尝试阅读源代码以找到答案

当你提出问题的时候,请先表明你已经做了上述的努力;这将有助于树立你并不是一个不劳而获且浪费别人的时间的提问者。如果你能一并表达在做了上述努力的过程中所**学到**的东西会更好,因为我们更乐于回答那些表现出能从答案中学习的人的问题。

运用某些策略,比如先用Google搜索你所遇到的各种错误信息(既搜索Google论坛,也搜索网页),这样很可能直接就找到了能解决问题的文件或邮件列表线索。即使没有结果,在邮件列表或新闻组寻求帮助时加上一句 我在Google中搜过下列句子但没有找到什么有用的东西 也是件好事,即使它只是表明了搜索引擎不能提供哪些帮助。这么做(加上搜索过的字串)也让遇到相似问题的其他人能被搜索引擎引导到你的提问来。

别着急,不要指望几秒钟的Google搜索就能解决一个复杂的问题。在向专家求助之前,再阅读一下常见问题文件(FAQ)、放轻松、坐舒服一些,再花点时间思考一下这个问题。相信我们,他们能从你的提问看出你做了多少阅读与思考,如果你是有备而来,将更有可能得到解答。不要将所有问题一股脑拋出,只因你的第一次搜索没有找到答案(或者找到太多答案)。

准备好你的问题,再将问题仔细的思考过一遍,因为草率的发问只能得到草率的回答,或者根本得不到任何答案。越是能表现出在寻求帮助前你为解决问题所付出的努力,你越有可能得到实质性的帮助。

小心别问错了问题。如果你的问题基于错误的假设,某个普通黑客(J. Random Hacker)多半会一边在心里想着蠢问题…, 一边用无意义的字面解释来答复你,希望着你会从问题的回答(而非你想得到的答案)中汲取教训。

绝不要自以为**够格得到答案,你没有;你并没有。毕竟你没有为这种服务支付任何报酬。你将会是自己去挣到**一个答案,靠提出有内涵的、有趣的、有思维激励作用的问题 –一个有潜力能贡献社区经验的问题,而不仅仅是被动的从他人处索取知识。

另一方面,表明你愿意在找答案的过程中做点什么是一个非常好的开端。谁能给点提示?、我的这个例子里缺了什么?以及我应该检查什么地方比请把我需要的确切的过程贴出来更容易得到答复。因为你表现出只要有人能指个正确方向,你就有完成它的能力和决心。

当你提问时

慎选提问的论坛
小心选择你要提问的场合。如果你做了下述的事情,你很可能被忽略掉或者被看作失败者:
• 在与主题不合的论坛上贴出你的问题
• 在探讨进阶技术问题的论坛张贴非常初级的问题;反之亦然
• 在太多的不同新闻群组上重复转贴同样的问题(cross-post)
• 向既非熟人也没有义务解决你问题的人发送私人电邮

黑客会剔除掉那些搞错场合的问题,以保护他们沟通的渠道不被无关的东西淹没。你不会想让这种事发生在自己身上的。

因此,第一步是找到对的论坛。再说一次,Google和其它搜索引擎还是你的朋友,用它们来找到与你遭遇到困难的软硬件问题最相关的网站。通常那儿都有常见问题(FAQ)、邮件列表及相关说明文件的链接。如果你的努力(包括**阅读**FAQ)都没有结果,网站上也许还有报告Bug(Bug-reporting)的流程或链接,如果是这样,连过去看看。

向陌生的人或论坛发送邮件最可能是风险最大的事情。举例来说,别假设一个提供丰富内容的网页的作者会想充当你的免费顾问。不要对你的问题是否会受到欢迎做太乐观的估计 — 如果你不确定,那就向别处发送,或者压根别发。

在选择论坛、新闻群组或邮件列表时,别太相信名字,先看看FAQ或者许可书以弄清楚你的问题是否切题。发文前先翻翻已有的话题,这样可以让你感受一下那里的文化。事实上,事先在新闻组或邮件列表的历史记录中搜索与你问题相关的关键词是个极好的主意,也许这样就找到答案了。即使没有,也能帮助你归纳出更好的问题。

别像机关枪似的一次”扫射”所有的帮助渠道,这就像大喊大叫一样会使人不快。要一个一个地来。

搞清楚你的主题!最典型的错误之一是在某种致力于跨平台可移植的语言、套件或工具的论坛中提关于Unix或Windows操作系统程序界面的问题。如果你不明白为什么这是大错,最好在搞清楚这之间差异之前什么也别问。

一般来说,在仔细挑选的公共论坛中提问,会比在私有论坛中提同样的问题更容易得到有用的回答。有几个理由可以支持这点,一是看潜在的回复者有多少,二是看观众有多少。黑客较愿意回答那些能帮助到许多人的问题。

可以理解的是,老练的黑客和一些热门软件的作者正在接受过多的错发信息。就像那根最后压垮骆驼背的稻草一样,你的加入也有可能使情况走向极端 — 已经好几次了,一些热门软件的作者从自己软件的支持中抽身出来,因为伴随而来涌入其私人邮箱的无用邮件变得无法忍受。

Stack Overflow

搜索,然后 在 Stack Exchange 问。

近年来,Stack Exchange community 社区已经成为回答技术及其他问题的主要渠道,尤其是那些开放源码的项目。

因为 Google 索引是即时的,在看 Stack Exchange 之前先在 Google 搜索。有很高的机率某人已经问了一个类似的问题,而且 Stack Exchange 网站们往往会是搜索结果中最前面几个。如果你在 Google 上没有找到任何答案,你再到特定相关主题的网站去找。用标签(Tag)搜索能让你更缩小你的搜索结果。

Stack Exchange 已经成长到超过一百个网站,以下是最常用的几个站:
• Super User 是问一些通用的电脑问题,如果你的问题跟代码或是写程序无关,只是一些网络连线之类的,请到这里。
• Stack Overflow 是问写程序有关的问题。
• Server Fault 是问服务器和网管相关的问题。

网站和IRC论坛

本地的使用者群组(user group),或者你所用的 Linux 发行版本也许正在宣传他们的网页论坛或 IRC 频道,并提供新手帮助(在一些非英语国家,新手论坛很可能还是邮件列表), 这些地方是开始提问的好首选,特别是当你觉得遇到的也许只是相对简单或者很普通的问题时。经过宣传的 IRC 频道是公开欢迎提问的地方,通常可以即时得到回应。

事实上,如果程序出的问题只发生在特定 Linux 发行版提供的版本(这很常见),最好先去该发行版的论坛或邮件列表中提问,再到程序本身的论坛或邮件列表提问。(否则)该项目的黑客可能仅仅回复 “用**我们的**版本”。

在任何论坛发文以前,先确认一下有没有搜索功能。如果有,就试着搜索一下问题的几个关键词,也许这会有帮助。如果在此之前你已做过通用的网页搜索(你也该这样做),还是再搜索一下论坛,搜索引擎有可能没来得及索引此论坛的全部内容。

通过论坛或 IRC 频道来提供使用者支持服务有增长的趋势,电子邮件则大多为项目开发者间的交流而保留。所以最好先在论坛或 IRC 中寻求与该项目相关的协助。

第二步,使用项目邮件列表

当某个项目提供开发者邮件列表时,要向列表而不是其中的个别成员提问,即使你确信他能最好地回答你的问题。查一查项目的文件和首页,找到项目的邮件列表并使用它。有几个很好的理由支持我们采用这种办法:
• 任何好到需要向个别开发者提出的问题,也将对整个项目群组有益。反之,如果你认为自己的问题对整个项目群组来说太愚蠢,也不能成为骚扰个别开发者的理由。
• 向列表提问可以分散开发者的负担,个别开发者(尤其是项目领导人)也许太忙以至于没法回答你的问题。
• 大多数邮件列表都会被存档,那些被存档的内容将被搜索引擎索引。如果你向列表提问并得到解答,将来其它人可以通过网页搜索找到你的问题和答案,也就不用再次发问了。
• 如果某些问题经常被问到,开发者可以利用此信息来改进说明文件或软件本身,以使其更清楚。如果只是私下提问,就没有人能看到最常见问题的完整场景。

如果一个项目既有”使用者” 也有”开发者”(或”黑客”)邮件列表或论坛,而你又不会动到那些源代码,那么就向”使用者”列表或论坛提问。不要假设自己会在开发者列表中受到欢迎,那些人多半会将你的提问视为干扰他们开发的噪音。

然而,如果你**确信**你的问题很特别,而且在”使用者” 列表或论坛中几天都没有回复,可以试试前往”开发者”列表或论坛发问。建议你在张贴前最好先暗地里观察几天以了解那里的行事方式(事实上这是参与任何私有或半私有列表的好主意)

如果你找不到一个项目的邮件列表,而只能查到项目维护者的电子邮件地址,尽管向他发信。即使是在这种情况下,也别假设(项目)邮件列表不存在。在你的电子邮件中,请陈述你已经试过但没有找到合适的邮件列表,也提及你不反对将自己的邮件转发给他人(许多人认为,即使没什么秘密,私人电子邮件也不应该被公开。通过允许将你的电子邮件转发他人,你给了相应人员处置你邮件的选择)。

使用有意义且描述明确的标题

在邮件列表、新闻群组或论坛中,大约50字以内的标题是抓住资深专家注意力的好机会。别用喋喋不休的帮帮忙、跪求、急(更别说救命啊!!!!这样让人反感的话,用这种标题会被条件反射式地忽略)来浪费这个机会。不要妄想用你的痛苦程度来打动我们,而是在这点空间中使用极简单扼要的描述方式来提出问题。

一个好标题范例是目标 — 差异式的描述,许多技术支持组织就是这样做的。在目标部分指出是哪一个或哪一组东西有问题,在差异部分则描述与期望的行为不一致的地方。

蠢问题:救命啊!我的笔电不能正常显示了!
聪明问题:X.org 6.8.1的鼠标游标会变形,某牌显卡 MV1005 芯片组。
更聪明问题:X.org 6.8.1的鼠标游标,在某牌显卡 MV1005 芯片组环境下 – 会变形。

编写目标 — 差异 式描述的过程有助于你组织对问题的细緻思考。是什么被影响了? 仅仅是鼠标游标或者还有其它图形?只在 X.org 的 X 版中出现?或只是出现在6.8.1版中? 是针对某牌显卡芯片组?或者只是其中的 MV1005 型号? 一个黑客只需瞄一眼就能够立即明白你的环境**和**你遇到的问题。

总而言之,请想像一下你正在一个只显示标题的存档讨论串(Thread)索引中查寻。让你的标题更好地反映问题,可使下一个搜索类似问题的人能够关注这个讨论串,而不用再次提问相同的问题。

如果你想在回复中提出问题,记得要修改内容标题,以表明你是在问一个问题, 一个看起来像 Re: 测试 或者 Re: 新bug 的标题很难引起足够重视。另外,在不影响连贯性之下,适当引用并删减前文的内容,能给新来的读者留下线索。

对于讨论串,不要直接点击回复来开始一个全新的讨论串,这将限制你的观众。因为有些邮件阅读程序,比如 mutt ,允许使用者按讨论串排序并通过折叠讨论串来隐藏消息,这样做的人永远看不到你发的消息。

仅仅改变标题还不够。mutt 和其它一些邮件阅读程序还会检查邮件标题以外的其它信息,以便为其指定讨论串。所以宁可发一个全新的邮件。

在网页论坛上,好的提问方式稍有不同,因为讨论串与特定的信息紧密结合,并且通常在讨论串外就看不到里面的内容,故通过回复提问,而非改变标题是可接受的。不是所有论坛都允许在回复中出现分离的标题,而且这样做了基本上没有人会去看。不过,通过回复提问,这本身就是暧昧的做法,因为它们只会被正在查看该标题的人读到。所以,除非你**只想**在该讨论串当前活跃的人群中提问,不然还是另起炉灶比较好。

使问题容易回复

以请将你的回复寄到……来结束你的问题多半会使你得不到回答。如果你觉得花几秒钟在邮件客户端设置一下回复地址都麻烦,我们也觉得花几秒钟思考你的问题更麻烦。如果你的邮件程序不支持这样做,换个好点的;如果是操作系统不支持这种邮件程序,也换个好点的。

在论坛,要求通过电子邮件回复是非常无礼的,除非你相信回复的信息可能比较敏感(而且有人会为了某些未知的原因,只让你而不是整个论坛知道答案)。如果你只是想在有人回复讨论串时得到电子邮件提醒,可以要求网页论坛发送给你。几乎所有论坛都支持诸如追踪此讨论串、有回复时发送邮件提醒等功能。

用清晰、正确、精准并语法正确的语句

我们从经验中发现,粗心的提问者通常也会粗心的写程序与思考(我敢打包票)。回答粗心大意者的问题很不值得,我们宁愿把时间耗在别处。

正确的拼字、标点符号和大小写是很重要的。一般来说,如果你觉得这样做很麻烦,不想在乎这些,那我们也觉得麻烦,不想在乎你的提问。花点额外的精力斟酌一下字句,用不着太僵硬与正式 — 事实上,黑客文化很看重能准确地使用非正式、俚语和幽默的语句。但它**必须很**准确,而且有迹象表明你是在思考和关注问题。

正确地拼写、使用标点和大小写,不要将its混淆为it’s,loose搞成lose或者将discrete弄成discreet。不要全部用大写,这会被视为无礼的大声嚷嚷(全部小写也好不到哪去,因为不易阅读。Alan Cox也许可以这样做,但你不行。)

更白话的说,如果你写得像是个半文盲[译注:小白]),那多半得不到理睬。也不要使用即时通讯中的简写或火星文,如将的简化为ㄉ会使你看起来像一个为了少打几个键而省字的小白。更糟的是,如果像个小孩似地鬼画符那绝对是在找死,可以肯定没人会理你(或者最多是给你一大堆指责与挖苦)。

如果在使用非母语的论坛提问,你可以犯点拼写和语法上的小错,但决不能在思考上马虎(没错,我们通常能弄清两者的分别)。同时,除非你知道回复者使用的语言,否则请使用英语书写。繁忙的黑客一般会直接删除用他们看不懂语言写的消息。在网络上英语是通用语言,用英语书写可以将你的问题在尚未被阅读就被直接删除的可能性降到最低。

如果英文是你的外语(Second language),提示潜在回复者你有潜在的语言困难是很好的: [译注:以下附上原文以供使用]
English is not my native language; please excuse typing errors.
• 英文不是我的母语,请原谅我的错字或语法

If you speak $LANGUAGE, please email/PM me; I may need assistance translating my question.
• 如果你说某语言,请寄信/私讯给我;我需要有人协助我翻译我的问题

I am familiar with the technical terms, but some slang expressions and idioms are difficult for me.
• 我对技术名词很熟悉,但对于俗语或是特别用法比较不甚了解。

I’ve posted my question in $LANGUAGE and English. I’ll be glad to translate responses, if you only use one or the other.
• 我把我的问题用某语言和英文写出来,如果你只用一种语言回答,我会乐意将其翻译成另一种。

使用易于读取且标准的文件格式发送问题

如果你人为地将问题搞得难以阅读,它多半会被忽略,人们更愿读易懂的问题,所以:
• 使用纯文字而不是HTML (关闭HTML并不难)

• 使用MIME附件通常是可以的,前提是真正有内容(譬如附带的源代码或patch),而不仅仅是邮件程序生成的模板(譬如只是信件内容的拷贝)。

• 不要发送一段文字只是单行句子但多次断行的邮件(这使得回复部分内容非常困难)。设想你的读者是在80个字符宽的终端机上阅读邮件,最好设置你的断行点小于80字。

• 但是,也**不要**用任何固定断行资料(譬如日志档案拷贝或会话记录)。档案应该原样包含,让回复者有信心他们看到的是和你看到的一样的东西。

• 在英语论坛中,不要使用Quoted-Printable MIME编码发送消息。这种编码对于张贴非ASCII语言可能是必须的,但很多邮件程序并不支持这种编码。当它们分断时,那些文本中四处散布的=20符号既难看也分散注意力,甚至有可能破坏内容的语意。

• 绝对,**永远**不要指望黑客们阅读使用封闭格式编写的文档,像是微软公司的Word或Excel文件等。大多数黑客对此的反应就像有人将还在冒热气的猪粪倒在你门口阶梯上时你的反应一样。即便他们能够处理,他们也很厌恶这么做。

• 如果你从使用Windows的电脑发送电子邮件,关闭微软愚蠢的智能引号功能 (从[选项] > [校订] > [自动校正选项], 按掉智能引号单选框),以免在你的邮件中到处散布垃圾字符。

• 在论坛,勿滥用表情符号和HTML功能(当它们提供时)。一两个表情符号通常没有问题,但花哨的彩色文本倾向于使人认为你是个无能之辈。过滥地使用表情符号、色彩和字体会使你看来像个傻笑的小姑娘。这通常不是个好主意,除非你只是对sex而不是有用的回复更有兴趣。

如果你使用图形用户界面的邮件程序(如微软公司的Outlook或者其它类似的),注意它们的默认设置不一定满足这些要求。大多数这类程序有基于选单的查看源代码命令,用它来检查发送文件夹中的消息,以确保发送的是没有多餘杂质的纯文本文件。

精确的描述问题并言之有物

• 仔细、清楚地描述你的问题或Bug的症状。

• 描述问题发生的环境(机器配置、操作系统、应用程序、以及相关的信息),提供经销商的发行版和版本号(如:Fedora Core 4、Slackware 9.1等)。

• 描述在提问前你是怎样去研究和理解这个问题的。

• 描述在提问前为确定问题而采取的诊断步骤。

• 描述最近做过什么可能相关的硬件或软件变更。

• 尽可能的提供一个可以重现这个问题的既定环境的方法

尽量去揣测一个黑客会怎样反问你,在他提问的时候预先给他答案。

以上几点中,当你报告的是你认为可能在代码中的问题时,给黑客一个可以重现你的问题的环境尤其重要。当你这么做时,你得到有效的回答的机会和速度都会大大的提升。

Simon Tatham写过一篇名为《如何有效的报告Bug》的出色文章。强力推荐你也读一读。

话不在多而在精

你需要提供精确有内容的信息。这并不是要求你简单的把成堆的出错代码或者资料完全转录到你的提问中。如果你有庞大而复杂的测试样例能重现程序挂掉的情境,尽量将它剪裁得越小越好。

这样做的用处至少有三点。 第一,表现出你为简化问题付出了努力,这可以使你得到回答的机会增加; 第二,简化问题使你更有可能得到**有用**的答案; 第三,在精炼你的bug报告的过程中,你很可能就自己找到了解决方法或权宜之计。

别动辄声称找到Bug

当你在使用软件中遇到问题,除非你非常、**非常**的有根据,不要动辄声称找到了Bug。提示:除非你能提供解决问题的源代码补丁,或者对前一版本的回归测试表现出不正确的行为,否则你都多半不够完全确信。这同样适用在网页和文件,如果你(声称)发现了文件的Bug,你应该能提供相应位置的修正或替代文件。

请记得,还有许多其它使用者没遇到你发现的问题,否则你在阅读文件或搜索网页时就应该发现了(你在抱怨前已经做了这些,是吧?)。这也意味着很有可能是你弄错了而不是软件本身有问题。

编写软件的人总是非常辛苦地使它尽可能完美。如果你声称找到了Bug,也就是在质疑他们的能力,即使你是对的,也有可能会冒犯到其中某部分人。这尤其严重当你在标题中嚷嚷着有Bug。

提问时,即使你私下非常确信已经发现一个真正的Bug,最好写得像是**你**做错了什么。如果真的有Bug,你会在回复中看到这点。这样做的话,如果真有Bug,维护者就会向你道歉,这总比你惹恼别人然后欠别人一个道歉要好一点。

可以低声下气,但还是要先做功课

有些人明白他们不该粗鲁或傲慢的提问并要求得到答复,但他们选择另一个极端 — 低声下气:我知道我只是个可悲的新手,一个撸瑟,但…。这既使人困扰,也没有用,尤其是伴随着与实际问题含糊不清的描述时更令人反感。

别用原始灵长类动物的把戏来浪费你我的时间。取而代之的是,尽可能清楚地描述背景条件和你的问题情况。这比低声下气更好地定位了你的位置。

有时网页论坛会设有专为新手提问的版面,如果你真的认为遇到了初学者的问题,到那去就是了,但一样别那么低声下气。

描述问题症状而非猜测

告诉黑客们你认为问题是怎样造成的并没什么帮助。(如果你的推断如此有效,还用向别人求助吗?),因此要确信你原原本本告诉了他们问题的症状,而不是你的解释和理论;让黑客们来推测和诊断。如果你认为陈述自己的猜测很重要,清楚地说明这只是你的猜测,并描述为什么它们不起作用。

蠢问题:我在编译内核时接连遇到 SIG11 错误, 我怀疑某条飞线搭在主板的走线上了,这种情况应该怎样检查最好?

聪明问题:我的组装电脑是 FIC-PA2007 主机板搭载 AMD K6/233 CPU(威盛 Apollo VP2芯片组), 256MB Corsair PC133 SDRAM内存,在编译内核时,从开机20分钟以后就频频产生 SIG11 错误, 但是在头20分钟内从没发生过相同的问题。重新启动也没有用,但是关机一晚上就又能工作20分钟。 所有内存都换过了,没有效果。相关部分的标准编译记录如下…。

由于以上这点似乎让许多人觉得难以配合,这里有句话可以提醒你:所有的诊断专家都来自密苏里州。 美国国务院的官方座右铭则是:让我看看(出自国会议员 Willard D. Vandiver 在1899年时的讲话:我来自一个出产玉米,棉花,牛蒡和民主党人的国家,滔滔雄辩既不能说服我,也不会让我满意。我来自密苏里州,你必须让我看看。) 针对诊断者而言,这并不是一种怀疑,而只是一种真实而有用的需求,以便让他们看到的是与你看到的原始证据尽可能一致的东西,而不是你的猜测与归纳的结论。所以,大方的展示给我们看吧!

按发生时间先后列出问题症状

问题发生前的一系列操作,往往就是对找出问题最有帮助的线索。因此,你的说明里应该包含你的操作步骤,以及机器和软件的反应,直到问题发生。在命令行处理的情况下,提供一段操作记录(例如运行脚本工具所生成的),并引用相关的若干行(如20行)记录会非常有帮助。

如果挂掉的程序有诊断选项(如 -v 的详述开关),试着选择这些能在记录中增加调试信息的选项。记住,多不等于好。试着选取适当的调试级别以便提供有用的信息而不是让读者淹没在垃圾中。

如果你的说明很长(如超过四个段落),在开头简述问题,接下来再按时间顺序详述会有所帮助。这样黑客们在读你的记录时就知道该注意哪些内容了。

描述目标而不是过程

如果你想弄清楚如何做某事(而不是报告一个Bug),在开头就描述你的目标,然后才陈述重现你所卡住的特定步骤。

经常寻求技术帮助的人在心中有个更高层次的目标,而他们在自以为能达到目标的特定道路上被卡住了,然后跑来问该怎么走,但没有意识到这条路本身就有问题。结果要费很大的劲才能搞定。

蠢问题:我怎样才能从某绘图程序的颜色选择器中取得十六进制的的RGB值?

聪明问题:我正试着用替换一幅图片的色码成自己选定的色码,我现在知道的唯一方法是编辑每个色码区块, 但却无法从某绘图程序的颜色选择器取得十六进制的的RGB值。

第二种提问法比较聪明,你可能得到像是建议采用另一个更合适的工具的回复。

别要求使用私人电邮回复

黑客们认为问题的解决过程应该公开、透明,此过程中如果更有经验的人注意到不完整或者不当之处,最初的回复才能够、也应该被纠正。同时,作为提供帮助者也能因为能力和学识被其它同行看到而得到某种奖励。

当你要求私下回复时,这个过程和奖励都被中止。别这样做,让**回复者**来决定是否私下回答 — 如果他真这么做了,通常是因为他认为问题编写太差或者太肤浅,以至于对其它人没有兴趣。

这条规则存在一条有限的例外,如果你确信提问可能会引来大量雷同的回复时,那么这个神奇的提问句会是向我发电邮,我将为论坛归纳这些回复。试着将邮件列表或新闻群组从洪水般的雷同回复中解救出来是非常有礼貌的 — 但你必须信守诺言。

清楚明确的表达你的问题以及需求

漫无边际的提问近乎无休无止的时间黑洞。最有可能给你有用答案的人通常也正是最忙的人(他们忙是因为要亲自完成大部分工作)。这样的人对无节制的时间黑洞相当厌恶,所以他们也倾向于厌恶那些漫无边际的提问。

如果你明确表述需要回答者做什么(如提供指点、发送一段代码、检查你的补丁、或是其他等等),就最有可能得到有用的答案。因为这会定出一个时间和精力的上限,便于回答者能集中精力来帮你。这么做很棒。

要理解专家们所处的世界,请把专业技能想像为充裕的资源,而回复的时间则是稀缺的资源。你要求他们奉献的时间越少,你越有可能从真正专业而且很忙的专家那里得到解答。

所以,界定一下你的问题,使专家花在辨识你的问题和回答所需要付出的时间减到最少,这技巧对你有用答案相当有帮助 — 但这技巧通常和简化问题有所区别。因此,问我想更好的理解X,可否指点一下哪有好一点说明?通常比问你能解释一下X吗?更好。如果你的代码不能运作,通常请别人看看哪里有问题,比要求别人替你改正要明智得多。

询问有关代码的问题时

别要求他人帮你有问题的代码调试而不提示一下应该从何入手。张贴几百行的代码,然后说一声:它不会动会让你完全被忽略。只贴几十行代码,然后说一句:在第七行以后,我期待它显示 ,但实际出现的是 比较有可能让你得到回应。

最有效描述程序问题的方法是提供最精简的Bug展示测试示例(bug-demonstrating test case)。什么是最精简的测试示例? 那是问题的缩影;一小个程序片段能刚好展示出程序的异常行为,而不包含其他令人分散注意力的内容。怎么制作最精简的测试示例?如果你知道哪一行或哪一段代码会造成异常的行为,复制下来并加入足够重现这个状况的代码(例如,足以让这段代码能被编译/直译/被应用程序处理)。如果你无法将问题缩减到一个特定区块,就复制一份代码并移除不影响产生问题行为的部分。总之,测试示例越小越好(查看话不在多而在精一节)。

一般而言,要得到一段相当精简的测试示例并不太容易,但永远先尝试这样做的是种好习惯。这种方式可以帮助你了解如何自行解决这个问题 —- 而且即使你的尝试不成功,黑客们也会看到你在尝试取得答案的过程中付出了努力,这可以让他们更愿意与你合作。

如果你只是想让别人帮忙审查(Review)一下代码,在信的开头就要说出来,并且一定要提到你认为哪一部分特别需要关注以及为什么。

别把自己家庭作业的问题贴上来

黑客们很擅长分辨哪些问题是家庭作业式的问题;因为我们中的大多数都曾自己解决这类问题。同样,这些问题得由**你**来搞定,你会从中学到东西。你可以要求给点提示,但别要求得到完整的解决方案。

如果你怀疑自己碰到了一个家庭作业式的问题,但仍然无法解决,试试在使用者群组,论坛或(最后一招)在项目的使用者邮件列表或论坛中提问。尽管黑客们**会**看出来,但一些有经验的使用者也许仍会给你一些提示。

去掉无意义的提问句

避免用无意义的话结束提问,例如有人能帮我吗?或者这有答案吗?。

首先:如果你对问题的描述不是很好,这样问更是画蛇添足。

其次:由于这样问是画蛇添足,黑客们会很厌烦你 — 而且通常会用逻辑上正确,但毫无意义的回答来表示他们的蔑视, 例如:没错,有人能帮你或者不,没答案。

一般来说,避免用 是或否、对或错、有或没有类型的问句,除非你想得到是或否类型的回答。

即使你很急也不要在标题写紧急

这是你的问题,不是我们的。宣称紧急极有可能事与愿违:大多数黑客会直接删除无礼和自私地企图即时引起关注的问题。更严重的是,紧急这个字(或是其他企图引起关注的标题)通常会被垃圾信过滤器过滤掉 — 你希望能看到你问题的人可能永远也看不到。

有半个例外的情况是,如果你是在一些很高调,会使黑客们兴奋的地方,也许值得这样去做。在这种情况下,如果你有时间压力,也很有礼貌地提到这点,人们也许会有兴趣回答快一点。

当然,这风险很大,因为黑客们兴奋的点多半与你的不同。譬如从 NASA 国际空间站(International Space Station)发这样的标题没有问题,但用自我感觉良好的慈善行为或政治原因发肯定不行。事实上,张贴诸如紧急:帮我救救这个毛绒绒的小海豹!肯定让你被黑客忽略或惹恼他们,即使他们认为毛绒绒的小海豹很重要。

如果你觉得这点很不可思议,最好再把这份指南剩下的内容多读几遍,直到你弄懂了再发文。

礼多人不怪,而且有时还很有帮助

彬彬有礼,多用请和谢谢您的关注,或谢谢你的关照。让大家都知道你对他们花时间免费提供帮助心存感激。

坦白说,这一点并没有比清晰、正确、精准并合法语法和避免使用专用格式重要(也不能取而代之)。黑客们一般宁可读有点唐突但技术上鲜明的Bug报告,而不是那种有礼但含糊的报告。(如果这点让你不解,记住我们是按问题能教我们什么来评价问题的价值的)

然而,如果你有一串的问题待解决,客气一点肯定会增加你得到有用回应的机会。

(我们注意到,自从本指南发布后,从资深黑客那里得到的唯一严重缺陷反馈,就是对预先道谢这一条。一些黑客觉得先谢了意味着事后就不用再感谢任何人的暗示。我们的建议是要么先说先谢了,**然后**事后再对回复者表示感谢,或者换种方式表达感激,譬如用谢谢你的关注或谢谢你的关照。)

问题解决后,加个简短的补充说明

问题解决后,向所有帮助过你的人发个说明,让他们知道问题是怎样解决的,并再一次向他们表示感谢。如果问题在新闻组或者邮件列表中引起了广泛关注,应该在那里贴一个说明比较恰当。

最理想的方式是向最初提问的话题回复此消息,并在标题中包含已修正,已解决或其它同等含义的明显标记。在人来人往的邮件列表里,一个看见讨论串问题 X和问题的X – 已解决的潜在回复者就明白不用再浪费时间了(除非他个人觉得问题 X的有趣),因此可以利用此时间去解决其它问题。

补充说明不必很长或是很深入;简单的一句你好,原来是网线出了问题!谢谢大家 – Bill比什么也不说要来的好。事实上,除非结论真的很有技术含量,否则简短可爱的小结比长篇大论更好。说明问题是怎样解决的,但大可不必将解决问题的过程复述一遍。

对于有深度的问题,张贴调试记录的摘要是有帮助的。描述问题的最终状态,说明是什么解决了问题,在此**之后**才指明可以避免的盲点。避免盲点的部分应放在正确的解决方案和其它总结材料之后,而不要将此信息搞成侦探推理小说。列出那些帮助过你的名字,会让你交到更多朋友。

除了有礼貌和有内涵以外,这种类型的补充也有助于他人在邮件列表/新闻群组/论坛中搜索到真正解决你问题的方案,让他们也从中受益。

至少,这种补充有助于让每位参与协助的人因问题的解决而从中得到满足感。如果你自己不是技术专家或者黑客,那就相信我们,这种感觉对于那些你向他们求助的大师或者专家而言,是非常重要的。问题悬而未决会让人灰心;黑客们渴望看到问题被解决。好人有好报,满足他们的渴望,你会在下次提问时尝到甜头。

思考一下怎样才能避免他人将来也遇到类似的问题,自问写一份文件或加个常见问题(FAQ)会不会有帮助。如果是的话就将它们发给维护者。

在黑客中,这种良好的后继行动实际上比传统的礼节更为重要,也是你如何透过善待他人而赢得声誉的方式,这是非常有价值的资产。

如何解读答案

RTFM和STFW:如何知道你已完全搞砸了

有一个古老而神圣的传统:如果你收到RTFM (Read The Fucking Manual)的回应,回答者认为你应该去读他妈的手册。当然,基本上他是对的,你应该去读一读。

RTFM 有一个年轻的亲戚。如果你收到STFW(Search The Fucking Web)的回应,回答者认为你应该到他妈的网上搜索过了。那人多半也是对的,去搜索一下吧。(更温和一点的说法是 Google是你的朋友!)

在论坛,你也可能被要求去爬爬论坛的旧文。事实上,有人甚至可能热心地为你提供以前解决此问题的讨论串。但不要依赖这种关照,提问前应该先搜索一下旧文。

通常,用这两句之一回答你的人会给你一份包含你需要内容的手册或者一个网址,而且他们打这些字的时候也正在读着。这些答复意味着回答者认为
• 你需要的信息非常容易获得;
• 你自己去搜索这些信息比灌给你能让你学到更多。

你不应该因此不爽;依照黑客的标准,他已经表示了对你一定程度的关注,而没有对你的要求视而不见。你应该对他祖母般的慈祥表示感谢。

如果还是搞不懂

如果你看不懂回应,别立刻要求对方解释。像你以前试着自己解决问题时那样(利用手册,FAQ,网络,身边的高手),先试着去搞懂他的回应。如果你真的需要对方解释,记得表现出你已经从中学到了点什么。

比方说,如果我回答你:看来似乎是 zentry 卡住了;你应该先清除它。,然后,这是一个**很糟的**后续问题回应:zentry是什么? **好**的问法应该是这样:哦~~~我看过说明了但是只有 -z 和 -p 两个参数中提到了 zentries,而且还都没有清楚的解释如何清除它。你是指这两个中的哪一个吗?还是我看漏了什么?

处理无礼的回应

很多黑客圈子中看似无礼的行为并不是存心冒犯。相反,它是直接了当,一针见血式的交流风格,这种风格更注重解决问题,而不是使人感觉舒服而却模模糊糊。

如果你觉得被冒犯了,试着平静地反应。如果有人真的做了出格的事,邮件列表、新闻群组或论坛中的前辈多半会招呼他。如果这**没有发生而你却发火了,那么你发火对象的言语可能在黑客社区中看起来是正常的,而你**将被视为有错的一方,这将伤害到你获取信息或帮助的机会。

另一方面,你偶而真的会碰到无礼和无聊的言行。与上述相反,对真正的冒犯者狠狠地打击,用犀利的语言将其驳得体无完肤都是可以接受的。然而,在行事之前一定要非常非常的有根据。纠正无礼的言论与开始一场毫无意义的口水战仅一线之隔,黑客们自己莽撞地越线的情况并不鲜见。如果你是新手或外人,避开这种莽撞的机会并不高。如果你想得到的是信息而不是消磨时光,这时最好不要把手放在键盘上以免冒险。

(有些人断言很多黑客都有轻度的自闭症或亚斯伯格综合症,缺少用于润滑人类社会正常交往所需的神经。这既可能是真也可能是假的。如果你自己不是黑客,兴许你认为我们脑袋有问题还能帮助你应付我们的古怪行为。只管这么干好了,我们不在乎。我们**喜欢**我们现在这个样子,并且通常对病患标记都有站得住脚的怀疑。)

在下一节,我们会谈到另一个问题,当**你**行为不当时所会受到的冒犯。

如何避免扮演失败者

在黑客社区的论坛中有那么几次你可能会搞砸 — 以本指南所描述到的或类似的方式。而你会在公开场合中被告知你是如何搞砸的,也许攻击的言语中还会带点夹七夹八的颜色。

这种事发生以后,你能做的最糟糕的事莫过于哀嚎你的遭遇、宣称被口头攻击、要求道歉、高声尖叫、憋闷气、威胁诉诸法律、向其雇主报怨、忘了关马桶盖等等。相反地,你该这么做:

熬过去,这很正常。事实上,它是有益健康且合理的。

社区的标准不会自行维持,它们是通过参与者积极而**公开地**执行来维持的。不要哭嚎所有的批评都应该通过私下的邮件传送,它不是这样运作的。当有人评论你的一个说法有误或者提出不同看法时,坚持声称受到个人攻击也毫无益处,这些都是失败者的态度。

也有其它的黑客论坛,受过高礼节要求的误导,禁止参与者张贴任何对别人帖子挑毛病的消息,并声称如果你不想帮助用户就闭嘴。 结果造成有想法的参与者纷纷离开,这么做只会使它们沦为毫无意义的嘮叨与无用的技术论坛。

夸张的讲法是:你要的是友善(以上述方式)还是有用?两个里面挑一个。

记着:当黑客说你搞砸了,并且(无论多么刺耳)告诉你别再这样做时,他正在为关心你和他的社区而行动。对他而言,不理你并将你从他的生活中滤掉更简单。如果你无法做到感谢,至少要表现地有点尊严,别大声哀嚎,也别因为自己是个有戏剧性超级敏感的灵魂和自以为有资格的新来者,就指望别人像对待脆弱的洋娃娃那样对你。

有时候,即使你没有搞砸(或者只是在他的想像中你搞砸了),有些人也会无缘无故地攻击你本人。在这种情况下,抱怨倒是**真的**会把问题搞砸。

这些来找麻烦的人要么是毫无办法但自以为是专家的不中用家伙,要么就是测试你是否真会搞砸的心理专家。其它读者要么不理睬,要么用自己的方式对付他们。这些来找麻烦的人在给他们自己找麻烦,这点你不用操心。

也别让自己卷入口水战,最好不要理睬大多数的口水战 — 当然,是在你检验它们只是口水战,而并未指出你有搞砸的地方,且也没有巧妙地将问题真正的答案藏于其后(这也是有可能的)。

不该问的问题

以下是几个经典蠢问题,以及黑客没回答时心中所想的:
问题:我能在哪找到 X 程序或 X 资源?
问题:我怎样用 X 做 Y?
问题:如何设定我的 shell 提示?
问题:我可以用 Bass-o-matic 文件转换工具将 AcmeCorp 档案转换为 TeX 格式吗?
问题:我的程序/设定/SQL语句没有用
问题:我的 Windows 电脑有问题,你能帮我吗?
问题:我的程序不会动了,我认为系统工具 X 有问题
问题:我在安装 Linux(或者 X )时有问题,你能帮我吗?
问题:我怎么才能破解 root 帐号/窃取 OP 特权/读别人的邮件呢?
________________________________________
问题:我能在哪找到 X 程序或 X 资源?
回答:就在我找到它的地方啊,白痴 — 搜索引擎的那一头。天哪!难道还有人不会用 Google 吗?

问题:我怎样用 X 做 Y?
回答:如果你想解决的是 Y ,提问时别给出可能并不恰当的方法。这种问题说明提问者不但对 X 完全无知,也对 Y 要解决的问题糊涂,还被特定形势禁锢了思维。最好忽略这种人,等他们把问题搞清楚了再说。

问题:如何设定我的 shell 提示??
回答:如果你有足够的智慧提这个问题,你也该有足够的智慧去 RTFM,然后自己去找出来。

问题:我可以用 Bass-o-matic 文件转换工具将 AcmeCorp 档案转换为 TeX 格式吗?
回答:试试看就知道了。如果你试过,你既知道了答案,就不用浪费我的时间了。

问题:我的程序/设定/SQL语句没有用
回答:这不算是问题吧,我对要我问你二十个问题才找得出你真正问题的问题没兴趣 — 我有更有意思的事要做呢。在看到这类问题的时候,我的反应通常不外如下三种
• 你还有什么要补充的吗?
• 真糟糕,希望你能搞定。
• 这关我有什么屁事?

问题:我的 Windows 电脑有问题,你能帮我吗?
回答:能啊,扔掉萎软的垃圾,换个像 Linux 或 BSD 的开放源代码操作系统吧。
注意:如果程序有官方版 Windows 或者与 Windows 有互动(如Samba),你**可以**问与Windows相关的问题, 只是别对问题是由 Windows 操作系统而不是程序本身造成的回复感到惊讶, 因为 Windows 一般来说实在太烂,这种说法通常都是对的。

问题:我的程序不会动了,我认为系统工具 X 有问题
回答:你完全有可能是第一个注意到被成千上万用户反复使用的系统调用与函数库档案有明显缺陷的人,更有可能的是你完全没有根据。不同凡响的说法需要不同凡响的证据,当你这样声称时,你必须有清楚而详尽的缺陷说明文件作后盾。

问题:我在安装 Linux(或者 X )时有问题,你能帮我吗?
回答:不能,我只有亲自在你的电脑上动手才能找到毛病。还是去找你当地的 Linux 使用群组者寻求实际的指导吧(你能在这儿找到使用者群组的清单)。
注意:如果安装问题与某 Linux 的发行版有关,在它的邮件列表、论坛或本地使用者群组中提问也许是恰当的。此时,应描述问题的准确细节。在此之前,先用 Linux 和**所有**被怀疑的硬件作关键词仔细搜索。

问题:我怎么才能破解 root 帐号/窃取 OP 特权/读别人的邮件呢?
回答:想要这样做,说明了你是个卑鄙小人;想找个黑客帮你,说明你是个白痴!

好问题与蠢问题

最后,我将透过举一些例子,来说明怎样聪明的提问;同一个问题的两种问法被放在一起,一种是愚蠢的,另一种才是明智的。
蠢问题:
我可以在哪儿找到关于 Foonly Flurbamatic 的资料?
这种问法无非想得到 STFW 这样的回答。

聪明问题:
我用Google搜索过 “Foonly Flurbamatic 2600″,但是没找到有用的结果。谁知道上哪儿去找对这种设备编程的资料?
这个问题已经 STFW 过了,看起来他真的遇到了麻烦。

蠢问题
我从 foo 项目找来的源码没法编译。它怎么这么烂?
他觉得都是别人的错,这个傲慢自大的提问者

聪明问题
foo 项目代码在 Nulix 6.2 版下无法编译通过。我读过了 FAQ,但里面没有提到跟 Nulix 有关的问题。这是我编译过程的记录,我有什么做的不对的地方吗?
提问者已经指明了环境,也读过了FAQ,还列出了错误,并且他没有把问题的责任推到别人头上,他的问题值得被关注。

蠢问题
我的主机板有问题了,谁来帮我?
某黑客对这类问题的回答通常是:好的,还要帮你拍拍背和换尿布吗?,然后按下删除键。

聪明问题
我在 S2464 主机板上试过了 X 、 Y 和 Z ,但没什么作用,我又试了 A 、 B 和 C 。请注意当我尝试 C 时的奇怪现象。显然 florbish 正在 grommicking,但结果出人意料。通常在 Athlon MP 主机板上引起 grommicking 的原因是什么?有谁知道接下来我该做些什么测试才能找出问题?
这个家伙,从另一个角度来看,值得去回答他。他表现出了解决问题的能力,而不是坐等天上掉答案。

在最后一个问题中,注意告诉我答案和给我启示,指出我还应该做什么诊断工作之间微妙而又重要的区别。

事实上,后一个问题源自于 2001 年 8 月在 Linux 内核邮件列表(lkml)上的一个真实的提问。我(Eric)就是那个提出问题的人。我在 Tyan S2464 主板上观察到了这种无法解释的锁定现象,列表成员们提供了解决这一问题的重要信息。

通过我的提问方法,我给了别人可以咀嚼玩味的东西;我设法让人们很容易参与并且被吸引进来。我显示了自己具备和他们同等的能力,并邀请他们与我共同探讨。通过告诉他们我所走过的弯路,以避免他们再浪费时间,我也表明了对他们宝贵时间的尊重。

事后,当我向每个人表示感谢,并且讚赏这次良好的讨论经歷的时候, 一个 Linux 内核邮件列表的成员表示,他觉得我的问题得到解决并非由于我是这个列表中的**名人**,而是因为我用了正确的方式来提问。

黑客从某种角度来说是拥有丰富知识但缺乏人情味的家伙;我相信他是对的,如果我**像**个乞讨者那样提问,不论我是谁,一定会惹恼某些人或者被他们忽视。他建议我记下这件事,这直接导致了本指南的出现。

如果得不到回答

如果仍得不到回答,请不要以为我们觉得无法帮助你。有时只是看到你问题的人不知道答案罢了。没有回应不代表你被忽视,虽然不可否认这种差别很难区分。

总的来说,简单的重复张贴问题是个很糟的点子。这将被视为无意义的喧闹。有点耐心,知道你问题答案的人可能生活在不同的时区,可能正在睡觉,也有可能你的问题一开始就没有组织好。

你可以通过其他渠道获得帮助,这些渠道通常更适合初学者的需要。

有许多网上的以及本地的使用者群组,由热情的软件爱好者(即使他们可能从没亲自写过任何软件)组成。通常人们组建这样的团体来互相帮助并帮助新手。

另外,你可以向很多商业公司寻求帮助,不论公司大还是小。别为要付费才能获得帮助而感到沮丧!毕竟,假使你的汽车发动机汽缸密封圈爆掉了– 完全可能如此 –你还得把它送到修车铺,并且为维修付费。就算软件没花费你一分钱,你也不能强求技术支持总是免费的。

对像是 Linux 这种大众化的软件,每个开发者至少会对应到上万名使用者。根本不可能由一个人来处理来自上万名使用者的求助电话。要知道,即使你要为这些协助付费,和你所购买的同类软件相比,你所付出的也是微不足道的(通常封闭源代码软件的技术支持费用比开放源代码软件的要高得多,且内容也没那么丰富)。

如何更好地回答问题

态度和善一点。问题带来的压力常使人显得无礼或愚蠢,其实并不是这样。

对初犯者私下回复。对那些坦诚犯错之人没有必要当众羞辱,一个真正的新手也许连怎么搜索或在哪找常见问题都不知道。

如果你不确定,一定要说出来!一个听起来权威的错误回复比没有还要糟,别因为听起来像个专家很好玩,就给别人乱指路。要谦虚和诚实,给提问者与同行都树个好榜样。

如果帮不了忙,也别妨碍他。不要在实际步骤上开玩笑,那样也许会毁了使用者的设置 –有些可怜的呆瓜会把它当成真的指令。

试探性的反问以引出更多的细节。如果你做得好,提问者可以学到点东西 –你也可以。试试将蠢问题转变成好问题,别忘了我们都曾是新手。

尽管对那些懒虫抱怨一声 RTFM 是正当的,能指出文件的位置(即使只是建议个 Google 搜索关键词)会更好。

如果你决定回答,就请给出好的答案。当别人正在用错误的工具或方法时别建议笨拙的权宜之计(wordaround),应推荐更好的工具,重新界定问题。
正面的回答问题!如果这个提问者已经很深入的研究而且也表明已经试过 X 、 Y 、 Z 、 A 、 B 、 C 但没得到结果,回答 试试看 A 或是 B 或者 试试X 、 Y 、 Z 、 A 、 B 、 C 并附上一个链接一点用都没有。

帮助你的社区从问题中学习。当回复一个好问题时,问问自己如何修改相关文件或常见问题文件以免再次解答同样的问题?,接着再向文件维护者发一份补丁。

如果你是在研究一番后才做出的回答,展现你的技巧而不是直接端出结果。毕竟授人以鱼不如授人以渔。

相关资源

如果你需要个人电脑、Unix 系统和网络如何运作的基础知识,参阅Unix系统和网络基本原理。

当你发布软件或补丁时,试着按软件发布实践操作。

鸣谢
Evelyn Mitchel贡献了一些愚蠢问题例子并启发了编写如何更好地回答问题这一节, Mikhail Ramendik贡献了一些特别有价值的建议和改进。

How To Ask Questions The Smart Way


How To Ask Questions The Smart Way
Eric Steven Raymond;Thyrsus Enterprises;esr@thyrsus.com
Rick Moen;respond-auto@linuxmafia.com
Copyright © 2001,2006,2014 Eric S. Raymond, Rick Moen

Revision History

Revision 3.10 21 May 2014 esr New section on Stack Overflow.
Revision 3.9 23 Apr 2013 esr URL fixes.
Revision 3.8 19 Jun 2012 esr URL fix.
Revision 3.7 06 Dec 2010 esr Helpful hints for ESL speakers.
Revision 3.7 02 Nov 2010 esr Several translations have disappeared.
Revision 3.6 19 Mar 2008 esr Minor update and new links.
Revision 3.5 2 Jan 2008 esr Typo fix and some translation links.
Revision 3.4 24 Mar 2007 esr New section, “When asking about code”.
Revision 3.3 29 Sep 2006 esr Folded in a good suggestion from Kai Niggemann.
Revision 3.2 10 Jan 2006 esr Folded in edits from Rick Moen.
Revision 3.1 28 Oct 2004 esr Document ‘Google is your friend!’
Revision 3.0 2 Feb 2004 esr Major addition of stuff about proper etiquette on Web forums.

Translations
Translations: Bahasa Indonesian Belorussian Brazilo-Portuguese Chinese (Traditional) Croatian Czech Dutch Estonian French Georgian German Greek Hindi Hungarian Irish Gaelic Indonesion Japanese Lithuanian Polish Portuguese Romanian Russian Serbian Spanish Uzbek If you want to copy, mirror, translate, or excerpt this document, please see my copying policy.

Disclaimer
Many project websites link to this document in their sections on how to get help. That’s fine, it’s the use we intended — but if you are a webmaster creating such a link for your project page, please display prominently near the link notice that we are not a help desk for your project!

We have learned the hard way that without such a notice, we will repeatedly be pestered by idiots who think having published this document makes it our job to solve all the world’s technical problems.

If you’re reading this document because you need help, and you walk away with the impression you can get it directly from the authors of this document, you are one of the idiots we are talking about. Don’t ask us questions. We’ll just ignore you. We are here to show you how to get help from people who actually know about the software or hardware you’re dealing with, but 99.9% of the time that will not be us. Unless you know for certain that one of the authors is an expert on what you’re dealing with, leave us alone and everybody will be happier.

Introduction
In the world of hackers, the kind of answers you get to your technical questions depends as much on the way you ask the questions as on the difficulty of developing the answer. This guide will teach you how to ask questions in a way more likely to get you a satisfactory answer.

Now that use of open source has become widespread, you can often get as good answers from other, more experienced users as from hackers. This is a Good Thing; users tend to be just a little bit more tolerant of the kind of failures newbies often have. Still, treating experienced users like hackers in the ways we recommend here will generally be the most effective way to get useful answers out of them, too.

The first thing to understand is that hackers actually like hard problems and good, thought-provoking questions about them. If we didn’t, we wouldn’t be here. If you give us an interesting question to chew on we’ll be grateful to you; good questions are a stimulus and a gift. Good questions help us develop our understanding, and often reveal problems we might not have noticed or thought about otherwise. Among hackers, “Good question!” is a strong and sincere compliment.

Despite this, hackers have a reputation for meeting simple questions with what looks like hostility or arrogance. It sometimes looks like we’re reflexively rude to newbies and the ignorant. But this isn’t really true.

What we are, unapologetically, is hostile to people who seem to be unwilling to think or to do their own homework before asking questions. People like that are time sinks — they take without giving back, and they waste time we could have spent on another question more interesting and another person more worthy of an answer. We call people like this “losers” (and for historical reasons we sometimes spell it “lusers”).

We realize that there are many people who just want to use the software we write, and who have no interest in learning technical details. For most people, a computer is merely a tool, a means to an end; they have more important things to do and lives to live. We acknowledge that, and don’t expect everyone to take an interest in the technical matters that fascinate us. Nevertheless, our style of answering questions is tuned for people who do take such an interest and are willing to be active participants in problem-solving. That’s not going to change. Nor should it; if it did, we would become less effective at the things we do best.

We’re (largely) volunteers. We take time out of busy lives to answer questions, and at times we’re overwhelmed with them. So we filter ruthlessly. In particular, we throw away questions from people who appear to be losers in order to spend our question-answering time more efficiently, on winners.

If you find this attitude obnoxious, condescending, or arrogant, check your assumptions. We’re not asking you to genuflect to us — in fact, most of us would love nothing more than to deal with you as an equal and welcome you into our culture, if you put in the effort required to make that possible. But it’s simply not efficient for us to try to help people who are not willing to help themselves. It’s OK to be ignorant; it’s not OK to play stupid.

So, while it isn’t necessary to already be technically competent to get attention from us, it is necessary to demonstrate the kind of attitude that leads to competence — alert, thoughtful, observant, willing to be an active partner in developing a solution. If you can’t live with this sort of discrimination, we suggest you pay somebody for a commercial support contract instead of asking hackers to personally donate help to you.

If you decide to come to us for help, you don’t want to be one of the losers. You don’t want to seem like one, either. The best way to get a rapid and responsive answer is to ask it like a person with smarts, confidence, and clues who just happens to need help on one particular problem.

(Improvements to this guide are welcome. You can mail suggestions to esr@thyrsus.com or respond-auto@linuxmafia.com. Note however that this document is not intended to be a general guide to netiquette, and we will generally reject suggestions that are not specifically related to eliciting useful answers in a technical forum.)

Before You Ask
Before asking a technical question by e-mail, or in a newsgroup, or on a website chat board, do the following:
1. Try to find an answer by searching the archives of the forum or mailing list you plan to post to.
2. Try to find an answer by searching the Web.
3. Try to find an answer by reading the manual.
4. Try to find an answer by reading a FAQ.
5. Try to find an answer by inspection or experimentation.
6. Try to find an answer by asking a skilled friend.
7. If you’re a programmer, try to find an answer by reading the source code.

When you ask your question, display the fact that you have done these things first; this will help establish that you’re not being a lazy sponge and wasting people’s time. Better yet, display what you have learned from doing these things. We like answering questions for people who have demonstrated they can learn from the answers.

Use tactics like doing a Google search on the text of whatever error message you get (searching Google groups as well as Web pages). This might well take you straight to fix documentation or a mailing list thread answering your question. Even if it doesn’t, saying “I googled on the following phrase but didn’t get anything that looked promising” is a good thing to do in e-mail or news postings requesting help, if only because it records what searches won’t help. It will also help to direct other people with similar problems to your thread by linking the search terms to what will hopefully be your problem and resolution thread.

Take your time. Do not expect to be able to solve a complicated problem with a few seconds of Googling. Read and understand the FAQs, sit back, relax and give the problem some thought before approaching experts. Trust us, they will be able to tell from your questions how much reading and thinking you did, and will be more willing to help if you come prepared. Don’t instantly fire your whole arsenal of questions just because your first search turned up no answers (or too many).

Prepare your question. Think it through. Hasty-sounding questions get hasty answers, or none at all. The more you do to demonstrate that having put thought and effort into solving your problem before seeking help, the more likely you are to actually get help.

Beware of asking the wrong question. If you ask one that is based on faulty assumptions, J. Random Hacker is quite likely to reply with a uselessly literal answer while thinking “Stupid question…”, and hoping the experience of getting what you asked for rather than what you needed will teach you a lesson.

Never assume you are entitled to an answer. You are not; you aren’t, after all, paying for the service. You will earn an answer, if you earn it, by asking a substantial, interesting, and thought-provoking question — one that implicitly contributes to the experience of the community rather than merely passively demanding knowledge from others.

On the other hand, making it clear that you are able and willing to help in the process of developing the solution is a very good start. “Would someone provide a pointer?”, “What is my example missing?”, and “What site should I have checked?” are more likely to get answered than “Please post the exact procedure I should use.” because you’re making it clear that you’re truly willing to complete the process if someone can just point you in the right direction.

When You Ask
Choose your forum carefully

Be sensitive in choosing where you ask your question. You are likely to be ignored, or written off as a loser, if you:
• post your question to a forum where it’s off topic
• post a very elementary question to a forum where advanced technical questions are expected, or vice-versa
• cross-post to too many different newsgroups
• post a personal e-mail to somebody who is neither an acquaintance of yours nor personally responsible for solving your problem

Hackers blow off questions that are inappropriately targeted in order to try to protect their communications channels from being drowned in irrelevance. You don’t want this to happen to you.

The first step, therefore, is to find the right forum. Again, Google and other Web-searching methods are your friend. Use them to find the project webpage most closely associated with the hardware or software giving you difficulties. Usually it will have links to a FAQ (Frequently Asked Questions) list, and to project mailing lists and their archives. These mailing lists are the final places to go for help, if your own efforts (including reading those FAQs you found) do not find you a solution. The project page may also describe a bug-reporting procedure, or have a link to one; if so, follow it.

Shooting off an e-mail to a person or forum which you are not familiar with is risky at best. For example, do not assume that the author of an informative webpage wants to be your free consultant. Do not make optimistic guesses about whether your question will be welcome — if you’re unsure, send it elsewhere, or refrain from sending it at all.

When selecting a Web forum, newsgroup or mailing list, don’t trust the name by itself too far; look for a FAQ or charter to verify your question is on-topic. Read some of the back traffic before posting so you’ll get a feel for how things are done there. In fact, it’s a very good idea to do a keyword search for words relating to your problem on the newsgroup or mailing list archives before you post. It may find you an answer, and if not it will help you formulate a better question.

Don’t shotgun-blast all the available help channels at once, that’s like yelling and irritates people. Step through them softly.

Know what your topic is! One of the classic mistakes is asking questions about the Unix or Windows programming interface in a forum devoted to a language or library or tool portable across both. If you don’t understand why this is a blunder, you’d be best off not asking any questions at all until you get it.

In general, questions to a well-selected public forum are more likely to get useful answers than equivalent questions to a private one. There are multiple reasons for this. One is simply the size of the pool of potential respondents. Another is the size of the audience; hackers would rather answer questions that educate many people than questions serving only a few.

Understandably, skilled hackers and authors of popular software are already receiving more than their fair share of mis-targeted messages. By adding to the flood, you could in extreme cases even be the straw that breaks the camel’s back — quite a few times, contributors to popular projects have withdrawn their support because collateral damage in the form of useless e-mail traffic to their personal accounts became unbearable.

Stack Overflow

Search, then ask on Stack Exchange
In recent years, the Stack Exchange community of sites has emerged as a major resource for answering technical and other questions and is even the preferred forum for many open-source projects.

Start with a Google search before looking at Stack Exchange; Google indexes it in real time. There’s a very good chance someone has already asked a similar question, and the Stack Exchange sites are often near the top of the search results. If you didn’t find anything through Google, search again on the specific site most relevant to your question (see below). Searching with tags can help narrow down the results.

If you still didn’t find anything, post your question on the one site where it’s most on-topic. Use the formatting tools, especially for code, and add tags that are related to the substance of your question (particularly the name of the programming language, operating system, or library you’re having trouble with). If a commenter asks you for more information, edit your main post to include it. If any answer is helpful, click the up arrow to upvote it; if an answer gives a solution to your problem, click the check under the voting arrows to accept it as correct.

Stack Exchange has grown to over 100 sites, but here are the most likely candidates:
• Super User is for questions about general-purpose computing. If your question isn’t about code or programs that you talk to only over a network connection, it probably goes here.
• Stack Overflow is for questions about programming.
• Server Fault is for questions about server and network administration.

Several projects have their own specific sites, including Android, Ubuntu, TeX/LaTeX, and SharePoint. Check the Stack Exchange site for an up-to-date list.

Web and IRC forums

Your local user group, or your Linux distribution, may advertise a Web forum or IRC channel where newbies can get help. (In non-English-speaking countries newbie forums are still more likely to be mailing lists.) These are good first places to ask, especially if you think you may have tripped over a relatively simple or common problem. An advertised IRC channel is an open invitation to ask questions there and often get answers in real time.

In fact, if you got the program that is giving you problems from a Linux distribution (as is common today), it may be better to ask in the distro’s forum/list before trying the program’s project forum/list. The project’s hackers may just say, “use our build”.

Before posting to any Web forum, check if it has a Search feature. If it does, try a couple of keyword searches for something like your problem; it just might help. If you did a general Web search before (as you should have), search the forum anyway; your Web-wide search engine might not have all of this forum indexed recently.

There is an increasing tendency for projects to do user support over a Web forum or IRC channel, with e-mail reserved more for development traffic. So look for those channels first when seeking project-specific help.

In IRC, it’s probably best not to dump a long problem description on the channel first thing; some people interpret this as channel-flooding. Best to utter a one-line problem description in a way pitched to start a conversation on the channel.

As a second step, use project mailing lists

When a project has a development mailing list, write to the mailing list, not to individual developers, even if you believe you know who can best answer your question. Check the documentation of the project and its homepage for the address of a project mailing list, and use it. There are several good reasons for this policy:
• Any question good enough to be asked of one developer will also be of value to the whole group. Contrariwise, if you suspect your question is too dumb for a mailing list, it’s not an excuse to harass individual developers.
• Asking questions on the list distributes load among developers. The individual developer (especially if he’s the project leader) may be too busy to answer your questions.
• Most mailing lists are archived and the archives are indexed by search engines. If you ask your question on-list and it is answered, a future querent could find your question and the answer on the Web instead of asking it again.
• If certain questions are seen to be asked often, developers can use that information to improve the documentation or the software itself to be less confusing. But if those questions are asked in private, nobody has the complete picture of what questions are asked most often.

If a project has both a “user” and a “developer” (or “hacker”) mailing list or Web forum, and you are not hacking on the code, ask in the “user” list/forum. Do not assume that you will be welcome on the developer list, where they’re likely to experience your question as noise disrupting their developer traffic.

However, if you are sure your question is non-trivial, and you get no answer in the “user” list/forum for several days, try the “developer” one. You would be well advised to lurk there for a few daysor at least review the last few days of archived messages, to learn the local folkways before posting (actually this is good advice on any private or semi-private list).

If you cannot find a project’s mailing list address, but only see the address of the maintainer of the project, go ahead and write to the maintainer. But even in that case, don’t assume that the mailing list doesn’t exist. Mention in your e-mail that you tried and could not find the appropriate mailing list. Also mention that you don’t object to having your message forwarded to other people. (Many people believe that private e-mail should remain private, even if there is nothing secret in it. By allowing your message to be forwarded you give your correspondent a choice about how to handle your e-mail.)

Use meaningful, specific subject headers

On mailing lists, newsgroups or Web forums, the subject header is your golden opportunity to attract qualified experts’ attention in around 50 characters or fewer. Don’t waste it on babble like “Please help me” (let alone “PLEASE HELP ME!!!!”; messages with subjects like that get discarded by reflex). Don’t try to impress us with the depth of your anguish; use the space for a super-concise problem description instead.

One good convention for subject headers, used by many tech support organizations, is “object – deviation”. The “object” part specifies what thing or group of things is having a problem, and the “deviation” part describes the deviation from expected behavior.

Stupid:
HELP! Video doesn’t work properly on my laptop!

Smart:
X.org 6.8.1 misshapen mouse cursor, Fooware MV1005 vid. chipset

Smarter:
X.org 6.8.1 mouse cursor on Fooware MV1005 vid. chipset – is misshapen

The process of writing an “object-deviation” description will help you organize your thinking about the problem in more detail. What is affected? Just the mouse cursor or other graphics too? Is this specific to the X.org version of X? To version 6.8.1? Is this specific to Fooware video chipsets? To model MV1005? A hacker who sees the result can immediately understand what it is that you are having a problem with and the problem you are having, at a glance.

More generally, imagine looking at the index of an archive of questions, with just the subject lines showing. Make your subject line reflect your question well enough that the next person searching the archive with a question similar to yours will be able to follow the thread to an answer rather than posting the question again.
If you ask a question in a reply, be sure to change the subject line to indicate that you’re asking a question. A Subject line that looks like “Re: test” or “Re: new bug” is less likely to attract useful amounts of attention. Also, pare quotation of previous messages to the minimum consistent with cluing in new readers.

Do not simply hit reply to a list message in order to start an entirely new thread. This will limit your audience. Some mail readers, like mutt, allow the user to sort by thread and then hide messages in a thread by folding the thread. Folks who do that will never see your message.

Changing the subject is not sufficient. Mutt, and probably other mail readers, looks at other information in the e-mail’s headers to assign it to a thread, not the subject line. Instead start an entirely new e-mail.

On Web forums the rules of good practice are slightly different, because messages are usually much more tightly bound to specific discussion threads and often invisible outside those threads. Changing the subject when asking a question in reply is not essential. Not all forums even allow separate subject lines on replies, and nearly nobody reads them when they do. However, asking a question in a reply is a dubious practice in itself, because it will only be seen by those who are watching this thread. So, unless you are sure you want to ask only the people currently active in the thread, start a new one.

Make it easy to reply

Finishing your query with “Please send your reply to… ” makes it quite unlikely you will get an answer. If you can’t be bothered to take even the few seconds required to set up a correct Reply-To header in your mail agent, we can’t be bothered to take even a few seconds to think about your problem. If your mail program doesn’t permit this, get a better mail program. If your operating system doesn’t support any e-mail programs that permit this, get a better operating system.

In Web forums, asking for a reply by e-mail is outright rude, unless you believe the information may be sensitive (and somebody will, for some unknown reason, let you but not the whole forum know it). If you want an e-mail copy when somebody replies in the thread, request that the Web forum send it; this feature is supported almost everywhere under options like “watch this thread”, “send e-mail on answers”, etc.

Write in clear, grammatical, correctly-spelled language

We’ve found by experience that people who are careless and sloppy writers are usually also careless and sloppy at thinking and coding (often enough to bet on, anyway). Answering questions for careless and sloppy thinkers is not rewarding; we’d rather spend our time elsewhere.

So expressing your question clearly and well is important. If you can’t be bothered to do that, we can’t be bothered to pay attention. Spend the extra effort to polish your language. It doesn’t have to be stiff or formal — in fact, hacker culture values informal, slangy and humorous language used with precision. But it has to be precise; there has to be some indication that you’re thinking and paying attention.

Spell, punctuate, and capitalize correctly. Don’t confuse “its” with “it’s”, “loose” with “lose”, or “discrete” with “discreet”. Don’t TYPE IN ALL CAPS; this is read as shouting and considered rude. (All-smalls is only slightly less annoying, as it’s difficult to read. Alan Cox can get away with it, but you can’t.)

More generally, if you write like a semi-literate boob you will very likely be ignored. So don’t use instant-messaging shortcuts. Spelling “you” as “u” makes you look like a semi-literate boob to save two entire keystrokes. Worse: writing like a l33t script kiddie hax0r is the absolute kiss of death and guarantees you will receive nothing but stony silence (or, at best, a heaping helping of scorn and sarcasm) in return.

If you are asking questions in a forum that does not use your native language, you will get a limited amount of slack for spelling and grammar errors — but no extra slack at all for laziness (and yes, we can usually spot that difference). Also, unless you know what your respondent’s languages are, write in English. Busy hackers tend to simply flush questions in languages they don’t understand, and English is the working language of the Internet. By writing in English you minimize your chances that your question will be discarded unread.

If you are writing in English but it is a second language for you, it is good form to alert potential respondents to potential language difficulties and options for getting around them. Examples:
• English is not my native language; please excuse typing errors.
• If you speak $LANGUAGE, please email/PM me; I may need assistance translating my question.
• I am familiar with the technical terms, but some slang expressions and idioms are difficult for me.
• I’ve posted my question in $LANGUAGE and English. I’ll be glad to translate responses, if you only use one or the other.

Send questions in accessible, standard formats

If you make your question artificially hard to read, it is more likely to be passed over in favor of one that isn’t. So:
• Send plain text mail, not HTML. (It’s not hard to turn off HTML.)
• MIME attachments are usually OK, but only if they are real content (such as an attached source file or patch), and not merely boilerplate generated by your mail client (such as another copy of your message).
• Don’t send e-mail in which entire paragraphs are single multiply-wrapped lines. (This makes it too difficult to reply to just part of the message.) Assume that your respondents will be reading mail on 80-character-wide text displays and set your line wrap accordingly, to something less than 80.
• However, do not wrap data (such as log file dumps or session transcripts) at any fixed column width. Data should be included as-is, so respondents can have confidence that they are seeing what you saw.
• Don’t send MIME Quoted-Printable encoding to an English-language forum. This encoding can be necessary when you’re posting in a language ASCII doesn’t cover, but many e-mail agents don’t support it. When they break, all those =20 glyphs scattered through the text are ugly and distracting — or may actively sabotage the semantics of your text.
• Never, ever expect hackers to be able to read closed proprietary document formats like Microsoft Word or Excel. Most hackers react to these about as well as you would to having a pile of steaming pig manure dumped on your doorstep. Even when they can cope, they resent having to do so.
• If you’re sending e-mail from a Windows machine, turn off Microsoft’s problematic “Smart Quotes” feature (From Tools > AutoCorrect Options, clear the smart quotes checkbox under AutoFormat As You Type.). This is so you’ll avoid sprinkling garbage characters through your mail.
• In Web forums, do not abuse “smiley” and “HTML” features (when they are present). A smiley or two is usually OK, but colored fancy text tends to make people think you are lame. Seriously overusing smileys and color and fonts will make you come off like a giggly teenage girl, which is not generally a good idea unless you are more interested in sex than answers.

If you’re using a graphical-user-interface mail client such as Netscape Messenger, MS Outlook, or their ilk, beware that it may violate these rules when used with its default settings. Most such clients have a menu-based “View Source” command. Use this on something in your sent-mail folder, verifying sending of plain text without unnecessary attached crud.

Be precise and informative about your problem

• Describe the symptoms of your problem or bug carefully and clearly.
• Describe the environment in which it occurs (machine, OS, application, whatever). Provide your vendor’s distribution and release level (e.g.: “Fedora Core 7”, “Slackware 9.1”, etc.).
• Describe the research you did to try and understand the problem before you asked the question.
• Describe the diagnostic steps you took to try and pin down the problem yourself before you asked the question.
• Describe any possibly relevant recent changes in your computer or software configuration.
• If at all possible, provide a way to reproduce the problem in a controlled environment.

Do the best you can to anticipate the questions a hacker will ask, and answer them in advance in your request for help.

Giving hackers the ability to reproduce the problem in a controlled environment is especially important if you are reporting something you think is a bug in code. When you do this, your odds of getting a useful answer and the speed with which you are likely to get that answer both improve tremendously.

Simon Tatham has written an excellent essay entitled How to Report Bugs Effectively. I strongly recommend that you read it.

Volume is not precision

You need to be precise and informative. This end is not served by simply dumping huge volumes of code or data into a help request. If you have a large, complicated test case that is breaking a program, try to trim it and make it as small as possible.

This is useful for at least three reasons. One: being seen to invest effort in simplifying the question makes it more likely you’ll get an answer, Two: simplifying the question makes it more likely you’ll get a useful answer. Three: In the process of refining your bug report, you may develop a fix or workaround yourself.

Don’t rush to claim that you have found a bug

When you are having problems with a piece of software, don’t claim you have found a bug unless you are very, very sure of your ground. Hint: unless you can provide a source-code patch that fixes the problem, or a regression test against a previous version that demonstrates incorrect behavior, you are probably not sure enough. This applies to webpages and documentation, too; if you have found a documentation “bug”, you should supply replacement text and which pages it should go on.

Remember, there are many other users that are not experiencing your problem. Otherwise you would have learned about it while reading the documentation and searching the Web (you did do that before complaining, didn’t you?). This means that very probably it is you who are doing something wrong, not the software.

The people who wrote the software work very hard to make it work as well as possible. If you claim you have found a bug, you’ll be impugning their competence, which may offend some of them even if you are correct. It’s especially undiplomatic to yell “bug” in the Subject line.

When asking your question, it is best to write as though you assume you are doing something wrong, even if you are privately pretty sure you have found an actual bug. If there really is a bug, you will hear about it in the answer. Play it so the maintainers will want to apologize to you if the bug is real, rather than so that you will owe them an apology if you have messed up.

Grovelling is not a substitute for doing your homework

Some people who get that they shouldn’t behave rudely or arrogantly, demanding an answer, retreat to the opposite extreme of grovelling. “I know I’m just a pathetic newbie loser, but…”. This is distracting and unhelpful. It’s especially annoying when it’s coupled with vagueness about the actual problem.

Don’t waste your time, or ours, on crude primate politics. Instead, present the background facts and your question as clearly as you can. That is a better way to position yourself than by grovelling.

Sometimes Web forums have separate places for newbie questions. If you feel you do have a newbie question, just go there. But don’t grovel there either.

Describe the problem’s symptoms, not your guesses

It’s not useful to tell hackers what you think is causing your problem. (If your diagnostic theories were such hot stuff, would you be consulting others for help?) So, make sure you’re telling them the raw symptoms of what goes wrong, rather than your interpretations and theories. Let them do the interpretation and diagnosis. If you feel it’s important to state your guess, clearly label it as such and describe why that answer isn’t working for you.

Stupid:
I’m getting back-to-back SIG11 errors on kernel compiles, and suspect a hairline crack on one of the motherboard traces. What’s the best way to check for those?

Smart:
My home-built K6/233 on an FIC-PA2007 motherboard (VIA Apollo VP2 chipset) with 256MB Corsair PC133 SDRAM starts getting frequent SIG11 errors about 20 minutes after power-on during the course of kernel compiles, but never in the first 20 minutes. Rebooting doesn’t restart the clock, but powering down overnight does. Swapping out all RAM didn’t help. The relevant part of a typical compile session log follows.

Since the preceding point seems to be a tough one for many people to grasp, here’s a phrase to remind you: “All diagnosticians are from Missouri.” That US state’s official motto is “Show me” (earned in 1899, when Congressman Willard D. Vandiver said “I come from a country that raises corn and cotton and cockleburs and Democrats, and frothy eloquence neither convinces nor satisfies me. I’m from Missouri. You’ve got to show me.”) In diagnosticians’ case, it’s not a matter of skepticism, but rather a literal, functional need to see whatever is as close as possible to the same raw evidence that you see, rather than your surmises and summaries. Show us.

Describe your problem’s symptoms in chronological order

The clues most useful in figuring out something that went wrong often lie in the events immediately prior. So, your account should describe precisely what you did, and what the machine and software did, leading up to the blowup. In the case of command-line processes, having a session log (e.g., using the script utility) and quoting the relevant twenty or so lines is very useful.

If the program that blew up on you has diagnostic options (such as -v for verbose), try to select options that will add useful debugging information to the transcript. Remember that more is not necessarily better; try to choose a debug level that will inform rather than drowning the reader in junk.

If your account ends up being long (more than about four paragraphs), it might be useful to succinctly state the problem up top, then follow with the chronological tale. That way, hackers will know what to watch for in reading your account.

Describe the goal, not the step

If you are trying to find out how to do something (as opposed to reporting a bug), begin by describing the goal. Only then describe the particular step towards it that you are blocked on.
Often, people who need technical help have a high-level goal in mind and get stuck on what they think is one particular path towards the goal. They come for help with the step, but don’t realize that the path is wrong. It can take substantial effort to get past this.

Stupid:
How do I get the color-picker on the FooDraw program to take a hexadecimal RGB value?

Smart:
I’m trying to replace the color table on an image with values of my choosing. Right now the only way I can see to do this is by editing each table slot, but I can’t get FooDraw’s color picker to take a hexadecimal RGB value.

The second version of the question is smart. It allows an answer that suggests a tool better suited to the task.

Don’t ask people to reply by private e-mail

Hackers believe solving problems should be a public, transparent process during which a first try at an answer can and should be corrected if someone more knowledgeable notices that it is incomplete or incorrect. Also, helpers get some of their reward for being respondents from being seen to be competent and knowledgeable by their peers.

When you ask for a private reply, you are disrupting both the process and the reward. Don’t do this. It’s the respondent’s choice whether to reply privately — and if he or she does, it’s usually because he or she thinks the question is too ill-formed or obvious to be interesting to others.

There is one limited exception to this rule. If you think the question is such that you are likely to get many answers that are all closely similar, then the magic words are “e-mail me and I’ll summarize the answers for the group”. It is courteous to try and save the mailing list or newsgroup a flood of substantially identical postings — but you have to keep the promise to summarize.

Be explicit about your question

Open-ended questions tend to be perceived as open-ended time sinks. Those people most likely to be able to give you a useful answer are also the busiest people (if only because they take on the most work themselves). People like that are allergic to open-ended time sinks, thus they tend to be allergic to open-ended questions.

You are more likely to get a useful response if you are explicit about what you want respondents to do (provide pointers, send code, check your patch, whatever). This will focus their effort and implicitly put an upper bound on the time and energy a respondent must allocate to helping you. This is good.

To understand the world the experts live in, think of expertise as an abundant resource and time to respond as a scarce one. The less of a time commitment you implicitly ask for, the more likely you are to get an answer from someone really good and really busy.

So it is useful to frame your question to minimize the time commitment required for an expert to field it — but this is often not the same thing as simplifying the question. Thus, for example, “Would you give me a pointer to a good explanation of X?” is usually a smarter question than “Would you explain X, please?”. If you have some malfunctioning code, it is usually smarter to ask for someone to explain what’s wrong with it than it is to ask someone to fix it.

When asking about code

Don’t ask others to debug your broken code without giving a hint what sort of problem they should be searching for. Posting a few hundred lines of code, saying “it doesn’t work”, will get you ignored. Posting a dozen lines of code, saying “after line 7 I was expecting to see , but occurred instead” is much more likely to get you a response.

The most effective way to be precise about a code problem is to provide a minimal bug-demonstrating test case. What’s a minimal test case? It’s an illustration of the problem; just enough code to exhibit the undesirable behavior and no more. How do you make a minimal test case? If you know what line or section of code is producing the problematic behavior, make a copy of it and add just enough supporting code to produce a complete example (i.e. enough that the source is acceptable to the compiler/interpreter/whatever application processes it). If you can’t narrow it down to a particular section, make a copy of the source and start removing chunks that don’t affect the problematic behavior. The smaller your minimal test case is, the better (see the section called “Volume is not precision”).

Generating a really small minimal test case will not always be possible, but trying to is good discipline. It may help you learn what you need to solve the problem on your own — and even when it doesn’t, hackers like to see that you have tried. It will make them more cooperative.

If you simply want a code review, say as much up front, and be sure to mention what areas you think might particularly need review and why.

Don’t post homework questions

Hackers are good at spotting homework questions; most of us have done them ourselves. Those questions are for you to work out, so that you will learn from the experience. It is OK to ask for hints, but not for entire solutions.

If you suspect you have been passed a homework question, but can’t solve it anyway, try asking in a user group forum or (as a last resort) in a “user” list/forum of a project. While the hackers will spot it, some of the advanced users may at least give you a hint.

Prune pointless queries

Resist the temptation to close your request for help with semantically-null questions like “Can anyone help me?” or “Is there an answer?” First: if you’ve written your problem description halfway competently, such tacked-on questions are at best superfluous. Second: because they are superfluous, hackers find them annoying — and are likely to return logically impeccable but dismissive answers like “Yes, you can be helped” and “No, there is no help for you.”

In general, asking yes-or-no questions is a good thing to avoid unless you want a yes-or-no answer.

Don’t flag your question as “Urgent”, even if it is for you

That’s your problem, not ours. Claiming urgency is very likely to be counter-productive: most hackers will simply delete such messages as rude and selfish attempts to elicit immediate and special attention. Furthermore, the word ‘Urgent’ (and other similar attempts to grab attention in the subject line) often triggers spam filters – your intended recipients might never see it at all!

There is one semi-exception. It can be worth mentioning if you’re using the program in some high-profile place, one that the hackers will get excited about; in such a case, if you’re under time pressure, and you say so politely, people may get interested enough to answer faster.

This is a very risky thing to do, however, because the hackers’ metric for what is exciting probably differs from yours. Posting from the International Space Station would qualify, for example, but posting on behalf of a feel-good charitable or political cause would almost certainly not. In fact, posting “Urgent: Help me save the fuzzy baby seals!” will reliably get you shunned or flamed even by hackers who think fuzzy baby seals are important.
If you find this mysterious, re-read the rest of this how-to repeatedly until you understand it before posting anything at all.

Courtesy never hurts, and sometimes helps

Be courteous. Use “Please” and “Thanks for your attention” or “Thanks for your consideration”. Make it clear you appreciate the time people spend helping you for free.

To be honest, this isn’t as important as (and cannot substitute for) being grammatical, clear, precise and descriptive, avoiding proprietary formats etc.; hackers in general would rather get somewhat brusque but technically sharp bug reports than polite vagueness. (If this puzzles you, remember that we value a question by what it teaches us.)

However, if you’ve got your technical ducks in a row, politeness does increase your chances of getting a useful answer.

(We must note that the only serious objection we’ve received from veteran hackers to this HOWTO is with respect to our previous recommendation to use “Thanks in advance”. Some hackers feel this connotes an intention not to thank anybody afterwards. Our recommendation is to either say “Thanks in advance” first and thank respondents afterwards, or express courtesy in a different way, such as by saying “Thanks for your attention” or “Thanks for your consideration”.)

Follow up with a brief note on the solution

Send a note after the problem has been solved to all who helped you; let them know how it came out and thank them again for their help. If the problem attracted general interest in a mailing list or newsgroup, it’s appropriate to post the followup there.

Optimally, the reply should be to the thread started by the original question posting, and should have ‘FIXED’, ‘RESOLVED’ or an equally obvious tag in the subject line. On mailing lists with fast turnaround, a potential respondent who sees a thread about “Problem X” ending with “Problem X – FIXED” knows not to waste his/her time even reading the thread (unless (s)he personally finds Problem X interesting) and can therefore use that time solving a different problem.

Your followup doesn’t have to be long and involved; a simple “Howdy — it was a failed network cable! Thanks, everyone. – Bill” would be better than nothing. In fact, a short and sweet summary is better than a long dissertation unless the solution has real technical depth. Say what action solved the problem, but you need not replay the whole troubleshooting sequence.

For problems with some depth, it is appropriate to post a summary of the troubleshooting history. Describe your final problem statement. Describe what worked as a solution, and indicate avoidable blind alleys after that. The blind alleys should come after the correct solution and other summary material, rather than turning the follow-up into a detective story. Name the names of people who helped you; you’ll make friends that way.

Besides being courteous and informative, this sort of followup will help others searching the archive of the mailing-list/newsgroup/forum to know exactly which solution helped you and thus may also help them.

Last, and not least, this sort of followup helps everybody who assisted feel a satisfying sense of closure about the problem. If you are not a techie or hacker yourself, trust us that this feeling is very important to the gurus and experts you tapped for help. Problem narratives that trail off into unresolved nothingness are frustrating things; hackers itch to see them resolved. The goodwill that scratching that itch earns you will be very, very helpful to you next time you need to pose a question.

Consider how you might be able to prevent others from having the same problem in the future. Ask yourself if a documentation or FAQ patch would help, and if the answer is yes send that patch to the maintainer.
Among hackers, this sort of good followup behavior is actually more important than conventional politeness. It’s how you get a reputation for playing well with others, which can be a very valuable asset.

How To Interpret Answers

RTFM and STFW: How To Tell You’ve Seriously Screwed Up

There is an ancient and hallowed tradition: if you get a reply that reads “RTFM”, the person who sent it thinks you should have Read The Fucking Manual. He or she is almost certainly right. Go read it.

RTFM has a younger relative. If you get a reply that reads “STFW”, the person who sent it thinks you should have Searched The Fucking Web. He or she is almost certainly right. Go search it. (The milder version of this is when you are told “Google is your friend!”)

In Web forums, you may also be told to search the forum archives. In fact, someone may even be so kind as to provide a pointer to the previous thread where this problem was solved. But do not rely on this consideration; do your archive-searching before asking.

Often, the person telling you to do a search has the manual or the web page with the information you need open, and is looking at it as he or she types. These replies mean that the responder thinks (a) the information you need is easy to find, and (b) you will learn more if you seek out the information than if you have it spoon-fed to you.

You shouldn’t be offended by this; by hacker standards, your respondent is showing you a rough kind of respect simply by not ignoring you. You should instead be thankful for this grandmotherly kindness.

If you don’t understand…

If you don’t understand the answer, do not immediately bounce back a demand for clarification. Use the same tools that you used to try and answer your original question (manuals, FAQs, the Web, skilled friends) to understand the answer. Then, if you still need to ask for clarification, exhibit what you have learned.

For example, suppose I tell you: “It sounds like you’ve got a stuck zentry; you’ll need to clear it.” Then: here’s a bad followup question: “What’s a zentry?” Here’s a good followup question: “OK, I read the man page and zentries are only mentioned under the -z and -p switches. Neither of them says anything about clearing zentries. Is it one of these or am I missing something here?”

Dealing with rudeness

Much of what looks like rudeness in hacker circles is not intended to give offense. Rather, it’s the product of the direct, cut-through-the-bullshit communications style that is natural to people who are more concerned about solving problems than making others feel warm and fuzzy.

When you perceive rudeness, try to react calmly. If someone is really acting out, it is very likely a senior person on the list or newsgroup or forum will call him or her on it. If that doesn’t happen and you lose your temper, it is likely that the person you lose it at was behaving within the hacker community’s norms and you will be considered at fault. This will hurt your chances of getting the information or help you want.

On the other hand, you will occasionally run across rudeness and posturing that is quite gratuitous. The flip-side of the above is that it is acceptable form to slam real offenders quite hard, dissecting their misbehavior with a sharp verbal scalpel. Be very, very sure of your ground before you try this, however. The line between correcting an incivility and starting a pointless flamewar is thin enough that hackers themselves not infrequently blunder across it; if you are a newbie or an outsider, your chances of avoiding such a blunder are low. If you’re after information rather than entertainment, it’s better to keep your fingers off the keyboard than to risk this.

(Some people assert that many hackers have a mild form of autism or Asperger’s Syndrome, and are actually missing some of the brain circuitry that lubricates “normal” human social interaction. This may or may not be true. If you are not a hacker yourself, it may help you cope with our eccentricities if you think of us as being brain-damaged. Go right ahead. We won’t care; we like being whatever it is we are, and generally have a healthy skepticism about clinical labels.)

Jeff Bigler’s observations about tact filters are also relevant and worth reading.

In the next section, we’ll talk about a different issue; the kind of “rudeness” you’ll see when you misbehave.

On Not Reacting Like A Loser

Odds are you’ll screw up a few times on hacker community forums — in ways detailed in this article, or similar. And you’ll be told exactly how you screwed up, possibly with colourful asides. In public.

When this happens, the worst thing you can do is whine about the experience, claim to have been verbally assaulted, demand apologies, scream, hold your breath, threaten lawsuits, complain to people’s employers, leave the toilet seat up, etc. Instead, here’s what you do:
Get over it. It’s normal. In fact, it’s healthy and appropriate.

Community standards do not maintain themselves: They’re maintained by people actively applying them, visibly, in public. Don’t whine that all criticism should have been conveyed via private e-mail: That’s not how it works. Nor is it useful to insist you’ve been personally insulted when someone comments that one of your claims was wrong, or that his views differ. Those are loser attitudes.

There have been hacker forums where, out of some misguided sense of hyper-courtesy, participants are banned from posting any fault-finding with another’s posts, and told “Don’t say anything if you’re unwilling to help the user.” The resulting departure of clueful participants to elsewhere causes them to descend into meaningless babble and become useless as technical forums.

Exaggeratedly “friendly” (in that fashion) or useful: Pick one.

Remember: When that hacker tells you that you’ve screwed up, and (no matter how gruffly) tells you not to do it again, he’s acting out of concern for (1) you and (2) his community. It would be much easier for him to ignore you and filter you out of his life. If you can’t manage to be grateful, at least have a little dignity, don’t whine, and don’t expect to be treated like a fragile doll just because you’re a newcomer with a theatrically hypersensitive soul and delusions of entitlement.

Sometimes people will attack you personally, flame without an apparent reason, etc., even if you don’t screw up (or have only screwed up in their imagination). In this case, complaining is the way to really screw up.
These flamers are either lamers who don’t have a clue but believe themselves to be experts, or would-be psychologists testing whether you’ll screw up. The other readers either ignore them, or find ways to deal with them on their own. The flamers’ behavior creates problems for themselves, which don’t have to concern you.
Don’t let yourself be drawn into a flamewar, either. Most flames are best ignored — after you’ve checked whether they are really flames, not pointers to the ways in which you have screwed up, and not cleverly ciphered answers to your real question (this happens as well).

Questions Not To Ask
Here are some classic stupid questions, and what hackers are thinking when they don’t answer them.
Q: Where can I find program or resource X?
Q: How can I use X to do Y?
Q: How can I configure my shell prompt?
Q: Can I convert an AcmeCorp document into a TeX file using the Bass-o-matic file converter?
Q: My {program, configuration, SQL statement} doesn’t work
Q: I’m having problems with my Windows machine. Can you help?
Q: My program doesn’t work. I think system facility X is broken.
Q: I’m having problems installing Linux or X. Can you help?
Q: How can I crack root/steal channel-ops privileges/read someone’s e-mail?
Q: Where can I find program or resource X?
A: The same place I’d find it, fool — at the other end of a web search. Ghod, doesn’t everybody know how to use Google yet?

Q: How can I use X to do Y?
A: If what you want is to do Y, you should ask that question without pre-supposing the use of a method that may not be appropriate. Questions of this form often indicate a person who is not merely ignorant about X, but confused about what problem Y they are solving and too fixated on the details of their particular situation. It is generally best to ignore such people until they define their problem better.

Q: How can I configure my shell prompt?
A: If you’re smart enough to ask this question, you’re smart enough to RTFM and find out yourself.

Q: Can I convert an AcmeCorp document into a TeX file using the Bass-o-matic file converter?
A: Try it and see. If you did that, you’d (a) learn the answer, and (b) stop wasting my time.

Q: My {program, configuration, SQL statement} doesn’t work
A: This is not a question, and I’m not interested in playing Twenty Questions to pry your actual question out of you — I have better things to do. On seeing something like this, my reaction is normally of one of the following:
• do you have anything else to add to that?
• oh, that’s too bad, I hope you get it fixed.
• and this has exactly what to do with me?

Q: I’m having problems with my Windows machine. Can you help?
A: Yes. Throw out that Microsoft trash and install an open-source operating system like Linux or BSD.
Note: you can ask questions related to Windows machines if they are about a program that does have an official Windows build, or interacts with Windows machines (i.e., Samba). Just don’t be surprised by the reply that the problem is with Windows and not the program, because Windows is so broken in general that this is very often the case.

Q: My program doesn’t work. I think system facility X is broken.
A: While it is possible that you are the first person to notice an obvious deficiency in system calls and libraries heavily used by hundreds or thousands of people, it is rather more likely that you are utterly clueless. Extraordinary claims require extraordinary evidence; when you make a claim like this one, you must back it up with clear and exhaustive documentation of the failure case.

Q: I’m having problems installing Linux or X. Can you help?
A: No. I’d need hands-on access to your machine to troubleshoot this. Go ask your local Linux user group for hands-on help. (You can find a list of user groups here.)
Note: questions about installing Linux may be appropriate if you’re on a forum or mailing list about a particular distribution, and the problem is with that distro; or on local user groups forums. In this case, be sure to describe the exact details of the failure. But do careful searching first, with “linux” and all suspicious pieces of hardware.

Q: How can I crack root/steal channel-ops privileges/read someone’s e-mail?
A: You’re a lowlife for wanting to do such things and a moron for asking a hacker to help you.

Good and Bad Questions

Finally, I’m going to illustrate how to ask questions in a smart way by example; pairs of questions about the same problem, one asked in a stupid way and one in a smart way.

Stupid: Where can I find out stuff about the Foonly Flurbamatic?
This question just begs for “STFW” as a reply.
Smart: I used Google to try to find “Foonly Flurbamatic 2600” on the Web, but I got no useful hits. Can I get a pointer to programming information on this device?

This one has already STFWed, and sounds like there might be a real problem.

Stupid: I can’t get the code from project foo to compile. Why is it broken?
The querent assumes that somebody else screwed up. Arrogant git…
Smart: The code from project foo doesn’t compile under Nulix version 6.2. I’ve read the FAQ, but it doesn’t have anything in it about Nulix-related problems. Here’s a transcript of my compilation attempt; is it something I did?

The querent has specified the environment, read the FAQ, is showing the error, and is not assuming his problems are someone else’s fault. This one might be worth some attention.

Stupid: I’m having problems with my motherboard. Can anybody help?
J. Random Hacker’s response to this is likely to be “Right. Do you need burping and diapering, too?” followed by a punch of the delete key.
Smart: I tried X, Y, and Z on the S2464 motherboard. When that didn’t work, I tried A, B, and C. Note the curious symptom when I tried C. Obviously the florbish is grommicking, but the results aren’t what one might expect. What are the usual causes of grommicking on Athlon MP motherboards? Anybody got ideas for more tests I can run to pin down the problem?

This person, on the other hand, seems worthy of an answer. He/she has exhibited problem-solving intelligence rather than passively waiting for an answer to drop from on high.

In the last question, notice the subtle but important difference between demanding “Give me an answer” and “Please help me figure out what additional diagnostics I can run to achieve enlightenment.”

In fact, the form of that last question is closely based on a real incident that happened in August 2001 on the linux-kernel mailing list (lkml). I (Eric) was the one asking the question that time. I was seeing mysterious lockups on a Tyan S2462 motherboard. The list members supplied the critical information I needed to solve them.

By asking the question in the way I did, I gave people something to chew on; I made it easy and attractive for them to get involved. I demonstrated respect for my peers’ ability and invited them to consult with me as a peer. I also demonstrated respect for the value of their time by telling them the blind alleys I had already run down.
Afterwards, when I thanked everyone and remarked how well the process had worked, an lkml member observed that he thought it had worked not because I’m a “name” on that list, but because I asked the question in the proper form.
Hackers are in some ways a very ruthless meritocracy; I’m certain he was right, and that if I had behaved like a sponge I would have been flamed or ignored no matter who I was. His suggestion that I write up the whole incident as instruction to others led directly to the composition of this guide.

If You Can’t Get An Answer

If you can’t get an answer, please don’t take it personally that we don’t feel we can help you. Sometimes the members of the asked group may simply not know the answer. No response is not the same as being ignored, though admittedly it’s hard to spot the difference from outside.

In general, simply re-posting your question is a bad idea. This will be seen as pointlessly annoying. Have patience: the person with your answer may be in a different time-zone and asleep. Or it may be that your question wasn’t well-formed to begin with.

There are other sources of help you can go to, often sources better adapted to a novice’s needs.

There are many online and local user groups who are enthusiasts about the software, even though they may never have written any software themselves. These groups often form so that people can help each other and help new users.

There are also plenty of commercial companies you can contract with for help, both large and small. Don’t be dismayed at the idea of having to pay for a bit of help! After all, if your car engine blows a head gasket, chances are you would take it to a repair shop and pay to get it fixed. Even if the software didn’t cost you anything, you can’t expect that support to always come for free.

For popular software like Linux, there are at least 10,000 users per developer. It’s just not possible for one person to handle the support calls from over 10,000 users. Remember that even if you have to pay for support, you are still paying much less than if you had to buy the software as well (and support for closed-source software is usually more expensive and less competent than support for open-source software).

How To Answer Questions in a Helpful Way

Be gentle. Problem-related stress can make people seem rude or stupid even when they’re not.
Reply to a first offender off-line. There is no need of public humiliation for someone who may have made an honest mistake. A real newbie may not know how to search archives or where the FAQ is stored or posted.

If you don’t know for sure, say so! A wrong but authoritative-sounding answer is worse than none at all. Don’t point anyone down a wrong path simply because it’s fun to sound like an expert. Be humble and honest; set a good example for both the querent and your peers.

If you can’t help, don’t hinder. Don’t make jokes about procedures that could trash the user’s setup — the poor sap might interpret these as instructions.

Ask probing questions to elicit more details. If you’re good at this, the querent will learn something — and so might you. Try to turn the bad question into a good one; remember we were all newbies once.

While muttering RTFM is sometimes justified when replying to someone who is just a lazy slob, a pointer to documentation (even if it’s just a suggestion to google for a key phrase) is better.

If you’re going to answer the question at all, give good value. Don’t suggest kludgy workarounds when somebody is using the wrong tool or approach. Suggest good tools. Reframe the question.

Answer the actual question! If the querent has been so thorough as to do his or her research and has included in the query that X, Y, Z, A, B, and C have already been tried without good result, it is supremely unhelpful to respond with “Try A or B,” or with a link to something that only says, “Try X, Y, Z, A, B, or C.”.

Help your community learn from the question. When you field a good question, ask yourself “How would the relevant documentation or FAQ have to change so that nobody has to answer this again?” Then send a patch to the document maintainer.

If you did research to answer the question, demonstrate your skills rather than writing as though you pulled the answer out of your butt. Answering one good question is like feeding a hungry person one meal, but teaching them research skills by example is showing them how to grow food for a lifetime.

Related Resources
If you need instruction in the basics of how personal computers, Unix, and the Internet work, see The Unix and Internet Fundamentals HOWTO.

When you release software or write patches for software, try to follow the guidelines in the Software Release Practice HOWTO.

Acknowledgements
Evelyn Mitchell contributed some example stupid questions and inspired the “How To Give A Good Answer” section. Mikhail Ramendik contributed some particularly valuable suggestions for improvements.

Jeff Dean facts

日常:

Jeff Dean was born on December 31, 1969 at 11:48 PM. It took him twelve minutes to implement his first time counter.

Jeff Dean puts his pants on one leg at a time, but if he had more legs, you would see that his approach is O(log n).

Jeff Dean’s watch displays seconds since January 1st, 1970. He is never late.

During his own Google interview, Jeff Dean was asked the implications if P=NP were true. He said, “P = 0 or N = 1.” Then, before the interviewer had even finished laughing, Jeff examined Google’s public certificate and wrote the private key on the whiteboard.

Jeff dean doesn’t have a wikipedia page. Wikipedia has a page on Jeff Dean.

Jeff Dean has binary readability.

Jeff Dean sorts his phone contacts by their vcard’s md5 checksums.

When Jeff has trouble sleeping, he Mapreduces sheep.

When Jeff Dean listens to mp3s, he just cats them to /dev/dsp and does the decoding in his head.

One day Jeff Dean grabbed his Etch-a-Sketch instead of his laptop on his way out the door. On his way back home to get his real laptop, he programmed the Etch-a-Sketch to play Tetris.

Jeff Dean is still waiting for mathematicians to discover the joke he hid in the digits of PI.

Jeff Dean can beat you at connect four. In three moves.

When Jeff Dean goes on vacation, production services across Google mysteriously stop working within a few days. This is actually true.

Jeff Dean was sick few times… That’s how computer viruses came to existence!

Jeff Dean can determine the exact position and velocity of an electron.

Jeff Dean doesn’t kill processes, he slays them.

In one of Jeff Dean’s Notebooks for Algorithms/Theory Of Computation , written on Margin is ” I have discovered a truly marvelous proof of this, which this margin is too narrow to contain”.

Jeff Dean Map Reduces his cereal.

Jeff Dean made Google Maps using his knitting kit.

The needle in haystack found Jeff Dean.

Jeff Dean’s Dropbox quota is bigger than all of YouTube’s storage farms.

All of the Google App Engine is actually hosted from Jeff Dean’s Nexus S.

PageRank made the Dean’s list.

Jeff Dean wrote a genetic algorithm. It made awesome things amongst which are BigTable and Peter Norvig.

Recently Jeff Dean got promoted even before the performance evaluation cycle started.

They had to invent a new post (Senior Google Fellow) just to promote Jeff (and Sanjay).

其他日常:

When he heard that Jeff Dean’s autobiography would be exclusive to the platform, Richard Stallman bought a Kindle.

God created Jeff Dean. Then he programmed Chuck Norris.

When Graham Bell invented the telephone, he saw a missed call from Jeff Dean.

Why did Vint Cerf invent the Internet? Because Jeff Dean didn’t have time.

Knuth mailed a copy of TAOCP to Google. Jeff Dean autographed it and mailed it back.

Only two people know all Jeff Dean facts. Both Jeff and Chuck think sharing them all would be too much for mere mortals.

Voldemort is scared of Jeff Dean.

Thron movies are based on Jeff Dean’s life.

算法与优化:

Unsatisfied with constant time, Jeff Dean created the world’s first O(1/n) algorithm.

Jeff Dean wrote an O(n^2) algorithm once. It was for the Traveling Salesman Problem.

Jeff Dean’s Bubble Sort runs in O(1) time.

The speed of light in a vacuum used to be about 35 mph. Then Jeff Dean spent a weekend optimizing physics.

Google search went down for a few hours in 2002, and Jeff Dean started handling queries by hand. Search Quality doubled.

Once, in early 2002, when the search back-ends went down, Jeff Dean answered user queries manually for two hours. Result quality improved markedly during this time.”

编程:

Jeff Dean eschews both Emacs and VI. He types his code into zcat, because it’s faster that way.

Jeff Dean writes directly in binary. He then writes the source code as a documentation for other developers.

Jeff Dean can parse HTML with Regular Expressions

All pointers point to Jeff Dean.

You name three pointers, Einstein, Euler, and Turing, when you de-reference them, all you get is Jeff Dean.

Jeff starts his programming sessions with ‘cat > /dev/mem’.

Jeff Dean once shifted a bit so hard, it ended up on another computer.

Jeff Dean’s infinite loops run in 5 seconds.

Jeff Dean can write infinite recursion functions…and have them return.

Jeff Dean has gone to /dev/null and come back.

Jeff Dean can losslessly compress random data.

All Jeff Dean’s code is pure. For fun, he once wrote a function with a side effect, that side effect is known as Gmail.

Jeff Dean can unit test entire applications with a single assert.

When Jeff Dean fires up the profiler, loops unroll themselves in fear.

Jeff Dean once implemented a web server in a single printf() call. Other engineers added thousands of lines of explanatory comments but still don’t understand exactly how it works. Today that program is the front-end to Google Search.

Jeff Dean was forced to invent asynchronous APIs one day when he optimized a function so that it returned before it was invoked.

Jeff once simultaneously reduced all binary sizes by 3% AND raised the severity of a previously known low-priority python bug to critical-priority in a single change that contained no python code.

When your code has undefined behavior, you get a seg fault and corrupted data. When Jeff Dean’s code has undefined behavior, a unicorn rides in on a rainbow and gives everybody free ice cream.

When Jeff Dean sends an ethernet frame there are no collisions because the competing frames retreat back up into the buffer memory on their source nic.

Jeff Dean once failed a Turing test when he correctly identified the 203rd Fibonacci number in less than a second.

命令行及编译器:

Compilers don’t warn Jeff Dean. Jeff Dean warns compilers.

Jeff Dean builds his code before committing it, but only to check for compiler and linker bugs.

gcc -O4 sends your code to Jeff Dean for a complete rewrite.

The x86-64 spec includes several undocumented instructions marked ‘private use.’ They are actually for Jeff Dean’s use.

When Jeff Dean designs software, he first codes the binary and then writes the source as documentation.

mantri@mantri-laptop~$ rm -r /
rm: cannot remove root directory `/’
mantri@mantri-laptop~$ su – jeffdean -c “rm -r /”
I am extremely sorry. Removing root directory…

硬件:

The rate at which Jeff Dean produces code jumped by a factor of 40 in late 2000 when he upgraded his keyboard to USB 2.0.

When Jeff Dean has an ergonomic evaluation, it is for the protection of his keyboard.

Jeff Dean’s ISP routes all traffic through Jeff Dean’s router. It is faster that way.

Jeff Deans’s keyboard doesn’t have a Ctrl key because nothing controls Jeff Dean.

Jeff Dean’s keyboard has two keys: 1 and 0.

参考:
google+
quora

一家IT公司最重要的财产是什么?

这个问题问过一些人,也在网上找过答案,有人说IT公司最重要的财产是源码,有人说是产品,有人说是客户,也有人说是关系。
其实这些回答,都是有一定道理的。

但我今天想说的答案却是:传承。
这里的传承,不仅是源码,不仅是产品,不仅是业务知识,不仅是编程技巧,更是一种精神,一种文化,一种理念,一种信仰。传承可以将一盘散沙铸成利剑,披荆斩棘。传承可以凝聚成一股强大的力量,无往而不利。

传承,在一个公司的不同阶段,有着不同的表现和不同的作用。

在公司的创业阶段,传承是靠个人来完成的。
这个阶段,公司规模很小,人员很少,是公司对个人依赖最强的阶段,但也是转型最快的阶段。
这个阶段,个人要有很强的付出精神,加班加点甚至通宵是常有的事情。是一个很累很痛苦,但也很充实很快乐的阶段。
创业团队的个人能力及付出,很大程度上决定着公司的未来,
这个阶段,沟通不要很多成本,但每个人都要独挡一面,一个都不能少。
知识都存在人的大脑中,靠人的记忆传递下来。

在公司迅速扩张的阶段,传承是靠传帮带及梯队建设来完成的。
这个阶段,公司初具规模,是对管理层能力要求最高的阶段。
管理层不仅要懂开发,而且要懂运营管理,可以团结力量,调动大家的积极性,沟通成本急速上升。
这个阶段,是公司文化形成的时期,各个环节处理的好坏,直接决定了公司的命运。
这个阶段,知识及文化的传播,主要依赖于师徒关系,一点儿一点儿扩散开来。梯队起来了,稳定了,也就成了;梯队一直不稳定,尤其是核心团队不稳定,也就危险了。

在公司平稳发展的阶段,传承是靠制度及培训完成的。
公司发展到一定规模,个人能力对公司的改变越来越小,甚至被称为螺丝钉。
这个阶段,主要靠公司的制度来保证公司的运营。员工进入公司时,便会接收大量培训,个人按制度完成自己的职责,保障公司正常运营,从而实现公司盈利。
这个阶段,个人对公司的影像变小,很难有所改变。但灵魂人物的作用却变得强大,因为灵魂人物要团结所有人,向应该努力的方向前进。

没有传承,一家公司就谈不上发展;
没有传承,一家公司就一直在走相同的老路;
没有传承,一家公司就会逐渐消亡;

传承,随着一家公司的进步而慢慢改变;
传承,决定了一家公司的气质及未来;
传承,是一家公司最宝贵的财产。

The Humble Programmer


The Humble Programmer
by Edsger W. Dijkstra

As a result of a long sequence of coincidences I entered the programming profession officially on the first spring morning of 1952 and as far as I have been able to trace, I was the first Dutchman to do so in my country. In retrospect the most amazing thing was the slowness with which, at least in my part of the world, the programming profession emerged, a slowness which is now hard to believe. But I am grateful for two vivid recollections from that period that establish that slowness beyond any doubt.

After having programmed for some three years, I had a discussion with A. van Wijngaarden, who was then my boss at the Mathematical Centre in Amsterdam, a discussion for which I shall remain grateful to him as long as I live. The point was that I was supposed to study theoretical physics at the University of Leiden simultaneously, and as I found the two activities harder and harder to combine, I had to make up my mind, either to stop programming and become a real, respectable theoretical physicist, or to carry my study of physics to a formal completion only, with a minimum of effort, and to become….., yes what? A programmer? But was that a respectable profession? For after all, what was programming? Where was the sound body of knowledge that could support it as an intellectually respectable discipline? I remember quite vividly how I envied my hardware colleagues, who, when asked about their professional competence, could at least point out that they knew everything about vacuum tubes, amplifiers and the rest, whereas I felt that, when faced with that question, I would stand empty-handed. Full of misgivings I knocked on van Wijngaarden’s office door, asking him whether I could “speak to him for a moment”; when I left his office a number of hours later, I was another person. For after having listened to my problems patiently, he agreed that up till that moment there was not much of a programming discipline, but then he went on to explain quietly that automatic computers were here to stay, that we were just at the beginning and could not I be one of the persons called to make programming a respectable discipline in the years to come? This was a turning point in my life and I completed my study of physics formally as quickly as I could. One moral of the above story is, of course, that we must be very careful when we give advice to younger people; sometimes they follow it!

Another two years later, in 1957, I married and Dutch marriage rites require you to state your profession and I stated that I was a programmer. But the municipal authorities of the town of Amsterdam did not accept it on the grounds that there was no such profession. And, believe it or not, but under the heading “profession” my marriage act shows the ridiculous entry “theoretical physicist”!

So much for the slowness with which I saw the programming profession emerge in my own country. Since then I have seen more of the world, and it is my general impression that in other countries, apart from a possible shift of dates, the growth pattern has been very much the same.

Let me try to capture the situation in those old days in a little bit more detail, in the hope of getting a better understanding of the situation today. While we pursue our analysis, we shall see how many common misunderstandings about the true nature of the programming task can be traced back to that now distant past.

The first automatic electronic computers were all unique, single-copy machines and they were all to be found in an environment with the exciting flavour of an experimental laboratory. Once the vision of the automatic computer was there, its realisation was a tremendous challenge to the electronic technology then available, and one thing is certain: we cannot deny the courage of the groups that decided to try and build such a fantastic piece of equipment. For fantastic pieces of equipment they were: in retrospect one can only wonder that those first machines worked at all, at least sometimes. The overwhelming problem was to get and keep the machine in working order. The preoccupation with the physical aspects of automatic computing is still reflected in the names of the older scientific societies in the field, such as the Association for Computing Machinery or the British Computer Society, names in which explicit reference is made to the physical equipment.

What about the poor programmer? Well, to tell the honest truth: he was hardly noticed. For one thing, the first machines were so bulky that you could hardly move them and besides that, they required such extensive maintenance that it was quite natural that the place where people tried to use the machine was the same laboratory where the machine had been developed. Secondly, his somewhat invisible work was without any glamour: you could show the machine to visitors and that was several orders of magnitude more spectacular than some sheets of coding. But most important of all, the programmer himself had a very modest view of his own work: his work derived all its significance from the existence of that wonderful machine. Because that was a unique machine, he knew only too well that his programs had only local significance and also, because it was patently obvious that this machine would have a limited lifetime, he knew that very little of his work would have a lasting value. Finally, there is yet another circumstance that had a profound influence on the programmer’s attitude to his work: on the one hand, besides being unreliable, his machine was usually too slow and its memory was usually too small, i.e. he was faced with a pinching shoe, while on the other hand its usually somewhat queer order code would cater for the most unexpected constructions. And in those days many a clever programmer derived an immense intellectual satisfaction from the cunning tricks by means of which he contrived to squeeze the impossible into the constraints of his equipment.

Two opinions about programming date from those days. I mention them now, I shall return to them later. The one opinion was that a really competent programmer should be puzzle-minded and very fond of clever tricks; the other opinion was that programming was nothing more than optimizing the efficiency of the computational process, in one direction or the other.

The latter opinion was the result of the frequent circumstance that, indeed, the available equipment was a painfully pinching shoe, and in those days one often encountered the naive expectation that, once more powerful machines were available, programming would no longer be a problem, for then the struggle to push the machine to its limits would no longer be necessary and that was all what programming was about, wasn’t it? But in the next decades something completely different happened: more powerful machines became available, not just an order of magnitude more powerful, even several orders of magnitude more powerful. But instead of finding ourselves in the state of eternal bliss of all programming problems solved, we found ourselves up to our necks in the software crisis! How come?

There is a minor cause: in one or two respects modern machinery is basically more difficult to handle than the old machinery. Firstly, we have got the I/O interrupts, occurring at unpredictable and irreproducible moments; compared with the old sequential machine that pretended to be a fully deterministic automaton, this has been a dramatic change and many a systems programmer’s grey hair bears witness to the fact that we should not talk lightly about the logical problems created by that feature. Secondly, we have got machines equipped with multi-level stores, presenting us problems of management strategy that, in spite of the extensive literature on the subject, still remain rather elusive. So much for the added complication due to structural changes of the actual machines.

But I called this a minor cause; the major cause is… that the machines have become several orders of magnitude more powerful! To put it quite bluntly: as long as there were no machines, programming was no problem at all; when we had a few weak computers, programming became a mild problem, and now we have gigantic computers, programming had become an equally gigantic problem. In this sense the electronic industry has not solved a single problem, it has only created them, it has created the problem of using its products. To put it in another way: as the power of available machines grew by a factor of more than a thousand, society’s ambition to apply these machines grew in proportion, and it was the poor programmer who found his job in this exploded field of tension between ends and means. The increased power of the hardware, together with the perhaps even more dramatic increase in its reliability, made solutions feasible that the programmer had not dared to dream about a few years before. And now, a few years later, he had to dream about them and, even worse, he had to transform such dreams into reality! Is it a wonder that we found ourselves in a software crisis? No, certainly not, and as you may guess, it was even predicted well in advance; but the trouble with minor prophets, of course, is that it is only five years later that you really know that they had been right.

Then, in the mid-sixties, something terrible happened: the computers of the so-called third generation made their appearance. The official literature tells us that their price/performance ratio has been one of the major design objectives. But if you take as “performance” the duty cycle of the machine’s various components, little will prevent you from ending up with a design in which the major part of your performance goal is reached by internal housekeeping activities of doubtful necessity. And if your definition of price is the price to be paid for the hardware, little will prevent you from ending up with a design that is terribly hard to program for: for instance the order code might be such as to enforce, either upon the programmer or upon the system, early binding decisions presenting conflicts that really cannot be resolved. And to a large extent these unpleasant possibilities seem to have become reality.

When these machines were announced and their functional specifications became known, quite a few among us must have become quite miserable; at least I was. It was only reasonable to expect that such machines would flood the computing community, and it was therefore all the more important that their design should be as sound as possible. But the design embodied such serious flaws that I felt that with a single stroke the progress of computing science had been retarded by at least ten years: it was then that I had the blackest week in the whole of my professional life. Perhaps the most saddening thing now is that, even after all those years of frustrating experience, still so many people honestly believe that some law of nature tells us that machines have to be that way. They silence their doubts by observing how many of these machines have been sold, and derive from that observation the false sense of security that, after all, the design cannot have been that bad. But upon closer inspection, that line of defense has the same convincing strength as the argument that cigarette smoking must be healthy because so many people do it.

It is in this connection that I regret that it is not customary for scientific journals in the computing area to publish reviews of newly announced computers in much the same way as we review scientific publications: to review machines would be at least as important. And here I have a confession to make: in the early sixties I wrote such a review with the intention of submitting it to the CACM, but in spite of the fact that the few colleagues to whom the text was sent for their advice, urged me all to do so, I did not dare to do it, fearing that the difficulties either for myself or for the editorial board would prove to be too great. This suppression was an act of cowardice on my side for which I blame myself more and more. The difficulties I foresaw were a consequence of the absence of generally accepted criteria, and although I was convinced of the validity of the criteria I had chosen to apply, I feared that my review would be refused or discarded as “a matter of personal taste”. I still think that such reviews would be extremely useful and I am longing to see them appear, for their accepted appearance would be a sure sign of maturity of the computing community.

The reason that I have paid the above attention to the hardware scene is because I have the feeling that one of the most important aspects of any computing tool is its influence on the thinking habits of those that try to use it, and because I have reasons to believe that that influence is many times stronger than is commonly assumed. Let us now switch our attention to the software scene.

Here the diversity has been so large that I must confine myself to a few stepping stones. I am painfully aware of the arbitrariness of my choice and I beg you not to draw any conclusions with regard to my appreciation of the many efforts that will remain unmentioned.

In the beginning there was the EDSAC in Cambridge, England, and I think it quite impressive that right from the start the notion of a subroutine library played a central role in the design of that machine and of the way in which it should be used. It is now nearly 25 years later and the computing scene has changed dramatically, but the notion of basic software is still with us, and the notion of the closed subroutine is still one of the key concepts in programming. We should recognise the closed subroutines as one of the greatest software inventions; it has survived three generations of computers and it will survive a few more, because it caters for the implementation of one of our basic patterns of abstraction. Regrettably enough, its importance has been underestimated in the design of the third generation computers, in which the great number of explicitly named registers of the arithmetic unit implies a large overhead on the subroutine mechanism. But even that did not kill the concept of the subroutine, and we can only pray that the mutation won’t prove to be hereditary.

The second major development on the software scene that I would like to mention is the birth of FORTRAN. At that time this was a project of great temerity and the people responsible for it deserve our great admiration. It would be absolutely unfair to blame them for shortcomings that only became apparent after a decade or so of extensive usage: groups with a successful look-ahead of ten years are quite rare! In retrospect we must rate FORTRAN as a successful coding technique, but with very few effective aids to conception, aids which are now so urgently needed that time has come to consider it out of date. The sooner we can forget that FORTRAN has ever existed, the better, for as a vehicle of thought it is no longer adequate: it wastes our brainpower, is too risky and therefore too expensive to use. FORTRAN’s tragic fate has been its wide acceptance, mentally chaining thousands and thousands of programmers to our past mistakes. I pray daily that more of my fellow-programmers may find the means of freeing themselves from the curse of compatibility.

The third project I would not like to leave unmentioned is LISP, a fascinating enterprise of a completely different nature. With a few very basic principles at its foundation, it has shown a remarkable stability. Besides that, LISP has been the carrier for a considerable number of in a sense our most sophisticated computer applications. LISP has jokingly been described as “the most intelligent way to misuse a computer”. I think that description a great compliment because it transmits the full flavour of liberation: it has assisted a number of our most gifted fellow humans in thinking previously impossible thoughts.

The fourth project to be mentioned is ALGOL 60. While up to the present day FORTRAN programmers still tend to understand their programming language in terms of the specific implementation they are working with —hence the prevalence of octal and hexadecimal dumps—, while the definition of LISP is still a curious mixture of what the language means and how the mechanism works, the famous Report on the Algorithmic Language ALGOL 60 is the fruit of a genuine effort to carry abstraction a vital step further and to define a programming language in an implementation-independent way. One could argue that in this respect its authors have been so successful that they have created serious doubts as to whether it could be implemented at all! The report gloriously demonstrated the power of the formal method BNF, now fairly known as Backus-Naur-Form, and the power of carefully phrased English, a least when used by someone as brilliant as Peter Naur. I think that it is fair to say that only very few documents as short as this have had an equally profound influence on the computing community. The ease with which in later years the names ALGOL and ALGOL-like have been used, as an unprotected trade mark, to lend some of its glory to a number of sometimes hardly related younger projects, is a somewhat shocking compliment to its standing. The strength of BNF as a defining device is responsible for what I regard as one of the weaknesses of the language: an over-elaborate and not too systematic syntax could now be crammed into the confines of very few pages. With a device as powerful as BNF, the Report on the Algorithmic Language ALGOL 60 should have been much shorter. Besides that I am getting very doubtful about ALGOL 60’s parameter mechanism: it allows the programmer so much combinatorial freedom, that its confident use requires a strong discipline from the programmer. Besides expensive to implement it seems dangerous to use.

Finally, although the subject is not a pleasant one, I must mention PL/1, a programming language for which the defining documentation is of a frightening size and complexity. Using PL/1 must be like flying a plane with 7000 buttons, switches and handles to manipulate in the cockpit. I absolutely fail to see how we can keep our growing programs firmly within our intellectual grip when by its sheer baroqueness the programming language —our basic tool, mind you!— already escapes our intellectual control. And if I have to describe the influence PL/1 can have on its users, the closest metaphor that comes to my mind is that of a drug. I remember from a symposium on higher level programming language a lecture given in defense of PL/1 by a man who described himself as one of its devoted users. But within a one-hour lecture in praise of PL/1. he managed to ask for the addition of about fifty new “features”, little supposing that the main source of his problems could very well be that it contained already far too many “features”. The speaker displayed all the depressing symptoms of addiction, reduced as he was to the state of mental stagnation in which he could only ask for more, more, more… When FORTRAN has been called an infantile disorder, full PL/1, with its growth characteristics of a dangerous tumor, could turn out to be a fatal disease.

So much for the past. But there is no point in making mistakes unless thereafter we are able to learn from them. As a matter of fact, I think that we have learned so much, that within a few years programming can be an activity vastly different from what it has been up till now, so different that we had better prepare ourselves for the shock. Let me sketch for you one of the possible futures. At first sight, this vision of programming in perhaps already the near future may strike you as utterly fantastic. Let me therefore also add the considerations that might lead one to the conclusion that this vision could be a very real possibility.

The vision is that, well before the seventies have run to completion, we shall be able to design and implement the kind of systems that are now straining our programming ability, at the expense of only a few percent in man-years of what they cost us now, and that besides that, these systems will be virtually free of bugs. These two improvements go hand in hand. In the latter respect software seems to be different from many other products, where as a rule a higher quality implies a higher price. Those who want really reliable software will discover that they must find means of avoiding the majority of bugs to start with, and as a result the programming process will become cheaper. If you want more effective programmers, you will discover that they should not waste their time debugging, they should not introduce the bugs to start with. In other words: both goals point to the same change.

Such a drastic change in such a short period of time would be a revolution, and to all persons that base their expectations for the future on smooth extrapolation of the recent past —appealing to some unwritten laws of social and cultural inertia— the chance that this drastic change will take place must seem negligible. But we all know that sometimes revolutions do take place! And what are the chances for this one?

There seem to be three major conditions that must be fulfilled. The world at large must recognize the need for the change; secondly the economic need for it must be sufficiently strong; and, thirdly, the change must be technically feasible. Let me discuss these three conditions in the above order.

With respect to the recognition of the need for greater reliability of software, I expect no disagreement anymore. Only a few years ago this was different: to talk about a software crisis was blasphemy. The turning point was the Conference on Software Engineering in Garmisch, October 1968, a conference that created a sensation as there occurred the first open admission of the software crisis. And by now it is generally recognized that the design of any large sophisticated system is going to be a very difficult job, and whenever one meets people responsible for such undertakings, one finds them very much concerned about the reliability issue, and rightly so. In short, our first condition seems to be satisfied.

Now for the economic need. Nowadays one often encounters the opinion that in the sixties programming has been an overpaid profession, and that in the coming years programmer salaries may be expected to go down. Usually this opinion is expressed in connection with the recession, but it could be a symptom of something different and quite healthy, viz. that perhaps the programmers of the past decade have not done so good a job as they should have done. Society is getting dissatisfied with the performance of programmers and of their products. But there is another factor of much greater weight. In the present situation it is quite usual that for a specific system, the price to be paid for the development of the software is of the same order of magnitude as the price of the hardware needed, and society more or less accepts that. But hardware manufacturers tell us that in the next decade hardware prices can be expected to drop with a factor of ten. If software development were to continue to be the same clumsy and expensive process as it is now, things would get completely out of balance. You cannot expect society to accept this, and therefore we must learn to program an order of magnitude more effectively. To put it in another way: as long as machines were the largest item on the budget, the programming profession could get away with its clumsy techniques, but that umbrella will fold rapidly. In short, also our second condition seems to be satisfied.

And now the third condition: is it technically feasible? I think it might and I shall give you six arguments in support of that opinion.

A study of program structure had revealed that programs —even alternative programs for the same task and with the same mathematical content— can differ tremendously in their intellectual manageability. A number of rules have been discovered, violation of which will either seriously impair or totally destroy the intellectual manageability of the program. These rules are of two kinds. Those of the first kind are easily imposed mechanically, viz. by a suitably chosen programming language. Examples are the exclusion of goto-statements and of procedures with more than one output parameter. For those of the second kind I at least —but that may be due to lack of competence on my side— see no way of imposing them mechanically, as it seems to need some sort of automatic theorem prover for which I have no existence proof. Therefore, for the time being and perhaps forever, the rules of the second kind present themselves as elements of discipline required from the programmer. Some of the rules I have in mind are so clear that they can be taught and that there never needs to be an argument as to whether a given program violates them or not. Examples are the requirements that no loop should be written down without providing a proof for termination nor without stating the relation whose invariance will not be destroyed by the execution of the repeatable statement.

I now suggest that we confine ourselves to the design and implementation of intellectually manageable programs. If someone fears that this restriction is so severe that we cannot live with it, I can reassure him: the class of intellectually manageable programs is still sufficiently rich to contain many very realistic programs for any problem capable of algorithmic solution. We must not forget that it is not our business to make programs, it is our business to design classes of computations that will display a desired behaviour. The suggestion of confining ourselves to intellectually manageable programs is the basis for the first two of my announced six arguments.

Argument one is that, as the programmer only needs to consider intellectually manageable programs, the alternatives he is choosing between are much, much easier to cope with.

Argument two is that, as soon as we have decided to restrict ourselves to the subset of the intellectually manageable programs, we have achieved, once and for all, a drastic reduction of the solution space to be considered. And this argument is distinct from argument one.

Argument three is based on the constructive approach to the problem of program correctness. Today a usual technique is to make a program and then to test it. But: program testing can be a very effective way to show the presence of bugs, but is hopelessly inadequate for showing their absence. The only effective way to raise the confidence level of a program significantly is to give a convincing proof of its correctness. But one should not first make the program and then prove its correctness, because then the requirement of providing the proof would only increase the poor programmer’s burden. On the contrary: the programmer should let correctness proof and program grow hand in hand. Argument three is essentially based on the following observation. If one first asks oneself what the structure of a convincing proof would be and, having found this, then constructs a program satisfying this proof’s requirements, then these correctness concerns turn out to be a very effective heuristic guidance. By definition this approach is only applicable when we restrict ourselves to intellectually manageable programs, but it provides us with effective means for finding a satisfactory one among these.

Argument four has to do with the way in which the amount of intellectual effort needed to design a program depends on the program length. It has been suggested that there is some kind of law of nature telling us that the amount of intellectual effort needed grows with the square of program length. But, thank goodness, no one has been able to prove this law. And this is because it need not be true. We all know that the only mental tool by means of which a very finite piece of reasoning can cover a myriad cases is called “abstraction”; as a result the effective exploitation of his powers of abstraction must be regarded as one of the most vital activities of a competent programmer. In this connection it might be worth-while to point out that the purpose of abstracting is not to be vague, but to create a new semantic level in which one can be absolutely precise. Of course I have tried to find a fundamental cause that would prevent our abstraction mechanisms from being sufficiently effective. But no matter how hard I tried, I did not find such a cause. As a result I tend to the assumption —up till now not disproved by experience— that by suitable application of our powers of abstraction, the intellectual effort needed to conceive or to understand a program need not grow more than proportional to program length. But a by-product of these investigations may be of much greater practical significance, and is, in fact, the basis of my fourth argument. The by-product was the identification of a number of patterns of abstraction that play a vital role in the whole process of composing programs. Enough is now known about these patterns of abstraction that you could devote a lecture to about each of them. What the familiarity and conscious knowledge of these patterns of abstraction imply dawned upon me when I realized that, had they been common knowledge fifteen years ago, the step from BNF to syntax-directed compilers, for instance, could have taken a few minutes instead of a few years. Therefore I present our recent knowledge of vital abstraction patterns as the fourth argument.

Now for the fifth argument. It has to do with the influence of the tool we are trying to use upon our own thinking habits. I observe a cultural tradition, which in all probability has its roots in the Renaissance, to ignore this influence, to regard the human mind as the supreme and autonomous master of its artefacts. But if I start to analyse the thinking habits of myself and of my fellow human beings, I come, whether I like it or not, to a completely different conclusion, viz. that the tools we are trying to use and the language or notation we are using to express or record our thoughts, are the major factors determining what we can think or express at all! The analysis of the influence that programming languages have on the thinking habits of its users, and the recognition that, by now, brainpower is by far our scarcest resource, they together give us a new collection of yardsticks for comparing the relative merits of various programming languages. The competent programmer is fully aware of the strictly limited size of his own skull; therefore he approaches the programming task in full humility, and among other things he avoids clever tricks like the plague. In the case of a well-known conversational programming language I have been told from various sides that as soon as a programming community is equipped with a terminal for it, a specific phenomenon occurs that even has a well-established name: it is called “the one-liners”. It takes one of two different forms: one programmer places a one-line program on the desk of another and either he proudly tells what it does and adds the question “Can you code this in less symbols?” —as if this were of any conceptual relevance!— or he just asks “Guess what it does!”. From this observation we must conclude that this language as a tool is an open invitation for clever tricks; and while exactly this may be the explanation for some of its appeal, viz. to those who like to show how clever they are, I am sorry, but I must regard this as one of the most damning things that can be said about a programming language. Another lesson we should have learned from the recent past is that the development of “richer” or “more powerful” programming languages was a mistake in the sense that these baroque monstrosities, these conglomerations of idiosyncrasies, are really unmanageable, both mechanically and mentally. I see a great future for very systematic and very modest programming languages. When I say “modest”, I mean that, for instance, not only ALGOL 60’s “for clause”, but even FORTRAN’s “DO loop” may find themselves thrown out as being too baroque. I have run a a little programming experiment with really experienced volunteers, but something quite unintended and quite unexpected turned up. None of my volunteers found the obvious and most elegant solution. Upon closer analysis this turned out to have a common source: their notion of repetition was so tightly connected to the idea of an associated controlled variable to be stepped up, that they were mentally blocked from seeing the obvious. Their solutions were less efficient, needlessly hard to understand, and it took them a very long time to find them. It was a revealing, but also shocking experience for me. Finally, in one respect one hopes that tomorrow’s programming languages will differ greatly from what we are used to now: to a much greater extent than hitherto they should invite us to reflect in the structure of what we write down all abstractions needed to cope conceptually with the complexity of what we are designing. So much for the greater adequacy of our future tools, which was the basis of the fifth argument.

As an aside I would like to insert a warning to those who identify the difficulty of the programming task with the struggle against the inadequacies of our current tools, because they might conclude that, once our tools will be much more adequate, programming will no longer be a problem. Programming will remain very difficult, because once we have freed ourselves from the circumstantial cumbersomeness, we will find ourselves free to tackle the problems that are now well beyond our programming capacity.

You can quarrel with my sixth argument, for it is not so easy to collect experimental evidence for its support, a fact that will not prevent me from believing in its validity. Up till now I have not mentioned the word “hierarchy”, but I think that it is fair to say that this is a key concept for all systems embodying a nicely factored solution. I could even go one step further and make an article of faith out of it, viz. that the only problems we can really solve in a satisfactory manner are those that finally admit a nicely factored solution. At first sight this view of human limitations may strike you as a rather depressing view of our predicament, but I don’t feel it that way, on the contrary! The best way to learn to live with our limitations is to know them. By the time that we are sufficiently modest to try factored solutions only, because the other efforts escape our intellectual grip, we shall do our utmost best to avoid all those interfaces impairing our ability to factor the system in a helpful way. And I cannot but expect that this will repeatedly lead to the discovery that an initially untractable problem can be factored after all. Anyone who has seen how the majority of the troubles of the compiling phase called “code generation” can be tracked down to funny properties of the order code, will know a simple example of the kind of things I have in mind. The wider applicability of nicely factored solutions is my sixth and last argument for the technical feasibility of the revolution that might take place in the current decade.

In principle I leave it to you to decide for yourself how much weight you are going to give to my considerations, knowing only too well that I can force no one else to share my beliefs. As each serious revolution, it will provoke violent opposition and one can ask oneself where to expect the conservative forces trying to counteract such a development. I don’t expect them primarily in big business, not even in the computer business; I expect them rather in the educational institutions that provide today’s training and in those conservative groups of computer users that think their old programs so important that they don’t think it worth-while to rewrite and improve them. In this connection it is sad to observe that on many a university campus the choice of the central computing facility has too often been determined by the demands of a few established but expensive applications with a disregard of the question how many thousands of “small users” that are willing to write their own programs were going to suffer from this choice. Too often, for instance, high-energy physics seems to have blackmailed the scientific community with the price of its remaining experimental equipment. The easiest answer, of course, is a flat denial of the technical feasibility, but I am afraid that you need pretty strong arguments for that. No reassurance, alas, can be obtained from the remark that the intellectual ceiling of today’s average programmer will prevent the revolution from taking place: with others programming so much more effectively, he is liable to be edged out of the picture anyway.

There may also be political impediments. Even if we know how to educate tomorrow’s professional programmer, it is not certain that the society we are living in will allow us to do so. The first effect of teaching a methodology —rather than disseminating knowledge— is that of enhancing the capacities of the already capable, thus magnifying the difference in intelligence. In a society in which the educational system is used as an instrument for the establishment of a homogenized culture, in which the cream is prevented from rising to the top, the education of competent programmers could be politically impalatable.

Let me conclude. Automatic computers have now been with us for a quarter of a century. They have had a great impact on our society in their capacity of tools, but in that capacity their influence will be but a ripple on the surface of our culture, compared with the much more profound influence they will have in their capacity of intellectual challenge without precedent in the cultural history of mankind. Hierarchical systems seem to have the property that something considered as an undivided entity on one level, is considered as a composite object on the next lower level of greater detail; as a result the natural grain of space or time that is applicable at each level decreases by an order of magnitude when we shift our attention from one level to the next lower one. We understand walls in terms of bricks, bricks in terms of crystals, crystals in terms of molecules etc. As a result the number of levels that can be distinguished meaningfully in a hierarchical system is kind of proportional to the logarithm of the ratio between the largest and the smallest grain, and therefore, unless this ratio is very large, we cannot expect many levels. In computer programming our basic building block has an associated time grain of less than a microsecond, but our program may take hours of computation time. I do not know of any other technology covering a ratio of 1010 or more: the computer, by virtue of its fantastic speed, seems to be the first to provide us with an environment where highly hierarchical artefacts are both possible and necessary. This challenge, viz. the confrontation with the programming task, is so unique that this novel experience can teach us a lot about ourselves. It should deepen our understanding of the processes of design and creation, it should give us better control over the task of organizing our thoughts. If it did not do so, to my taste we should not deserve the computer at all!

It has already taught us a few lessons, and the one I have chosen to stress in this talk is the following. We shall do a much better programming job, provided that we approach the task with a full appreciation of its tremendous difficulty, provided that we stick to modest and elegant programming languages, provided that we respect the intrinsic limitations of the human mind and approach the task as Very Humble Programmers.

原文:原文地址

谦逊的程序员


谦逊的程序员
Edsger W. Dijkstra
黄索远(译)

1952年初春的早晨,由于一系列巧合,我正式进入了编程界,成为了程序员历史上第一位荷兰人。回想起来,程序员作为一种职业,是以现在很难相信的缓慢速度出现的,至少在我所了解的范围内是这样,这让人非常惊奇。那个缓慢时期的两段清晰回忆让我心存感激。

在有了三年编程经验后,我和当时我在阿姆斯特丹数学中心的老板 A. Van Wijngaarden(译注:荷兰数学家和计算机科学家),进行了一场讨论,关于这场讨论我在有生之年都会感激他。讨论的焦点在于,我本来是要在编程的同时,在莱顿大学学习理论物理,但是当发现鱼和熊掌不可兼得时,我不得不做出选择,要么停止编程,成为一个名符其实的可敬的理论物理学家;或者把我的物理学研究敷衍了事,而成为一个…那个叫什么?程序员?但那是个受人尊敬的职业么?什么又是编程呢?它作为一门学科所需要的完备知识体系又在哪里呢?我非常清晰得记得自己有多嫉妒我从事硬件的同僚们,因为当被问到专业技能时,他们至少可以谈自己所知道关于真空管,放大器,和其他一些硬件的一切;而被问到这个问题时,我只能茫然无措。满心焦虑,我敲开了 van Wijngaarden 的办公室大门,问道:“是否能占用他一点时间”;而在几个小时后离开他办公室时,我整个人焕然一新。在耐心听完我的问题后,他同意当时并没有学科是关于编程的,但是他接下来解释说,自动化电脑会继续发展,而我们正处于摸索阶段,那我能不能成为先驱者之一,使编程在未来成为一个受人认可的学科呢?这成了我人生中的一个转折点,促使我尽快完成了我的物理学研究。上述故事的寓意是,我们必须谨慎地向年轻人提供意见,因为有时他们真的会听的!

荷兰婚礼仪式上有要求新人陈述职业的传统,而两年后的1957年,当我结婚时我宣告自己是一名程序员。但是阿姆斯特丹的市政当局没有接受,理由是并不存在程序员这样一种职业。不管你信不信,在我婚姻证书上“职业”这一栏里,可笑的写着“理论物理学家”!

关于程序员作为一种职业在我国的缓慢出现,就说这么多了。从那时起,我见识到了外面的世界,留下的总体印象是,尽管起步的时间不同,但是其他国家的发展模式是大同小异的。

让我尝试更多地回顾下昔日的一些细节,以期更好地理解现在的情况。现在我们对问题进行分析时,应该知道,关于编程任务很多常见误解是可以追溯到很久以前的。

第一代的电子计算机是独特的机器,并且只能在各种进行开拓性试验的实验室里被找到。从人类见识了自动化计算机那天起,实现它就是对当时现有的电子技术一个巨大挑战,不过有一件事很确定,那就是我们不能否认那些致力于开发这些设备先驱们的勇气。这些设备是如此的令人惊奇,回想起来,至少是有时候,人们只能怀疑,这些机器是否真的运行起来了。最难解决的问题就在于让机器跑起来并让其保持工作秩序。一些较老的计算机科学学会的命名中依然反映着自动计算机硬件方面的当务之急,如美国计算机协会(ACM)和英国计算机协会,这些协会的名称中明确提到了物理设备。

那么可怜的程序员又是什么样的处境呢?实情是:他根本没有被人注意。一方面,第一代计算机是如此得笨重,以至于无法搬来搬去,同时,它们又需要大规模的维护,因此很自然的,人们就在发明这些计算机的实验室里使用它们。另一方面,程序员的工作既不为人所知又缺少魅力,在打动参观者的程度上,展示机器比展示几页代码要高出几个数量级。但是最重要的是,程序员以非常谦逊的眼光看待自己的工作:程序员工作的所有重要性都继承自硬件设备。因为每一台计算机都是不同的,程序员非常清楚,他的程序只有在特定计算机上才能运行,并且由于计算机的寿命有限,导致他的工作会随着机器的老化而丧失价值。最后,还有一种情况对程序员的工作态度产生了深远的影响:一方面,除了不稳定,他工作的机器一般还存在运行缓慢、内存太小等问题,这让巧妇难为无米之炊;另一方面,程序中通常又会存在少量古怪代码来应对突发的状况。在那些日子里,有很多聪明的程序员通过一些巧妙的方法,使他的设备可以完成一些本来不可能完成的任务,以这样的方式来获得智力上的巨大满足感。

关于编程的两种观点就起源于那个时期。我现在提下这件事,等下会回到这个话题。一种观点认为真正专业的程序员应该具有解决问题的头脑,并且非常喜欢聪明的伎俩;另一种观点认为,编程就是在某个方向上优化计算效率的过程。

后一种观点源自于设备落后的年代,那时候有些人简单的期望着,一旦机器变得更为强大,编程将不会成为难题,到那时想尽办法榨干机器的性能将不再有必要,这就是编程的目的,难道不是吗?但是下一个十年里发生了巨变,更为强大的机器被造出来了,不是一个数量级的强大,而是好几个数量级的强大。但是出人意料的是,我们并没有一劳永逸地解决所有的问题,反而发现自己处在了软件危机中!这是怎么回事呢?

一个小小的原因是:现代计算机在一个或两个方面比老式的计算机更难以操作。首先,现代计算机有I/O中断,中断的发生不可预知也不可重现,这个特性与能完全掌控运行过程的旧式计算机相比,是一个巨大的变化,但是这个特性会产生难以预料的逻辑错误,很多程序员花白的头发见证了这一点。第二,现在的计算机配置了多级存储设备,关于设备管理的策略,虽然已经有大量的文献,但是对我们来说仍然相当难以捉摸。关于计算机结构的变化所增加的复杂性就讲这么多了。

但是上面所举的只是“小”原因,真正大的原因是…现代计算机性能比原来强大了好几个数量级!可以不客气的说:当世上没有计算机的时候,根本就不会有编程问题;当我们有了几台性能弱小的计算机后,编程就出现小问题了,现在我们有了性能强大的计算机,编程自然变成了巨大的问题。在这样的发展过程中,电子产业非但没有解决一个问题,而是产生了问题,即使用产品所带来的问题。换种方式说,如果现有计算机性能增长了千分之一,那么社会对于使用这些机器的期望也会以同样的比例增长,而可怜的程序员会发现自己处于到底是目的优先还是方式优先的紧张选择中。硬件性能的提升,加上其可靠性甚至更急剧的提升,使得几年前程序员做梦都不敢想的问题变得可以实现。而几年后,他不得不梦见这个问题,更糟的是,他不得不将这样的梦变成现实!那么我们发现自己仍身处于软件危机中是不是一个奇迹呢?当然不是了,正如你猜测的那样,这些甚至是可以提前预知的,只不过这种小众预测的问题在于五年后你才能知道它是正确的。

接着在六十年代中期,有一件可怕的事情发生:所谓的第三代计算机出现了。官方的文献表示,性价比一直是他们主要的设计目标之一。但是如果你将机器众多组件的占空比作为“表现”的衡量标准,你会看到一个内存被必要性存疑的内部常驻活动所占据的设计。如果你对于价格的定义是硬件的价值,你会看到一个对其编程极其困难的设计:举个例子,无论对于程序员还是系统,用于执行的指令码早期绑定所带来的问题都不能真正得到解决。并且在很大程度上,这些令人不快的可能性看起来已经成为了现实。

当这样的机器宣布发售,其功能规格为人所知后,我们之中的不少人肯定相当难受,至少我是这样。第三代计算机的发行肯定会席卷计算机界,而人们更加期待它的设计能够尽量健全。但是因为这样一个有着如此严重缺陷的设计,让我感觉到计算机科学至少退步了十年:这也让我的职业生涯经历了最为黑暗的一个星期。也许最可悲的事情是,即使有了这么多年令人沮丧的经验,依然有如此多的人天真的相信计算机必须是这样。他们用机器的销量来打消自己的疑虑,并且从这种观察中得到使用这些机器是安全的错觉,毕竟,机器的设计不可能那样糟糕。但是仔细想想,这种被销量欺骗的安全感就和吸烟必须是健康的说法相差无几,因为吸烟的人很多。

正是这方面,我很遗憾,在发表对最新公布的计算机的评论时,计算机领域的科学期刊并没有习惯像其他科学出版物那样做出复查:对机器的复查至少应该同样重要。这里我要检讨:在六十年代早期,我写过这样的评论并准备提交给CACM,尽管我没有向同事们寻求建议,但他们极力主张我这样做,可我还是不敢,因为担心这样无论对我还是对编委会来说,困难都太大。是懦弱没有让我提交这样一份报告,对此我越来越自责。我预见到的困难是当时缺乏普遍接受的标准,虽然确信自己的标准是正确的,但我还是担心我的报告会被拒绝,或者被贴上“个人口味问题”的标签。我仍然认为这样的报告是及其有用的,并且渴望着它们的出现,因为它们的出现将代表着计算机界的成熟。

之所以对硬件保持上面提到那样的关注,是因为我相信影响那些使用者的思考习惯是任何计算工具最重要的作用之一,并且我有理由相信,这种影响力比预期的更为强烈。现在让我们的注意力回到软件上。

由于软件具有显著的多样性,我必须将自己限制在几个立足点上。这使得我做出的选择显得很武断,也让我觉得很痛苦,希望大家不要因此怀疑我对其他没有提到的努力的欣赏。

刚开始的时候,EDSAC 在英国的剑桥兴起,我对其起初让子程序库在机器设计和使用方法中发挥主要作业的观点印象深刻。接近25年后的今天,计算领域彻底的变化了,但是软件的基本观念还伴随着我们,闭合子程序的观念也还是我们编程的核心概念之一。我们应该认可闭合子程序作为最伟大的软件发明之一,它经历了三代计算机的发展并且仍将继续存活几代,因为它迎合了我们基本抽象模式的接口思想。遗憾的是,在第三代计算机的设计中,它的重要性被低估了,而这个设计中,大量明确命名为寄存器的算术计算单位揭示了子程序机制的广泛使用。尽管如此,也没有让子程序的概念就此消失,我们只能祈祷这种变化不会在下一代的计算机中被遗传。

我要讲的第二个软件业的主要发展是FORTRAN的诞生。在当时这是一个伟大而冒失的计划,负责这个计划的人们值得我们大声地赞美。因为大约10年后才日渐明显的外延错误用法而去责备他们是显然不公平的:能够成功预测十年后的团队相当罕见。当我们回顾过去时,必须把FORTRAN看做一项成功但是对其产生概念基本没啥帮助的编码技术,在需求如此迫切的现在,这项技术已经过时了。我们应该尽快忘记FORTRAN,对于思想的马车而言,它不再胜任:它浪费了我们的脑力,使用它过于冒险,因此也太过奢侈。FORTRAN的悲惨命运已经因为它广泛的接受度,影响了数以千计的程序员为我们过去的错误买单。我每天都祈祷,会有更多程序员小伙伴找到从通用性的祸害中解脱出来的方法。

第三个不能忽略的就是LISP,一个完全与众不同的迷人设计。基于LISP的几个基本原则使得LISP展示出了非凡的健壮性。除此以外,LISP成为了相当多的复杂计算机载体。LISP曾经被调侃为滥用电脑的最智能方法。我想这种描述是一种很高的赞美,因为它传递了解放的气息——它已经帮助我们之中最有天赋的人思考了之前不可能思考的东西。

第四个要提到的就是 ALGOL 60。到目前为止,FORTRAN程序员仍然倾向于从他们的开发中了解他们的编程语言——八进制的兴起和十六进制的衰落;而LISP的定义依然是一种令人好奇的混合体,其中包括这门语言意味着什么和这门机制是怎么工作的,《算法语言》那篇著名的报告中说道,ALGOL 60是真正努力去承载抽象概念至关重要的一步,再加上通过独立于语言之外的方法定义一门编程语言的成果。有人会说,ALGOL 60的作者们已经如此的成功,以至于他们自己引出这门语言是否可以实现产生的严肃疑问!那篇报告冠冕堂皇地展示了BNF范式(即现在人尽皆知的Backs-Naur-Form)的作用,和英语谨慎措辞的力量,至少是像Peter Naur一样聪明的人使用时。我觉得可以负责任地说,基本没有像它这么短而在计算机界有相同影响力的文档存在。人们习惯于使用用“ALGOL”或者是“类ALGOL”这样未经保护的标签,向大量基本不相关的年轻语言分享ALGOL的荣耀,这本身某种程度上就是对ALGOL惊人生命力的极大致敬。BNF作为一种严格定义的语言,它的长处导致了我个人认为是这门语言的缺点——过分精心制作并且语法定义不规则,很难在几页纸中完全说明。如果有个BNF般强大的设备,《算术语言》中那篇关于ALGOL60的报告可以变得更短很多。除此以外,我对ALGOL60的参数机制表示怀疑,它赋予程序员如此多的组合自由,以至于要求程序员更自律。除了开发成本外,它使用起来似乎也很危险。

最后,尽管令人不太愉快,但我必须提及——PL/1,一门描述文档非常庞大而且复杂的编程语言。使用PL/1就像开着一架有着7000个按钮,使用开关和扳手操作的飞机。我完全不能理解怎么靠智力来把握这种完全怪异的编程语言(我们的基本工具),使之保持稳定的发展,提醒你,这已经脱离我们智力的掌控了。还有如果非要描述PL/1对其用户的影响,我脑海中最为形象的隐喻就是毒品。我记得这个出自一个自称是PL/1的忠实用户在一个高级语言的专题讨论会上做的一个演讲。但是,在这个为期一小时充满对PL/1赞美的演讲中,他希望大家添加50种新特性,却没有想过他问题的源头是这门语言已经包含了太多的特性。演讲者展示了所有令人沮丧大的症状,他陷入内心停滞,但是渴求更多。当FORTRAN被称为婴儿期的凌乱时,完整的PL/1却是危险的肿瘤,最后成长为了一种致命病毒。

关于过去的事,就讲这么多吧。但是如果我们不能从中汲取教训的话,制造错误是没有任何意义的。事实上,我觉得我们学习了如此多的错误,以至于几年后的编程可以和之前截然不同。让我简述下你们可能的未来。乍看一下,这种编程的想象也许会让你不久的将来变得非常的不切实际。所以也允许加上也许会让人得出“这个人的想象相对实际”的结论的考虑吧。

这种想象就是,在七十年代结束之前,我们有可能设计和实现那种尽量利用编程能力,开支是许多年前百分之几的系统。此外,这些系统可以几乎摆脱bug。这两项提升相辅相成。在后一个方面,软件看上去和许多其他产品不同,很多产品质量和价格是成正比的。那些想要真正有效的软件的人将会发现他们必须从找到避免大多数bug的方法开始,最后,编程过程将变得便宜。如果你想要一些有能力的程序员,你将发现他们不会浪费时间在调试上,他们不应该以调试bug作为开始。换句话说,两种目标指向同样的变化。

在如此短的一段时间内发生如此激烈的变革,这会是一场革命,对所有人来说,基于他们对未来的期望,对过去(诉诸不成文的社会,文化惰性的法律)做出的和平推断,这种巨大变革会发生的机会几乎微不足道。但我们都知道有时候革命真的发生了。 那么这次变革我们的机遇是什么呢?

似乎有三个主要条件需要满足。一般来说,世界必须承认需要变化,第二经济需求十分强烈,还有第三,变革在技术上是可行的。让我讨论按顺序讨论一下上述三个条件。

谈到对软件更为可靠的需求,我表示完全同意。在几年前,就不一样了——讨论软件危机是对上帝的亵渎。转折点是 1968年十月在Garmisch举行的软件工程的学术会议,一次萌生了知觉承认软件危机的回忆。到目前为止,普遍认为任何大型系统的设计都是一项十分困难的工作,无论何时,人们遇到负责这样工作的人,都会发现他们非常关心可靠性问题。简而言之,我们第一个条件似乎满足了。

现在说到经济需求。现在人们总是遇到说六十年代编程是一个薪酬过高的职业的观点,并且说未来几年内,程序员薪酬希望可以下降。通常,这种观点的表述与经济衰退有关,但这是一种不同,健康的事物的征兆——也许过去几十年里程序员没有很好完成他们应该完成的工作。社会对程序员的表现和他们的产品感到不满意。但还存在另外一种导致重担的因素。现在的情况是,对于特定的系统,为软件升级的价格和升级硬件的价格在同一个数量级,社会或多或少接受了这一点。但硬件制造商告诉我们说在接下来数十年,硬件价格将会以十倍速度下降。如果软件发展还是一如既往的笨拙,程序一如既往的昂贵,局势将失去平衡。你不能指望社会接受这一点,因此我们必须学会有效的编程。 换句话说,只要机器还是预算中的大项,那么笨拙的编程技术还能侥幸逃脱,但是保护伞会快的折起来。总之,我们的第二个条件似乎也能满足。

现在轮到第三个条件,技术上可行吗?我觉得可行,我会用六个论据支撑我的观点。

一份程序结构的研究表明程序,即便是同一个任务的替补程序和有着相同的数学内容,在程序管理方面都有着巨大的差异。研究发现许多规律,违反任何一条规律要么局部或者整体的破坏程序的人为管理。这些规律不外乎两种。第一种容易在物理上加以利用,即选用合适的编程语言。Goto语句的和多输出参数的程序的剔除是很好的佐证。对于第二种,我至少看不到物理上使之暴露的方法(可能是我能力不足),好像需要一些我没有证明存在的自动化的定理证明程序。因此,第二种规律时不时作为程序员训练的要素之一出现。有些规律我清楚的知道以至于可以教给他人和不需要判断一段给定的程序是否违反了。 我们给出必要的例子——任何循环需要给出终止条件或者声明不变量之间的关系保证不变量不会被程序的循环语句执行而破坏。

我现在提议把我们限制在智能可控程序的设计和实现的范围内。如果有些人害怕这种限制过于严格,我们没有办法存活,我保证智能可控程序的种类足够的丰富,可以囊括现实很多能够解决算术问题的程序。我们不能忘记我们的职业不是为了编程,而是设计能够表现预设行为的计算类别。把我们限制在智能可控程序的建议是我所谓的六个论据的前两个的基础。

论据一,程序员只要考虑智能可控问题,选择更为容易考虑。

论据二,我们一决定把我们限制在智能可控程序的子集内,我们就一劳永逸的实现了考虑解决方案的空间的减少。

论据三是建立在程序正确性问题的建设性方法上的。今天,一项普通的技术就是写一个程序,然后去测试。 尽管,程序测试是一种非常有效的方法去暴露bugs,但对证明不存在bugs几乎是完全没用的。显著提高程序可信度唯一有效的方法是给出一个令人信服的关于正确性的证据。但是我们不应该首先写出程序,然后去证明它的正确性,因为要求证明只会增加苦逼程序员的负担。相反,程序员应该让正确性证明和程序相互验证,发展。论据三本质上是从以下的观察得来的。如果一个人问自己一个令人信服的证据应该具备什么,他了解后,写了一个很好的满足了证明要求的程序,然后这些关于正确性的担心变成一种有效的启发式的指导。当我们把自己限制在智能可控程序时,按照定义,只有这种方法是可行,但这种方法也提供许多有效的方法,让我们从中挑选一个满意的。

设计一个程序需要多少人力根据程序的长度判断,论据四与此相关。曾经有人指出存在一种自然法则告诉我们耗费人力是程序长度的平方。但是谢天谢地,还没有人能够证明这种法则。这是因为它需要是假的。我们都知道能够解决很多问题的推理论证工具称之为抽象,抽象能力的有效开发可以被认为一个有能力的程序员至关重要的敏捷之一。关于这一点,值得指出抽象的意图并不是为了模糊本身,而是去创造新的准确语义水平。当然,我曾经尝试去找到能够阻止我们抽象机制起作用的基础原因。但不管我多么努力,我都找不到任何一个原因。最后,我倾向于假设(直到现在未通过经验证明)我恰当的抽象化能力,也就是人力需要想象或者理解一个程序的耗费不会根据程序长度按照超过正比例的速度增长。但是这些调查的一个衍生品更有实际意义,实际上,它是我论据四的基础。衍生品是许多在整个编程过程中扮演重要角色的抽象模式的识别。你了解这些抽象模式足够多,你就可以就每个模式作报告。这些抽象模式的熟悉和了解让我幡然醒悟,例如从BNF到方向句法编译,可以用几分钟代替几年的花费。 因此,我把我们最近对重要抽象模式的理解作为论据四。

现在说到论据五,它和我们建立在我们思考习惯上的工具的影响有关。我观察到一种十有八九来源于文艺复兴的文化传统,为了忽略这种影响,需要把人心视为肉体最高自主的主人。 但我一开始分析我和同类的思考习惯时,我得到一个完全不同的结论,不管我喜欢与否,即我们使用的工具和我们用来表达或者记录我们想法的语言或记号,是决定我们能够想到什么的主要因素。对编程影响程序员的思考习惯的分析和脑力是我们几乎不曾使用的资源的认识,它们给出了从多方面给出不同编程语言优缺点的尺度。一个有能力的程序员能够意识到他自己脑容量的严格尺寸,因此,他谦逊的完成编程任务,牵涉到其他事情时,他避免小聪明像躲避瘟疫一样。说到一种著名的会话式程序设计技术,我从不同渠道被告知说如果一个计算社区一旦装备终端,一种特殊的现象就会发生,这种现象甚至有了一个被广泛接受的名称——打趣的人。它有一到两种不同的形式,一个程序员在别人桌面放了一个调侃的程序,他要么骄傲的展示它的用途并问别人你能用更少的字符写完吗(好像有任何概念的相关性一样),要么就问说猜猜这是用来干嘛的。通过这个观察,我们必须总结说这门语言是一种宣扬奇技淫巧的工具,同时这会是它的一些诉求的解释,例如说那些喜欢展示他们有多聪明的人,对不起,但是我必须把它视作关于编程语言最令人恶心的地方。我们必须从过去学到的另外一课是所谓功能强大,丰富的编程语言的发展是一种错误,就像这些奇怪庞然大物,某人特有的气质的聚集,都是心灵上,肉体上不可控的。我从系统的谦逊的编程语言上看到很美好的未来。 当我说谦逊时,我的意思是,例如,不仅是ALGOL60的for分支语句,还有FORTRAN的DO循环语句发现因为变得过于怪异而被淘汰。我曾经和一些有经验的志愿者做过一点编程实验,但有些不期望发生和预料不到的事情发生了。我的志愿者没有一个找到明显而漂亮的解决方法。通过更为细致的观察,我们找到相同的源头:他们对与重复的概念与用于加速的联合控制变量的联系过于紧密,以至于他们被蒙蔽了完全看不到明显的方法。他们的方法低效,晦涩难懂,并且耗费了大量时间。这是一段对我来说具有启示作用,和令人震惊的经历。最后,从某个方面上来讲,如果一个人希望明天的编程语言和现在的大为不同,很大程度的优于现在的,他们应该邀请我们在我们写下的所有需要用来应付概念上我们如今设计的抽象结构中思考。关于我们未来工具的优越性,也就是我们第五个论据的基础,就讲到这里。

作为旁观者,我希望提醒一下那些以现有工具不足而觉得编程任务困难的人。编程依旧会十分困难因为一旦我们从详尽的笨重中解放出来,我们将会发现自己得以面对解决远在我们编程能力以外的问题。

你可以不同意我的第六个论据,因为很难收据支持的实验证据,但不能阻止我相信它的正确性。直到现在,我还没有提到分层这个词,但我认为把它作为一个所有收录着一个精细分解解决方案的系统的核心概念是合理的。我甚至可以走更远一步写一篇关于信仰的文章,即我们能够以令人满意的方式解决的唯一问题是那些最后接受精细分解解决方案的问题。乍看之下,这种人类局限的观点是一种令人抑郁的关于我们处境的观点,但我恰恰相反,不这么觉得。学会和我们的局限共存的方法就是了解我们的局限。等到我们足够谦逊去尝试分解方案的死后,因为其他形式的努力已经超过我们智力的掌控,我们将要尽最大的努力去避免所有这些内部损害我们以有用的方式分解系统的能力的交流。我不得不希望这不停的引领我们发现一个容易解决的问题最终也是可以分解的。任何一个看到了大多数所谓的“代码生成”的编译状态的麻烦都可追溯到指令码的有趣特性的人,都会知道一个我在脑海中想到的事情简单示例。适用性更好的分解良好的解决方案是我第六个也是最后一个论据用于支持技术上可行的可能会在这十年发生的革命。

原则上,我把这些论据留给你,让你决定我的考察占多少分量,因为我很清楚我没有办法强迫任何人跟随我的信仰。每次重要的变革都会招致剧烈反对,每个人都可以问自己希望保守力量抵消多少发展。我不指望主要的大财团,甚至计算机领域的集团,我宁愿希望教育机构提供培训,希望那些保守团体的计算机用户认为他们古老的程序很重要以至于不值得重写或者优化。关于这一点,很多大学校园的中心电脑设备的选择视一些现成但昂贵且不理会千千万万愿意自己编程的小用户的问题的程序的需求而定,学校将为他们的选择埋单,这是相当可悲的。这种事情太常发生,例如,高能物理似乎曾经用他们剩下的实验设备勒索科学社区。当然,最容易的解决方法,是对技术可行性的干脆的拒绝,但我担心你需要足够支撑这种方法的论据。唉,现在普遍程序员的脑力水平可以阻止变革发生是得不到任何保证的,因为其他人的编程变得更为有效,程序员很容易在社会的版图中被边缘化。

还有很多政治方面的障碍。即便我们知道怎么去培养未来的专业的程序员,我们不能确定社会允许我们这样做。传授方法论(而不是散布知识)的第一影响是增强了现有的能者的能力,因此拉大了智商上的差异。在一个教育系统是用来建立平均文化的社会,在一个精英不允许出现在顶层的社会,培养有能力的程序员在政治上是不对味的。

让我总结一下。计算机已经伴随我们走过一个世纪的四分之一了。它们以工具的身份对我们社会产生了深远的影响,但是和在人类历史上史无前例的以智力挑战的形式产生深远的影响相比,它们只能以波浪的形式影响我们文化的表面。似乎拥有决定在某种程度上将物体视作一个不可分割整体的权利的分层系统,被视作一个级别更低,细节更多的混合物,最后,当我们将注意力从一级转向更低一级时,时空的天然粒面会以合适的数量级减少。 我们知道墙以砖为单位,砖以结晶体为单位,结晶体以分子为单位,等等。在分层系统中,许多级别可以有意义的区分出来,这和最大与最小粒度的比率的对数成正比,因此,除非比率很大,我们不能指望能够分很多层。在计算机编程中,我们基本的编程语句有低于一微秒的时间粒度,但我们的程序却可能花费几小时的计算时间。我不知道任何一种超过10的10次方的比率的技术,以它超凡速度为优点的计算机,似乎是第一个给我们提供需要分层粒度大和实现它的环境的。这样的挑战,即面对编程任务,是独一无二的,因此这样小说一般的经历可以教会我们很多关于自己的知识。它加深了我们对设计和创造程序的理解,它帮助我们更好的完成想法条理化的任务。如果它没有这样做,对我来说,我们根本不值得拥有计算机。

它已经给我们上了几课,在这次演讲中我要强调以下几点。我们应该更好的编程,证明我们用满是对任务带来的巨大困难的感激的方法完成任务,证明我们坚持谦逊和优雅的编程语言,证明我们尊重人类内心固有的限制和以谦卑的程序员的身份完成任务。

参考:原文地址