摘录与 《黑客与画家》

第一章节:为什么书呆子不受欢迎

首先这里“书呆子”指的“高智商”的人。

解开这个谜的关键是把问题换一种提法。为什么聪明的小孩没有让自己变得受欢迎?如果他们真的很聪明,为什么找不到受欢迎的诀窍呢?他们在标准化测试中表现得这么好,为什么就不能在这方面也大获成功呢?

有一种观点认为,其他小孩妒忌聪明学生,所以聪明的学生不可能受到欢迎。我倒希望这种解释是对的。回想起来,要是初中里真的有人妒忌我,那么他们一定费了很大力气才把这种妒忌隐藏得无法发现。而且,在任何情况下,如果聪明真的令他人妒忌,这反而会招来女生。因为女生喜欢被其他男生妒忌的男生。

在我就读过的学校,聪明根本就是无足轻重的一样东西。同学们既不看重它,也不唾弃它。如果别的事情都相同,那么大家还是愿意自己变得聪明一点,因为这总比做个笨人好。但是总的来说,智力在大家心里的分量远远不如相貌、魅力和运动能力的分量重。

书呆子不受欢迎的真正原因,是他们脑子里想着别的事情。他们的注意力都放在读书或者观察世界上面,而不是放在穿衣打扮、开晚会上面。他们就像头顶一杯水来踢足球,一边踢球,一边拼命保持不让水洒出来。其他人都在一门心思玩足球,遇到这样的对手,自然能够毫不费力地击败,并且心里还奇怪,对方怎么如此无能。

虽然“书呆子”饱尝不受欢迎之苦,但是为了解除痛苦而让他们放弃“聪明”,我想大多数人是不会愿意的。对他们来说,平庸的智力是不可忍受的。不过,要是换了别的孩子,情况就不一样了,大多数人会接受这笔交易。对于很多人来说,这反而是更上一层楼的机会。即使是那些智力排名在前20%的学生(我在这里假设智力可以测量,那时的人们似乎都相信这一点),谁不愿意用30分的成绩换来别人的友爱和钦佩?

就算书呆子心里想着变得与其他小孩一样受欢迎,做起来却是难上加难。因为那些受欢迎的小孩从小就在琢磨如何受欢迎,打心底里追求这个。但是,书呆子从小琢磨的却是如何更聪明,心底里也是这样追求的。这都是受父母的影响,书呆子被教导追求正确答案,而受欢迎的小孩被教导讨人喜欢

在校园环境下,书呆子为什么会被歧视?

一部分原因是,青少年在心理上还没有摆脱儿童状态,许多人都会残忍地对待他人;另一方面,一些追求受欢迎的孩子往往会”结盟”,书呆子就是他们一个共同的敌人(这就好比一个政客,他想让选民忘记糟糕的国内局势,方法就是为国家找出一个敌人,哪怕敌人并不真的存在,他也可以创造一个出来),再进一步,由于书呆子是不受欢迎的,处在学校的底层,所以全校学生都把书呆子当作一个可供欺负的安全目标。

成年人世界如何?

因为那是成年人的世界,他们都成熟了,不会把书呆子挑出来欺负。更重要的是,真实世界的关键并非在于它是由成年人组成的,而在于它的庞大规模使得你做的每件事都能产生真正意义上的效果。

学校的作用

看管监狱的人主要关心的是犯人都待在自己应该待的位置。然后,让犯人有东西吃,尽可能不要发生斗殴和伤害事件,这就可以了;

校方最重视的事情,就是让学生待在自己应该待的位置。与此同时,让学生有东西吃,避免公然的暴力行为,接下来才是尝试教给学生一些东西。

公立学校的老师很像监狱的狱卒。表面上,学校的使命是教育儿童。事实上,学校的真正目的是把儿童都关在同一个地方,以便大人们白天可以腾出手来把事情做完

学校和外面的环境

有了围墙,成年人与学生并不能相互理解,已然是两个不同的世界,一个扭曲的世界,一个真实的世界。
生活在这个扭曲的世界,不仅仅对书呆子,对所有孩子来说,都是充满压力的。就像任何一场战争,胜利方也是要付出代价的。

校园生活的问题

校园生活的两大恐怖之处——残忍和无聊

美国公立学校的平庸并不仅仅是让学生度过了不快乐的六年,还带来了严重后果。这种平庸直接导致学生的叛逆心理,使他们远离那些原本应该要学习的东西。

校园生活的真正问题是空虚。除非成年人意识到这一点,否则无法解决这个问题。

作者意见

对于书呆子来说,意识到学校并非全部的人生,也是很重要的事情。学校是一个很奇怪的、人为设计出来的体系,一半像是无菌室,一半像是野蛮洪荒之地。它就像人生一样,里面无所不包,但又不是事物的真实样子。它只是一个暂时的过程,只要你向前看,你就能超越它,哪怕现在你还是身处其中。

如果你觉得人生糟透了,那不是因为体内激素分泌失调(你父母相信这种说法),也不是因为人生真的糟透了(你本人相信这种说法)。那是因为你对成年人不再具有经济价值(与工业社会以前的时期相比),所以他们把你扔在学校里,一关就是好几年,根本没有真正的事情可做。任何这种类型的组织都是可怕的生存环境。你根本不需要寻找其他的原因就能解释为什么青少年是不快乐的。

我在这篇文章中发表了一些刺耳的意见,但是我对未来是乐观的。我们认定无法解决的难题,事实上完全可以解决。青少年并不是洪水猛兽,也并非天生就不快乐。这一点对于青少年和成年人,应该都是令人鼓舞的消息。

第二章节:黑客与画家

黑客与画家

黑客与画家的共同之处,在于他们都是创作者。

计算机科学就像一个大杂烩,由于某些历史意外,很多不相干的领域被强行拼装在一起。这个学科的一端是纯粹的数学家,中间部分是计算机博物学家,另一端则是黑客。

对于黑客,只想写出有趣的软件,对于他们来说,计算机只是一种表达的媒介,就像建筑师手里的混凝土,或者画家手里的颜料。

黑客搞懂“计算理论”(theory of computation)的必要性,与画家搞懂颜料化学成分的必要性差不多大。

优美的事物

创造优美事物的方式往往不是从头做起,而是在现有成果的基础上做一些小小的调整,或者将已有的观点用比较新的方式组合起来。这种类型的工作很难用研究性的论文表达。

唯一有效的外部考核就是时间。经过岁月的洗礼,优美的东西生存发展的机会更大,丑陋的东西往往会被淘汰

如何赚大钱

如果大学和实验室不允许黑客做他们想做的事情,那么适合黑客的地方可能就是企业。不幸的是,大多数企业也不允许黑客做他们想做的事情。大学和实验室强迫黑客成为科学家,企业强迫黑客成为工程师。

如果某一天你想要去赚大钱,那么记住上面这一点,因为这是创业公司能够成功的原因之一。

大公司只要做到不太烂,就能赢。

真正竞争软件设计的战场是新兴领域的市场,这里还没有人建立过防御工事。只要你能做出大胆的设计,由一个人或一批人同时负责设计和实现产品,你就能在这里战胜大公司。

开发优秀软件的方法之一就是自己创业。

创业的困难

一个是自己开公司的话,必须处理许许多多与开发软件完全无关的事情;

另一个问题是赚钱的软件往往不是好玩的软件,两者的重叠度不高。

黑客如何才能做自己喜欢的事情?

我认为这个问题的解决方法是一个几乎所有创作者都知道的方法:找一份养家糊口的“白天工作”(day job)。这个词是从音乐家身上来的,他们晚上表演音乐,所以白天可以找一份其他工作。更一般地说,“白天工作”的意思是,你有一份为了赚钱的工作,还有一份为了爱好的工作。

开源软件的这种工作模式可能就是正确的模式,因为它已经被其他领域的创作者都验证过了。

如何学习编程

“画家学习绘画的方法主要是动手去画,黑客学习编程的方法也理应如此 “

画家的作品都会保留下来,你观察这些作品,就能看出他们是怎么一步步通过实践学习绘画的。

也许对于黑客来说,采取像画家这样的做法很有好处:应该定期地从头开始,而不要长年累月地在一个项目上不断工作,并且试图把所有的最新想法都以修订版的形式包括进去。

黑客的出发点是原创,最终得到一个优美的结果;而科学家的出发点是别人优美的结果,最终得到原创性。

创作者另一个学习的途径是通过范例。

对画家来说,博物馆就是美术技巧的图书馆。几百年来,临摹大师的作品一直是传统美术教育的一部分,因为临摹迫使你仔细观察一幅画是如何完成的。

同样地,黑客可以通过观看优秀的程序学会编程,不是看它们的执行结果,而是看它们的源代码。开源运动最鲜为人知的优点之一,就是使得学习编程变得更容易了

还有一个可以借鉴绘画的地方:一幅画是逐步完成的。通常一开始是一张草图,然后再逐步填入细节。但是,它又不单纯是一个填入细节的过程。有时,原先的构想看来是错的,你就必须动手修改。无数古代油画放在X光下检视,就能看出修改痕迹,四肢的位置被移动过,或者脸部的表情经过了调整。

绘画的这个创作过程就值得学习。我认为黑客也应该这样工作。你不能盼望先有一个完美的规格设计,然后再动手编程,这样想是不现实的。如果你预先承认规格设计是不完美的,在编程的时候,就可以根据需要当场修改规格,最终会有一个更好的结果。(大公司的内部结构,使得它们很难这样做。这是又一个创业公司占优之处。)

黑客是一个创作者

黑客就像画家,工作起来是有心理周期的。有时候,你有了一个令人兴奋的新项目,你会愿意为它一天工作16个小时。等过了这一阵,你又会觉得百无聊赖,对所有事情都提不起兴趣

对于编程,这实际上意味着你可以把bug留到以后解决。

对于产品

大多数创作者都是为人类用户而创作

就像绘画作品一样,大多数软件是为人类用户准备的。所以,黑客必须像画家一样,时刻考虑到用户的人性需要,这样才能做出伟大的产品。你必须能够站在用户的角度思考问题,也就是说你必须学会“换位思考”。

普通黑客与优秀黑客的所有区别之中,会不会“换位思考”可能是最重要的单个因素。有些黑客很聪明,但是完全以自我为中心,根本不会设身处地为用户考虑。这样的人很难设计出优秀软件,因为他们不从用户的角度看待问题

对于源代码

程序写出来是给人看的,附带能在机器上运行。

换位思考”不仅是为了你的用户,也是为了你的读者。这对你是有利的,因为你也会读自己写的东西。许多黑客六个月后再读自己的程序,却发现根本看不懂它是怎么运行的。

我们的时代

我们能够有把握说的就是,现在正是编程的黄金年代。大多数领域的伟大作品都诞生于很早以前。1430年1500年之间的绘画杰作,至今仍然是不可超越的。

我们看到这种模式一再反复出现。一种新的媒介刚刚诞生的时候,人们热情高涨、兴奋不已,短短几代人就探索清楚了这种媒介的大部分可能性,把它的能量发挥到极致。编程目前好像就处在这个阶段。

达·芬奇的年代,绘画并不是一件很酷的事情,达·芬奇用自己的工作推动绘画成为一种伟大的表达方式。同样,编程到底能够有多酷,取决于我们能够用这种新媒介做出怎样的工作。

个人感悟:黑客是创作者,而不是理论研究者(科学家),也不是大公司中的技工。如果想要赚大钱,在新兴领域进行创作。一个优秀的产品需要等待时间来考证。

第三章节:不能说的话

时尚的本质

所谓“时尚”,本质上就是自己看不见自己的样子。好比我们在地球上,却感觉不到地球在动。
流行一时的不仅有衣服,还有道德观念。如果别人都穿流行的衣服,而你不穿,你就会遭到嘲讽;如果别人都遵守流行的道德观念,而你不遵守,结果则要严重得多。
书呆子就是那样惹上麻烦的。他们穿着不流行的衣服,讲着不合适的话。他们觉得自己说出了正确的观点,实际上却惹来了麻烦。习俗的力量不足以束缚他们。

时代的观念

历史的常态似乎就是,任何一个年代的人们,都会对一些荒谬的东西深信不疑。他们的信念还很坚定,只要有人稍微表示一点怀疑,就会惹来大麻烦。(这一点看,我们这个时代并没有什么不同)

你是一个随大流的人吗?

有时候,别人会对你说:“要根据社会需要,改造自己的思想(well-adjusted)。”这种说法隐含的意思似乎是,如果你不认同社会,那么肯定是你自己的问题。你同意这种说法吗?事实上,它不仅不对,而且会让历史倒退。如果你真的相信了它,凡是不认同社会之处,你连想都不敢想,马上就放弃自己的观点,那才会真正出问题。

哪些话是不能说的?

到底什么话是我们不能说的?为了找到答案,首先,我们可以看看,周围的人因为说了什么而陷入麻烦。

1.真话

第一个条件是,这些话不能说出口;第二个条件是,它们是正确的,或者看起来很可能正确,值得进一步讨论。如果达不到第二个条件,大部分情况下你都不会有麻烦。你说2+2等于5,或者匹兹堡的市民身高三米,都不会有事的。这些明显错误的言论也许会被当成笑话,或者更糟一点,被当成你发疯的证据,但是肯定不会惹恼任何人。触怒他人的言论是那些可能会有人相信的言论。我猜想,最令人暴跳如雷的言论,就是被认为说出了真相的言论。

方法:为了找出那些“不能说的话”,让我们问自己,它们会不会是真的?OK,当你发现某些言论很可疑时,你可以这样想,那些话听上去真是大逆不道(或者其他类似的形容词),但是有没有可能是真的?这就是找出“不能说的话”的第一种方法:判断言论的真伪。

2.异端邪说

有些想法,纯粹因为非常特别,而不能说出口。比如,某个话题极其富有争议,不管是对是错,没有人敢在公开场合谈论它。我们怎样才能发现这种情况呢?

方法:我们把这种不一定正确、但是极富争议的言论称为“异端邪说”。关注“异端邪说”,是找出“不能说的话”的第二种方法。比如,有一个标签叫做“性别歧视”,你问自己哪些想法属于“性别歧视”。然后,把头脑中跳出来的那些想法按照先后顺序列出来,再逐个追问,它们真的属于“性别歧视”吗?

3.时空差异

(回顾历史,可以发现古人有许多”可笑“的观念)

如果我们可以通晓未来,那么找出当代的那些表面上正确、实际上可笑的想法是一件很容易的事。

我们可以自以为是地相信,当代人比古人更聪明、更高尚。但是,了解的历史越多,就越明白事实并非如此。古人与我们是一样的人,他们既不是更勇敢,也不是更野蛮,而是像我们一样通情达理的普通人。不管他们产生怎样的想法,都是正常人产生的想法。

方法:回顾过去。我们可以去找那些过去被认为理所当然,如今却被认为不可思议的事情,这是用来找出我们自己正在犯下的错误的第三种方法。

4.道貌岸然

大多数成年人故意让孩子对世界有一个错误的认识。最鲜明的例子之一就是圣诞老人。我们觉得,小孩子相信圣诞老人,真是太可爱了。我本人其实也是这样想。但是,扪心自问,我们向孩子灌输圣诞老人的神话,到底是为了孩子,还是为了我们自己?

方法:寻找那些一本正经的卫道者,看看他们到底在捍卫着什么。

5.机制

一般来说,流行的时尚产生于某个有影响力的人物,他突发奇想,接着其他人纷纷模仿。但是,流行的道德观念不是这样,它们往往不是偶然产生的,而是被刻意创造出来的。如果有些观点我们不能说出口,原因很可能是某些团体不允许我们说。

方法:我还想到了第五种方法,可以找出“不能说的话”,那就是去观察禁忌是如何产生的。某种道德观念到底是怎么出现的,又是怎么被其他人接受的?如果我们能够理解它的产生机制,可能就可以应用于我们自己的时代。

如果你要寻找“不能说的话”,可以观察流行的产生方式,试着预测它会禁止哪些话。哪一个团体势力强大,却又精神高度紧张?这种团体喜欢压制什么样的思想观点?近来有没有什么社会斗争,失败的一方是哪一方,受到他们牵连的是什么样的思想观点?如果一个先锋人物想要挣脱当前的流行(比如上一代人的观点)脱颖而出,他会支持什么样的思想观点?随大流的人对什么样的思想观点抱有恐惧心?

为什么要这样做?(这样做有哪些好处)

首先,我这样做与小孩子翻石头是出于同样的原因:纯粹的好奇心。我对任何被禁止的东西都有特别强烈的好奇心。我要亲眼看一下,然后自己做决定。
其次,我这样做是因为我不喜欢犯错。如果像其他时代一样,那些我们自以为正确的事情将来会被证明是荒谬可笑的,我希望自己能够知道是哪些事情,这样可以使我不会上当。
再次,我这样做,是因为这是很好的脑力训练。想要做出优秀作品,你需要一个什么问题都能思考的大脑。尤其是那些似乎不应该思考的问题,你的大脑也要养成思考它们的习惯。

然后应该这么做?

1.守口如瓶

自由思考比畅所欲言更重要。如果你感到一定要跟那些人辩个明白,绝不咽下这口气,一定要把话说清楚,结果很可能是从此你再也无法自由理性地思考了。

“守口如瓶”的真正缺点在于,你从此无法享受讨论带来的好处了。讨论一个观点会产生更多的观点,不讨论就什么观点也没有。所以,如果可能的话,你最好找一些信得过的知己,只与他们畅所欲言、无所不谈。这样不仅可以获得新观点,还可以用来选择朋友。能够一起谈论“异端邪说”并且不会因此气急败坏的人,就是你最应该认识的朋友

2.笑脸相迎

⑴假设狂热分子试图引诱你说出来真心话,但是你可以不回答。

你不妨以不变应万变:“我既不反对也不赞成。”,更好的回答是“我还没想好”。

⑵假设社会上充斥着反对“黄色分子”的人,他们只要看谁不顺眼,就大肆攻击。你看不下去,准备出手反击。

一种方法就是逐步把辩论提升到一个抽象的层次。

另一种反击的方法就是使用隐喻(metaphor)。

所有反击方法之中,最好的一种可能就是幽默。

3.永远质疑

如果自己就是潮水的一部分,怎么能看见潮流的方向呢?你只能永远保持质疑。问自己,什么话是我不能说的?为什么?

第四章节:良好的坏习惯

”(hack)这个词也有两个意思,既可以用作赞美,也可以用作羞辱。如果你解决问题的方式非常丑陋笨拙,这叫做你很“”。如果你解决问题的方式非常聪明高超,将整个系统操纵在股掌之间,这也叫做你很“”。

”的这两个意思也是相关的。丑陋的做法与聪明的做法存在一个共同点,那就是都不符合常规。从“丑陋”到“聪明”,它们之间存在一种连续性渐变。

公民自由并不仅仅是社会制度的装饰品,或者一种很古老的传统。公民自由使得国家富强。如果将人均国民生产总值与公民自由的关系画成图,你会发现它们是很清楚的正相关关系。公民自由真的是国家富强的原因,而不是结果吗?我认为是的。在我看来,一个人们拥有言论自由和行动自由的社会,往往最有可能采纳最优方案,而不是采纳最有权势的人提出的方案。专制国家会变成腐败国家,腐败国家会变成贫穷国家,贫穷国家会变成弱小国家。经济学里有一条拉弗曲线(Laffer curve),认为随着税率的上升,税收收入会先增加后减少。我认为政府的力量也是如此,随着对公民自由的限制不断上升,政府的力量会先增加后减小。至少现在看来,我们的政府很可能蠢到会真的把这个实验付诸实施,亲自验证一下这个观点。但是,税率提高了还能再降下来,而一旦这个实验铸成大错,就悔之晚矣,因为极权主义制度只要形成了,就很难废除。

这就是为什么黑客感到担忧。政府侵犯公民自由,表面上看,并不会让程序员的代码质量下降。它只是逐渐地导致一个错误观点占上风的世界。黑客对于公民自由是非常敏感的,因为这对他们至关重要。他们远远地就能感到极权主义的威胁,好比动物能够感知即将来临的暴风雨。

有一种东西,叫做美国精神(American-ness),生活在国外的人最能体会到这一点。如果你想知道哪些事情可以滋养或者削弱这种精神,不妨去问问黑客,他们是最敏感的焦点人群,因为在他们身上,比我知道的其他人群,更能体现出这种精神。真的,他们可能比那些政府里掌管美国的人更懂得什么叫做美国精神。那些政客开口必谈爱国主义,总是让我想起黎塞留(Richelieu)或者马萨林(Mazarin),而不是杰弗逊或者华盛顿。

如果读美国开国元勋的自述,你会发现他们听起来很像黑客。“反抗政府的精神,”杰弗逊写道,“在某些场合是如此珍贵,我希望它永远保持活跃。”

第五章节:另一条路

互联网软件

互联网软件运行在服务器上,用户界面就是网页。对于普通用户来说,使用这种新型软件将更容易、更便宜、更机动、更可靠,通常也比桌面软件更强大。

使用互联网软件,除了软件本身,大多数用户不需要知道别的事情。所有那些乱七八糟、经常变动的东西,都放在服务器端,由精通此道的专业人员维护。

互联网软件的优点

对用户

  1. 方便,使用那些纯粹的互联网软件,你只需要一个能够上网的浏览器即可。有了互联网软件,你的数据和软件本身都不保存在终端设备上,可以从任何电脑上获取你的数据。
  2. 不用安装就能使用。不需要用户手动升级
  3. 互联网应用程序能够同时被多人使用,所以非常适合团队协作性的工作。
  4. 如果使用互联网软件,数据会更安全。数据丢失的责任在于公司。
  5. 互联网软件不太容易感染病毒。

对开发者

  1. 对于开发者来说,互联网软件与桌面软件最显著的区别就是,前者不是一个单独的代码块。它是许多不同种类程序的集合,而不是一个单独的巨大的二进制文件。
  2. 光有软件还不够,我们还花了许多时间琢磨服务器应该如何配置。
  3. 由于互联网应用程序由多种软件而不是单独一个二进制文件构成,所以可以使用多种编程语言开发。
  4. 软件的发布过程可以分解为一系列的渐进式修改,而不是猛地推出一个大幅变动的版本。
  5. 把发现bug的任务交给用户去完成,使得软件可以快速迭代更新。
  6. 开发互联网软件需要的程序员比较少。开发软件需要的程序员人数减少,不仅意味着省下更多的钱,软件开发的效率将指数式增长。
  7. 能够即时发布软件,对开发者是一个巨大的激励。只要想到好的构思,我们就立刻着手实现。
  8. 互联网软件不仅把开发者与他的代码更紧密地联系在了一起,而且把开发者与他的用户也更紧密联系在了一起。因为你能得到用户数据,所以就不用依赖基准测试了。

目标客户
谁是互联网软件的目标客户?Viaweb一开始就把个人和小企业当作目标客户。我认为这是互联网软件的通行规则。这些客户决策比较灵活,又需要低成本的新技术,所以他们更愿意尝试新事物。

巨无霸公司VS创业公司在于新领域

微软

除了微软自己,没有人能让微软遭受严重挫折。随着互联网软件的崛起,微软不仅要面对新的技术问题,还要面对它自己毫无根据、一厢情愿的旧思维。微软需要把它现有的商业模式拆除,建设一个新模式,我看不到它有正视这个问题的任何迹象。它一心一意地坚持桌面软件模式,固然把它带到现在的地位,但是现在开始将成为它继续前进的障碍。IBM曾经有过同样的处境,它没有正确应对。在很晚的阶段,它才进入微机市场,并且三心二意没有倾注全力,因为大型机是IBM的主要利润来源,发展微机就等于扼杀这头金牛,所以它感到很纠结。微软也同样感到纠结,因为它想保住桌面软件。看来金牛也会成为沉重负担。

创业公司

典型的创业公司行动快速,看上去不是那么正式,只有很少几个人,资金也有限。

开发互联网软件的创业公司会把与创业有关的每一件事做到极致。只用更少的人、更少的钱,就可以把软件写出来,并且开始运作。你必须打破常规、快速行动,循规蹈矩不可能成功。

鼓励黑客创业

只有懂得设计的黑客,才能设计软件,不能交给对软件一知半解的设计师。如果你不打算自己动手设计和开发,那就不要创业。

管理企业其实很简单,只要记住两点就可以了:做出用户喜欢的产品,保证开支小于收入。只要做到这两点,你就会超过大多数创业公司。随着事业的发展,你自己就能琢磨出来其他的诀窍。

第六章节:如何创造财富

如果你想致富,最好的办法就是自己创业,或者加入创业公司。

创业公司往往与技术有关,所以“高技术创业公司”这个短语几乎就是同义重复。

一个命题

你不再是低强度地工作四十年,而是以极限强度工作四年。在高技术领域,这种压缩的回报尤其丰厚,工作效率越高,额外报酬就越高。

运气的成分

比尔·盖茨很聪明,有决断力,工作也很勤奋,但是单单这样还不足以让你成为他。你还需要非同一般的好运气。

手艺人

目前还存在的最大的手工艺人群体就是程序员。程序员坐在电脑前就能创造财富。

可测量性和可放大性

要致富,你需要两样东西:可测量性和可放大性。你的职位产生的业绩,应该是可测量的,否则你做得再多,也不会得到更多的报酬。此外,你还必须有可放大性,也就是说你做出的决定能够产生巨大的效应。

小团体=可测量性

高科技=可放大性

创业潜规则

一条就是很多事情由不得你,真正创业以后,你的竞争对手决定了你到底要有多辛苦,而他们做出的决定都是一样的:你能吃多少苦,我们就能吃多少苦。

创业的付出与回报虽然总体上是成比例的,但是在个体上是不成比例的。

创业公司如同蚊子,往往只有两种结局,要么赢得一切,要么彻底消失。

保险的做法就是在早期卖掉自己的创业公司,放弃未来发展壮大(但风险也随之增大)的机会,只求数量较少但是更有把握的回报。

创业

创造财富不是致富的唯一方法。但是要鼓励大家去创业。只要懂得藏富于民,国家就会变得强大。

第七章节:关注贫富分化

为什么人们会有仇富心理?

第一,我们从小被误导的对财富的看法;第二,历史上积累财富的方式大多名声不好;第三,担心收入差距拉大将对社会产生不利影响。

就我所知,第一点是错的,第二点已经过时了,第三点通不过现实的检验。

财富是被创造出来的

财富与金钱是两个概念。金钱只是用来交易财富的一种手段,财富才是有价值的东西,我们购买的商品和服务都属于财富。
孩子没有能力创造财富,他们享有的一切都来自别人无偿的给予。既然得到财富不要求对应的付出,那么它当然应该平均分配。大多数家庭都是这样,如果兄弟姐妹中有人多得到了一份,其他孩子就会喊:“不公平!”

进入社会,每个人创造财富的能里不同,一个人代表的价值也就不同了。

公平与平等

当我们讨论“收入分配不公平”时,我们还要问问收入从何而来,收入背后的财富到底是谁生产出来的。如果收入完全根据个人创造的财富数量而分配,那么结果可能是不平均的,但是很难说是不公平的。

由于每个人创造财富的能力和欲望强烈程度都不一样,所以每个人创造财富的数量很不平等。

为什么在过去富人就是不道德的呢?

在大部分的人类历史中,积累财富最常见的方法其实是偷窃。游牧社会是偷别人的牲口,农业社会是征税(和平时期)和直接掠夺(战争时期)。并且每个人创造财富的能力都很平均,那些勤勤恳恳的个人基本积累不多财富。

为什么在现在积累财富又是正当了的呢?

工业革命时代之后,创造财富真正取代掠夺和贪污成为致富的最佳方式。通过技术的方式,可以更快速的积累财富。

技术的发展是否加剧了贫富分化?

首先,技术肯定加剧了有技术者与无技术者之间的生产效率差异,毕竟这就是技术进步的目的。一个勤劳的农民使用拖拉机比使用马可以多耕六倍的田。但是,前提条件是他必须掌握如何使用新技术。

技术应该会引起收入差距的扩大,但是似乎能缩小其他差距。一百年前,富人过着与普通人截然不同的生活。现在,由于技术的发展,富人的生活与普通人的差距缩小了。

富人日常做的事情也和普通人差不多。无所事事的闲适生活早就成为罕见情况了。

社会需要有富人(真正创造价值的那一波人)

一个社会需要有富人,这主要不是因为你需要富人的支出创造就业机会,而是因为他们在致富过程做出的事情。我在这里谈的不是财富从富人流向穷人的那种扩散效应(trickle-down effect),也不是说如果你让亨利·福特致富,他就会在下一场宴会雇用你当服务员,而是说如果你让他致富,他就会造出一台拖拉机,使你不再需要使用马匹耕田了。

第八章节:防止垃圾邮件的一种方法

发送垃圾邮件的人形形色色。有的是公司,经营着一个所谓的邮件列表,表面上说你可以选择订阅,但是实际上根本无法退订,他们肆无忌惮地向你发送广告;有的是个人,专门劫持邮件服务器,推广色情网站。如果我们的过滤器迫使他们只能把垃圾邮件写成上面那样,应该会使得垃圾邮件业中合法经营的那部分人退出这个行业。因为他们很乐于遵守各州的法律规定,在邮件中附上正式声明,解释为什么自己不是垃圾邮件以及如何才能取消订阅。这一类文字反而使得识别他们变得更容易了。
(我以前曾经认为,那些相信更严格的法律会遏制垃圾邮件的人真是太天真了。我现在认为,更严格的法律或许无法减少我们收到的垃圾邮件的数量,但是肯定有助于减少逃过过滤器拦截的垃圾邮件的数量。)

在垃圾邮件业中,如果发送销售类垃圾邮件受到限制,那么整个行业将不可避免地受到重创。“行业”这个词是很准确的,发送垃圾邮件的人其实都是商人,他们这么做只是因为这招很有效。虽然垃圾邮件的回应率低到不能再低了(不超过百万分之15,相比之下,传统的邮寄商品目录的回应率是百万分之3000),但是发送垃圾邮件的成本实际上为零,所以它还是有效的。但是对于收到垃圾邮件的人来说,成本却很高昂,假定有100万人分别收到一封垃圾邮件,每人花一秒钟删除,累计起来就相当于一个人5个星期的工作量,而发送人连一分钱也不用付出。

不过,虽然接近于零,发送垃圾邮件还是有成本的。所以,只要我们把垃圾邮件的回应率降得很低(不管手段是直接过滤,还是让垃圾邮件被迫掩盖它们的销售意图),商家就会发现,发送垃圾邮件是一件经济上不值得的事情。

另一方面,垃圾邮件使用了那么多推销语言就是为了增加回应率。如果有一天推销语言突然不能用了,对他们就是重大打击。为了说明这一点,让我们把自己想象成一个回应垃圾邮件的人,看看这些人到底是怎么想的(这要比把自己想象成垃圾邮件发送者更让人难受)。回应垃圾邮件的人要么是惊人地轻信,要么是表面上完全否认、但是私底下却有着对性的强烈兴趣。不管哪一种情况,也不管垃圾邮件在正常人看来是多么令人反感或愚蠢万分,总是可以让这些人兴奋不已,因为邮件内容写得实在太诱人了,毕竟如果不是这样,商家也就不发送垃圾邮件了。要是邮件内容改成“请点击下面的链接”,对于收信人来说就没有太大的吸引力了,根本比不上现在的效果。结果就是,如果垃圾邮件不能使用诱人的推销语言,它作为推销工具的价值就会大大降低,使用它的商家数量也会减少。

最终,我们将取得全胜。我开始写垃圾邮件过滤器只是因为不想再让这些东西烦我了。但是,如果我们把过滤器做得足够好,那么垃圾邮件将不再有效,商家最后将不再发送它。

所有对抗垃圾邮件的方法之中(从软件方法到法律方法),我认为单独来看,“贝叶斯过滤”是最有效的工具。但是,我也认为,我们使用的不同方法越多,综合效果就越好,因为任何对发送人构成限制的方法往往都会使得过滤器工作起来更顺利。即使同样是基于内容的过滤器,我也认为,如果有多种不同的软件可以同时使用会比较好。过滤器的差异越大,垃圾邮件想要逃过拦截就越不可能。

第九章节:设计者的品味

品位不是个人偏好,而是共同的认知

把品味说成个人的偏好可以有效地杜绝争论,防止人们争执哪一种品味更好。但是问题是,这种说法是不正确的。只要你自己开始动手设计东西,就能明白这一点。

什么才算是优秀的设计

优秀设计的原则是许多学科的共同原则,一再反复地出现。

  • 好设计是简单的设计。当你被迫把东西做得很简单时,你就被迫直接面对真正的问题。当你不能用表面的装饰交差时,你就不得不做好真正的本质部分。
  • 好设计是永不过时的设计。如果你希望自己的作品对未来的人们有吸引力,方法之一就是让你的作品对上几代人有吸引力。
  • 好设计是解决主要问题的设计。答案可以不断改进,同样,问题本身也可以不断改进。软件的难题通常可以被改成等价的较易解决的形式。
  • 好设计是启发性的设计。在软件业中,这条原则意味着,你应该为用户提供一些基本模块,使得他们可以随心所欲自由组合,就像玩乐高积木那样。
  • 好设计通常是有点趣味性的设计。好的设计并非一定要有趣,但是很难想象完全无趣的设计会是好的设计。
  • 好设计是艰苦的设计。困难的问题需要艰巨的付出才能解决,高难度的数学证明需要结构非常精细的解决方法(它们往往做起来很有趣),工程学也是如此。
  • 好设计是看似容易的设计。在大多数领域,看上去容易的事情,背后都需要大量的练习。
  • 好设计是对称的设计。对称也许只是简洁性的一种表现,但是它十分重要,值得单独列为一点。自然界的对称大量存在,这* 就说明了对称的重要性。
  • 好设计是模仿大自然的设计。模仿大自然也是工程学的有效方法。
  • 好设计是一种再设计。很少有人一次就把事情做对。专家的做法是先完成一个早期原型,然后提出修改计划,最后把早期原型扔掉。
  • 好设计是能够复制的设计。我们对待复制的态度经常是一个否定之否定的过程。刚入门的新手不知不觉地模仿他人,逐渐熟练之后才开始创作原创性作品。最后他会意识到,把事情做对比原创更重要。(先模仿,再创作)
  • 好设计常常是奇特的设计。唯一达到“奇特”的方法,就是追求做出好作品,完成之后再回过头看。
  • 好设计是成批出现的。你个人最多可以对趋势产生一定的影响,但是你不可能决定趋势,实际上是趋势决定了你。(或许有人办得到,但是米兰的达·芬奇显然没有办到。)
  • 好设计常常是大胆的设计。在任何一段历史中,人们都会把某些荒谬的东西当作正确的,并且深信不疑,以至于一旦你出言质疑,就有被排挤或者被暴力伤害的危险。

严格的品位+熟练的技能=优秀的作品

我们自己的这个时代要是不同以往,当然令人欢欣鼓舞。但是就我所知,它并没有任何不同。

单单是无法容忍丑陋的东西还不够,只有对这个领域非常熟悉,你才可能发现哪些地方可以动手改进。你必须锻炼自己。只有在成为某个领域的专家之后,你才会听到心里有一个细微的声音说:“这样解决太糟糕了!一定有更好的选择。”不要忽视这种声音,要培育它们。优秀作品的秘诀就是:非常严格的品味,再加上实现这种品味的能力。

第十章:编程语言解析

所有机器都有一张操作命令清单,让你可以控制它。有时这个清单非常简短。电水壶就只允许两种操作:打开和关闭。CD播放器稍微复杂点,除了打开和关闭以外,还能调节音量、播放、暂停、快进、快退、随机播放等。

计算机和其他机器一样,也有一张操作命令清单。比如,可以命令计算机把两个数相加。这种操作命令的总和就是计算机的机器语言(machine language)。

机器语言

机器语言和汇编语言的共同问题就是,只能让大多数计算机做一些很简单的事情。比如,假定你想让计算机的蜂鸣器响10次,但是不存在一条直接的机器语言命令让电脑重复进行n次操作,所以只能用机器语言写出下面这样的程序:

a  将数字10存入内存地址0如果内存地址0的值为负数,跳到b行蜂鸣器发出声音将内存地址0的值减1跳到a行b
  ……程序的其他部分……

如果只是为了让蜂鸣器响10次就不得不写这么多代码,不难想象写出一个文字处理器或电子表格将是一项多么浩大的工程。

高级语言

事实上大多数程序员就是这样工作的,不同之处就是,程序员的助手不是一个人,而是编译器。所谓“编译器”,本身就是一个程序,作用是将简便方式书写的程序(就像上面这一行命令)转变为硬件可以理解的语言。

这种简便方式书写的程序所使用的语言就叫做高级语言。它让你能够使用更强大的命令开发程序,比如现在你就有了“重复n次操作”的命令,不再仅限于只能做简单的“两个数相加”。

写程序时有了方便的命令,就可以把程序写得更简短。在上面假想的例子中,高级语言写出来的程序的长度只有机器语言的五分之一。所以,要是你犯错了,现在也更容易发现。

高级语言还有一个优点,它使得程序更具有可移植性。不同计算机的机器语言都不是完全相同的。所以,你无法将为某一种机型写的机器语言程序放到另一种机型上运行,只有彻底重写才能实现。但是,如果你的程序是用高级语言写的,你只需要重写编译器就可以了。

编译器不是高级语言唯一的实现方法,另一种方法是使用解释器,它的作用是实时地将代码解释为相应的机器语言,然后一行行运行。相比之下,编译器则是先将整个程序全部翻译成机器语言,然后再运行。

开放源码

编译器处理的高级语言代码又叫做源码。它经过翻译以后产生的机器码就叫做目标码。顾客购买市场上的商业软件时得到的往往只是目标码。(目标码很难读懂,所以相当于被加密了,可以保护公司的商业秘密。)但是,后来出现另一种潮流:开放源码的软件。你可以得到源码,并且可以不受限制地修改它。

这两种方式的真正区别在于,开放源码使你对软件有更大的控制权,如果你想理解开源软件如何运行,只要阅读源码就行了。如果愿意,你甚至可以修改软件、重新编译。

语言战争

FortranLispCobolBasicCPascalSmalltalkC++JavaPerlPython,全都是高级语言。它们只是比较出名的几种而已。现在的高级语言大概有几百种之多。不同机器语言的指令集基本相同,但是高级语言就不一样,它们开发程序的模式差别相当大。

那么,应该使用哪一种语言?嗯,关于这个问题,现在有很多争论。部分原因是,如果你长期使用某种语言,你就会慢慢按照这种语言的思维模式进行思考。所以,后来当你遇到其他任何一种有重大差异的语言,即使那种语言本身并没有任何不对的地方,你也会觉得它极其难用。缺乏经验的程序员对于各种语言优缺点的判断经常被这种心态误导。

抽象性

高级语言比汇编语言更接近人类语言,而某些高级语言又比其他语言更进一步。举例来说,C 语言是一种低层次语言,很接近硬件,几乎堪称可移植的汇编语言,而Lisp语言的层次则是相当高。

如果高层级语言比汇编语言更有利于编程,你也许会认为语言的层次越高越好。一般情况下确实如此,但不是绝对的。编程语言可以变得很抽象,完全脱离硬件,但也有可能走错了方向。比如,我觉得Prolog语言就有这个问题。它的抽象能力强得不可思议,但是只能用来解决2%的问题,其余时间你苦思冥想、运用这些抽象能力写出来的程序实际上就是Pascal语言的程序。

静态类型和动态类型

自由语言派的信徒嘲笑另一方是“B&D”(奴役和戒律,Bondage and Discipline)语言,很无礼地暗示用那些语言编程的人是下等人。我不知道对方如何反击这些喜欢Perl的自由派,也许他们不喜欢给别人起绰号,因此我就无从知道。

由于防止程序员做蠢事有好几种方法,所以上面的争论逐渐分化成几个较小的议题。目前最活跃的议题之一就是静态类型语言与动态类型语言之争。在静态类型语言中,写代码时必须知道每个变量的类型。而在动态类型语言中,随便什么时候,你都可以把变量设为任意类型的值。

静态类型语言的拥护者认为这样可以防止bug,并且帮助编译器生成更快的代码(这两点理由都成立)。动态类型语言的拥护者认为静态类型对程序构成了限制(这点理由也成立)。我本人更喜欢动态类型,痛恨那些限制我的自由的语言。但是,确实有一些很聪明的人看来喜欢用静态类型语言。所以,这个问题依然值得讨论,并没有固定答案。

面向对象编程

面向对象编程的优点在于,如果你需要修改程序,计算另一种图形的面积,比如三角形,你只需要再另外增加一块相应的代码就可以了,甚至可以不修改程序的其他部分。但是,批评者会反驳说,这种方法的缺点是,由于增加代码不用考虑其他部分,结果往往导致写出性能不佳甚至有副作用的代码,就好比造房子不考虑已经完成的部分一样。

关于面向对象编程优劣的争论并不像静态类型与动态类型之争那样壁垒分明,因为编程的时候你只能在静态类型和动态类型之中选一种。但是,面向对象编程只是程度不同的问题。事实上有两种程度的面向对象编程:某些语言允许你以这种风格编程,另一些语言则强迫你一定要这样编程。

我觉得后一类语言不可取。允许你做某事的语言肯定不差于强迫你做某事的语言。所以,至少在这方面我们可以得到明确的结论:你应该使用允许你面向对象编程的语言。至于你最后到底用不用则是另外一个问题了。

编程语言的文艺复兴

现在好像每隔一段日子就能听到一种新出现的语言。乔纳森·埃里克森把这种现象称为“编程语言的文艺复兴”。人们有时还会用另一个说法,即“编程语言的战争”。这并不矛盾,文艺复兴时期就是存在很多战争的

实际上,很多历史学家相信战争是文艺复兴的一个副产品。当时,欧洲活力旺盛可能就是因为它分成许多互相竞争的小国。它们互相毗邻,所以新思想能够从一个国家传播到另一个国家,但是它们又互相独立,使得单个的统治者无法遏制创新的发展。相比之下,中国古代的封建皇朝禁止民间建造大型的远洋船只,阻止了经济的正常发展。

所以,程序员活在这个文艺复兴时代可能是一件好事。如果我们所有人都使用同一种编程语言,反而有可能是坏事。

第十一章:一百年后的编程语言

一百年以后人们使用什么语言开发软件?

我认为,编程语言就像生物物种一样,存在一个进化的脉络,许许多多分支最终都会成为进化的死胡同。这种现象已经发生了。Cobol 语言曾经流行一时,但是现在看来没有任何后续语言继承它的思想。它就像尼安德特人一样,进化之路已经走到了尽头。

我预言Java也会如此。有人写信说:“你怎么能说Java不会成功呢?它已经成功了。”我觉得这要看你的成功标准是什么。如果标准是相关书籍的出版量,或者是相信学会Java就能找到工作的大学生数量,那么Java确实已经成功了。当我说Java不会成功时,我的意思是它和Cobol一样,进化之路已经走到了尽头。

这只是我的猜测,未必正确。这里的重点不是看衰Java,而是提出编程语言存在一个进化的脉络,从而引导读者思考,在整个进化过程中,某一种语言的位置到底在哪里?之所以要问这个问题,不是为了一百年后让后人感叹我们曾经如此英明,而是为了找到进化的主干。它会启发我们去选择那些靠近主干的语言,这样对当前的编程最有利。

编程语言的进化

编程语言的进化与生物学进化还是有区别的,因为不同分支的语言会发生聚合。比如,Fortran分支看来正在与Algol的继承者聚合。理论上,不同的生物物种也可能发生聚合,但是可能性很低,所以大概从来没有真正出现过。

编程语言之所以可能出现聚合,一个原因是它的概率空间比较小,另一个原因是它的突变不是随机的。语言的设计者们总是有意识地借鉴其他语言的设计思想。

对于语言设计者来说,认清编程语言的进化路径特别有用,因为这样就可以照着样子设计语言了。这时,认清进化的主干就不仅有助于识别现存的优秀语言,还可以把它当作设计语言的指南

什么语言在进化主干上

任何一种编程语言都可以分成两大组成部分:基本运算符的集合(扮演公理的角色)以及除运算符以外的其他部分(原则上,这个部分可以用基本运算符表达出来)。

我认为,基本运算符是一种语言能否长期存在的最重要因素。其他因素都不是决定性的。这有点像买房子的时候你应该先考虑地理位置。别的地方将来出问题都有办法弥补,但是地理位置是没法变的。

慎重选择公理还不够,还必须控制它的规模。数学家总是觉得公理越少越好,我觉得他们说到了点子上。

你仔细审视一种语言的内核,考虑哪些部分可以被摒弃,这至少也是一种很有用的训练。在长期的职业生涯中,我发现冗余的代码会导致更多冗余的代码,不仅软件如此,而且像我这样性格懒散的人,我发现在床底下和房间的角落里这个命题也成立,一件垃圾会产生更多的垃圾。

我的判断是,那些内核最小、最干净的编程语言才会存在于进化的主干上。一种语言的内核设计得越小、越干净,它的生命力就越顽强。

硬件的增加的算力会被浪费掉

浪费可以分成好的浪费和坏的浪费。我感兴趣的是好的浪费,即用更多的钱得到更简单的设计。所以,问题就变成了如何才能充分利用新硬件更强大的性能最有利地“浪费”它们?

对速度的追求是人类内心深处根深蒂固的欲望。当你看着计算机这个小玩意,就会不由自主地希望程序运行得越快越好,真的要下一番功夫才能把这种欲望克制住。设计编程语言的时候,我们应该有意识地问自己,什么时候可以放弃一些性能,换来一点点便利性的提高。

很多数据结构存在的原因都与计算机的速度有关。比如,今天的许多语言都同时有字符串和列表。从语义上看,字符串或多或少可以理解成列表的一个子集,其中的每一个元素都是字符。那么,为什么还需要把字符串单列为一种数据类型呢?完全可以不这么做。只是为了提高效率,所以字符串才会存在。但是,这种以加快运行速度为目的、却使得编程语言的语义大大复杂的行为,很不可取。编程语言设置字符串似乎就是一个过早优化的例子。

我们需要什么样的编程语言

一百年后的程序员最需要的编程语言就是可以让你毫不费力地写出程序第一版的编程语言,哪怕它的效率低下得惊人(至少按我们今天的眼光来看是如此)。他们会说,他们想要的就是很容易上手的编程语言。

效率低下的软件并不等于很烂的软件。一种让程序员做无用功的语言才真正称得上很烂。浪费程序员的时间而不是浪费机器的时间才是真正的无效率。随着计算机速度越来越快,这会变得越来越明显

一百年以后还有面向对象语言吗

顺便说一句,我不认为面向对象编程将来会消亡。我觉得,除了某些特定的领域,这种编程方法其实没有为优秀程序员带来很多好处,但是它对大公司有不可抗拒的吸引力。面向对象编程使得你有办法对面条式代码进行可持续性开发。通过不断地打补丁,它让你将软件一步步做大。大公司总是倾向于采用这样的方式开发软件。我预计一百年后也是如此

如果我们现在就能拥有一百年后的编程语言,那就至少能用来写出优秀的伪码。我们会用它开发软件吗?因为一百年后的编程语言需要为某些应用程序生成快速代码,所以很可能它生成的代码能够在我们的硬件上运行,速度也还可以接受。相比一百年后的用户,我们也许不得不对这种语言做更多的优化,但是总的来看,它应该仍然会为我们带来净收益。

现在,我们的两个观点就是:(1)一百年后的编程语言在理论上今天就能设计出来;(2)如果今天真能设计出这样一种语言,很可能现在就适合编程,并且能够产生更好的结果。如果我们把这两个观点联系起来,那就得出了一些有趣的可能性。为什么不现在就动手尝试写出一百年后的编程语言呢?

当你设计语言的时候,心里牢牢记住这个目标是有好处的。学习开车的时候,一个需要记住的原则就是要把车开直,不是通过将车身对齐画在地上的分隔线,而是通过瞄准远处的某个点。即使你的目标只在几米开外,这样做也是正确的。我认为,设计编程语言时,我们也应该这样做。

第十二章:拒绝平庸

主要说创业公司应该选择一个能节省开发效率的语言,作者主要推崇了LispLisp问世不久,用的人还不多,作者决定使用Lisp原因,是因为它极高的开发效率,可以在很短时间内开发出与竞品一样的功能,是他的秘密武器。

技术的变化速度通常是很快的。但是,编程语言不一样,与其说它是技术,还不如说是程序员的思考模式。编程语言是技术和宗教的混合物。所以,一种很普通的编程语言就是很普通的程序员使用的语言,它的变化就像冰山那样缓慢。大概在1960年,Lisp语言引入了垃圾回收机制(Garbage Collection),今天已经被广泛认为是非常好的做法。Lisp的动态类型特点也同样受到越来越多人的认同。闭包是20世纪60年代Lisp语言引入的功能,现在的接受程度还很低。宏也是60年代中期Lisp语言引入的,现在还是一片处女地。

很显然,那些很普通的编程语言正在主导一切。我不建议你挑战这种强大的习惯势力,相反,我建议你向日本合气道选手学习,利用这种势力削弱你的竞争对手,让他们自食其果。

如果你为大公司工作,想要改用Lisp语言可能不是一件容易的事。你很难说服自以为是的老板,让他允许你用Lisp语言开发程序。老板受到报纸的影响,认为某些其他语言将主宰世界(就像20年前Ada语言受到的评价)。但是,如果你为创业公司工作,那里没有这样的老板,那么你就能和我们一样,将他人的Blub困境转变为你的优势。你的竞争对手被牢牢粘在那些很普通的语言上面,永远都追不上你使用的技术。

如果你为创业公司工作,那么这里有一个评估竞争对手的妙招——关注他们的招聘职位。他们网站上的其他内容无非是一些陈腐的照片和夸夸其谈的文字,但是招聘职位却不得不写得很明确,反映出他们到底想干什么,否则就会引来一大批不合适的求职者。

第十二章:书呆子的复仇

当你按照JavaPerlPythonRuby这样的顺序观察这些语言,你会发现一个有趣的结果。至少,如果你是一个Lisp黑客,你就看得出来,排在越后面的语言越像LispPython语言模仿Lisp,甚至把许多Lisp黑客认为属于设计错误的功能也一起模仿了。至于Ruby语言,如果回到1975年,你声称它是一种有着自己句法的Lisp方言,没有人会提出反对意见。编程语言现在的发展不过刚刚赶上1958Lisp语言的水平

朝着数学方向发展

由此也就得出了20世纪50年代的编程语言到现在还没有过时的原因。简单说,因为这种语言本质上不是一种技术,而是数学。数学是不会过时的。你不应该把Lisp语言与50年代的硬件联系在一起,而是应该把它与快速排序(Quicksort)算法进行类比。这种算法是1960年提出的,至今仍然是最快的通用排序方法。

Fortran语言也是20世纪50年代出现的,并且一直使用至今。它代表了语言设计的一种完全不同的方向。Lisp语言是无意中从纯理论发展为编程语言的,而Fortran从一开始就是作为编程语言设计出来的。但是,今天我们把Lisp看成高级语言,而把Fortran看成一种相当低层次的语言。

1956Fortran刚诞生的时候,叫做Fortran I,与今天的Fortran语言差别极大。Fortran I 实际上是汇编语言加上数学,在某些方面还不如今天的汇编语言强大。比如,它没有子例程,只有分支跳转结构(branch)。今天的Fortran语言可以说更接近Lisp而不是Fortran I

LispFortran代表了编程语言发展的两大方向。前者的基础是数学,后者的基础是硬件架构。从那时起,这两大方向一直在互相靠拢。Lisp语言刚设计出来的时候就很强大,接下来的二十年它提高了运行速度。而那些所谓的主流语言把更快的运行速度作为设计的出发点,然后再用四十多年的时间一步步变得更强大。直到今天,最高级的主流语言也只是刚刚接近Lisp的水平。虽然已经很接近了,但还是没有Lisp那样强大。

向心力

使用一种不常见的语言会出现的问题我想到了三个:你的程序可能无法很好地与使用其他语言写的程序协同工作;你可能找不到很多函数库;你可能不容易雇到程序员。

它们有多严重?第一个问题取决于你是否控制整个系统。如果你的软件运行在客户的机器上,而客户又使用一个到处都是bug的专有操作系统(我可没提操作系统的名字),那么使用那个操作系统的开发语言可能会给你带来优势。但是,如果你控制整个系统,并且还有各个组成部分的源码(正如我推测ITA就是这种情况),那么你就能使用任何你想用的语言。如果出现不兼容的情况,你自己就能动手解决。

把软件运行在服务器端就可以没有顾忌地使用最先进的技术。乔纳森·埃里克森说现在是“编程语言的文艺复兴时期”,我想最大的原因就是有了服务器端软件。这也能解释为什么像PerlPython这样的新语言会流行起来,它们之所以流行不是因为人们使用它们开发Windows应用程序,而是因为人们在服务器上使用它们。随着软件从桌面端向服务器端转移(连微软公司都看出这是未来的趋势),逼迫你使用某一种语言的限制将越来越少。

至于第二个问题,函数库的重要性也取决于你的应用程序。对于那些条件不苛刻的应用,有没有一个好的函数库比语言本身的能力更重要。那么到底应该怎么选择语言?是根据函数库,还是根据语言本身的能力?很难确切地找出一条清楚的规则,但是无论哪种情况,你都必须考虑到你开发的应用程序的特点。如果你是一家软件公司,你开发的程序打算拿到市场上销售,那么这个程序可能会耗费好几个优秀程序员至少6个月的时间。为一个这样规模的项目选择编程语言,语言本身要有强大的编程能力可能就是最重要的考虑因素,比是否有方便的函数库更重要

第三个问题是你的经理担忧雇不到程序员,我认为这根本就是混淆视听。说实话,你究竟想雇用多少个黑客?到目前为止,大家公认少于10个人的团队最适合开发软件。雇用这样规模的开发团队,只要使用的不是无人知道的语言,应该都不会遇到很大麻烦。如果你无法找到10Lisp黑客,那么你可能选错了创立软件公司的城市。

事实上,选择更强大的编程语言会减少所需要的开发人员数量。因为:(a)如果你使用的语言很强大,可能会减少一些编程的工作量,也就不需要那么多黑客了;(b)使用更高级语言的黑客可能比别的程序员更聪明。

随大流的代价

使用一种不强大的语言,你的损失有多大?实际上有一些现成的数据可以说明这个问题。

衡量语言的编程能力的最简单方法可能就是看代码数量。所谓高级语言,就是能够提供更强大抽象能力的语言,从某种意义上,就像能够提供更大的砖头,所以砌墙的时候用到的砖头数量就变少了。因此,语言的编程能力越强大,写出来的程序就越短(当然不是指字符数量,而是指独立的语法单位)。

强大的编程语言如何让你写出更短的程序?一个技巧就是(在语言允许的前提下)使用“自下而上”(bottom-up)的编程方法。你不是用基础语言(base language)开发应用程序,而是在基础语言之上先构建一种你自己的语言,然后再用后者开发应用程序。这样写出来的代码会比直接用基础语言开发出来的短得多。实际上,大多数压缩算法也是这样运作的。“自下而上”的编程往往也便于修改,因为许多时候你自己添加的中间层根本不需要变化,你只需要修改前端逻辑就可以了。

一个诀窍

在大型组织内部,有一个专门的术语描述这种跟随大多数人的选择的做法,叫做“业界最佳实践”。这个词出现的原因其实就是为了让你的经理可以推卸责任。既然我选择的是“业界最佳实践”,如果不成功,项目失败了,那么你也无法指责我,因为做出选择的人不是我,而是整个“业界”。

我认为这个词原来是指某种会计方法,大致意思就是不要采用很奇怪的处理方法。在会计方法中,这可能是一个很好的主意。“尖端”和“核算”这两个词听上去就不适合放在一起。但是如果你把这个标准引入技术决策,你就开始要出错了。
技术本来就应该是尖端的。正如伊拉恩·加内特所说,编程语言的所谓“业界最佳实践”,实际上不会让你变成最佳,只会让你变得很平常。如果你选择的编程语言使得你开发软件的速度只有(选择更激进技术的)对手的几分之一,那么“最佳实践”真的起错了名字。

所以,我们就有了两点结论,我认为它们非常有价值。事实上,这是我用自己的经历换来的。第一,不同语言的编程能力不一样。第二,大多数经理故意忽视第一点。你把这两点事实结合起来,其实就得到了赚钱的诀窍。ITA 软件公司是运用这个诀窍的典型例子。如果你想在软件业获得成功,就使用你知道的最强大的语言,用它解决你知道的最难的问题,并且等待竞争对手的经理做出自甘平庸的选择。

第十四章:梦寐以求的编程语言

我的朋友曾对一位著名的操作系统专家说他想要设计一种真正优秀的编程语言。那位专家回答,这是浪费时间,优秀的语言不一定会被市场接受,很可能无人使用,因为语言的流行不取决于它本身。至少,那位专家设计的语言就遭遇到了这种情况。
那么,语言的流行到底取决于什么因素呢?流行的语言是否真的值得流行呢?还有必要尝试设计一种更好的语言吗?如果有必要的话,怎样才能做到这一点呢?

流行的秘诀

专家级黑客的看法不是决定一种语言流行程度的唯一因素,某些古老的软件(FortranCobol的情况)和铺天盖地的广告宣传(AdaJava的情况)也会起到作用。但是,我认为从长期来看,专家级黑客的看法是最重要的因素。只要有了达到“临界数量”(critical mass)的最初用户和足够长的时间,一种语言可能就会达到应有的流行程度。而流行本身又会使得这种优秀的语言更加优秀,进一步拉大它与平庸语言之间的好坏差异,因为使用者的反馈总是会导致语言的改进。你可以想一下,所有流行的编程语言从诞生至今的变化有多大。PerlFortran是极端的例子,除它们两个之外,甚至就连Lisp都发生了很大的变化。

所以,即使不考虑语言本身的优秀是否能带动流行,我想单单流行本身就肯定会使得这种语言变得更好,只有流行才会让它保持优秀。编程语言的最高境界一直在发展之中。虽然语言的核心功能就像大海的深处,很少有变化,但是函数库和开发环境之类的东西就像大海的表面,一直在汹涌澎湃。

当然,黑客必须先知道这种语言,才可能去用它。他们怎么才能知道呢?就是从其他黑客那里。所以不管怎样,一开始必须有一群黑客使用这种语言,然后其他人才会知道它。我不知道“一群”的最小数量是多少,多少个黑客才算达到“临界数量”呢?如果让我猜,我会说20人。如果一种语言有20个独立用户,就意味这20个人是自主决定使用这种语言的,我觉得这就说明这种语言真的有优点。

影响流行的外部因素

我们得先承认,确实有一个外部因素会影响到语言的流行。一种语言必须是某一个流行的计算机系统的脚本语言(scripting language),才会变得流行。FortranCobol是早期IBM大型机的脚本语言。CUnix的脚本语言,后来的PerlPython也是如此。TclTk的脚本语言,Visual BasicWindows的脚本语言,(某种形式的)LispEmacs的脚本语言,PHP是网络服务器的脚本语言,JavaJavaScript是浏览器的脚本语言。

编程语言不是存在于真空之中。“编程”其实是及物动词,黑客一般都是为某个系统编程,在现实中,编程语言总是与它们依附的系统联系在一起的。所以,如果你想设计一种流行的编程语言,就不能只是单纯地设计语言本身,还必须为它找到一个依附的系统,而这个系统也必须流行。除非你只想用自己设计的语言取代那个系统现有的脚本语言。

这种情况导致的一个结果就是,无法以一种语言本身的优缺点评判这种语言。另一个结果则是,只有当一种语言是某个系统的脚本语言时,它才能真正成为编程语言。如果你对此很吃惊,觉得不公平,那么我会跟你说不必大惊小怪。这就好比大家都认为,如果一种编程语言只有语法规则,没有一个好的实现(implementation),那么它就不能算完整的编程语言。这些都是很正常很合理的事情,编程语言本来就该如此。

简洁

假定你的语言已经能够满足上面三项条件——一种免费的实现,一本相关书籍,以及语言所依附的计算机系统——那么还需要做什么才能使得黑客喜欢上你的语言?

黑客欣赏的一个特点就是简洁。黑客都是懒人,他们同数学家和现代主义建筑师一样,痛恨任何冗余的东西或事情。有一个笑话说,黑客动手写程序之前,至少会在心里盘算一下哪种语言的打字工作量最小,然后就选择使用该语言。这个笑话其实与真实情况相差无几。就算这真的是个笑话,语言的设计者也必须把它当真,按照它的要求设计语言。

简洁性最重要的方面就是要使得语言更抽象。为了达到这一点,首先你设计的必须是高级语言,然后把它设计得越抽象越好。语言设计者应该总是看着代码,问自己能不能使用更少的语法单位把它表达出来。如果你有办法让许多不同的程序都能更简短地表达出来,那么这很可能意味着你发现了一种很有用的新抽象方法。

可编程性(Hackability)

优秀程序员经常想做一些既危险又令人恼火的事情。所谓“令人恼火”,我指的是他们会突破设计者提供给用户的外部语义层,试着控制某些高级抽象的语言内部接口。比如,黑客喜欢破解,而破解就意味着深入内部,揣测原始设计者的意图。

你应该敞开胸怀,欢迎这种揣测。对于制造工具的人来说,总是会有用户以违背你本意的方式使用你的工具。如果你制造的是编程语言这样高度组合的系统,那就更是如此了。许多黑客会用你做梦也想不到的方式改动你的语法模型。我的建议就是,让他们这样干吧,而且应该为他们创造便利,尽可能多地把语言的内部暴露在他们面前。

其实,黑客并不会彻底颠覆你的工具,在一个大型程序中,他可能只是对语言改造一两个地方。但是,改动多少地方并不重要,重要的是他能够对语言进行改动。这可能不仅有助于解决一些特殊的问题,还会让黑客觉得很好玩。黑客改造语言的乐趣就好比外科医生摆弄病人内脏的乐趣,或者青少年喜欢用手挤破青春痘的那种感觉。至少对男生来说,某些类型的破坏非常刺激。针对青年男性读者的Maxim杂志每年出版一本特辑,里面一半是美女照片,另一半是各种严重事故的现场照片。这本杂志非常清楚它的读者想看什么。

一种真正优秀的编程语言应该既整洁又混乱。“整洁”的意思是设计得很清楚,内核由数量不多的运算符构成,这些运算符易于理解,每一个都有很完整的独立用途。“混乱”的意思是它允许黑客以自己的方式使用。C语言就是这样的例子,早期的Lisp语言也是如此。真正的黑客语言总是稍微带一点放纵不羁、不服管教的个性。

优秀的编程语言所具备的功能,应该会使得言必称“软件工程”的人感到非常不满、频频摇头。与黑客语言形成鲜明对照的就是像Pascal那样的语言,它是井然有序的模范,非常适合教学,但是除此之外就没有很大用处了。

一次性程序

为了吸引黑客,一种编程语言必须善于完成黑客想要完成的各种任务。这意味着它必须很适合开发一次性程序。这一点可能出乎很多人的意料。

所谓一次性程序,就是指为了完成某些很简单的临时性任务而在很短时间内写出来的程序。比如,自动完成某些系统管理任务的程序,或者(为了某项模拟任务)自动生成测试数据的程序,以及在不同格式之间转化数据的程序等。令人吃惊的是,一次性程序往往不是真的只用一次,就像二战期间很多美国大学造的一大批临时建筑后来都成了永久建筑。许多一次性程序后来也都变成了正式的程序,具备了正式的功能和外部用户。

开发大型程序的另一个方法就是从一次性程序开始,然后不断地改进。这种方法比较不会让人望而生畏,程序在不断的开发之中逐渐进步。一般来说,使用这种方法开发程序,一开始用什么编程语言,就会一直用到最后,因为除非有外部政治因素的干预,程序员很少会中途更换编程语言。所以,我们就有了一个看似矛盾的结论:如果你想设计一种适合开发大型项目的编程语言,就必须使得这种语言也适合开发一次性程序,因为大型项目就是从一次性程序演变而来的。

函数库

简洁性的最高形式当然是有人已经帮你把程序写好,你只要运行就可以了。函数库就是别人帮你写好的程序,所以它是编程语言的另一个重要特点,并且我认为正在变得越来越重要。Perl 就赢在它具有操作字符串的巨大函数库。这类函数库对一次性程序特别重要,因为开发一次性程序的原始目的往往就是转化或提取字符串。许多Perl程序的原型可能就是把几个函数库调用放在一起。

效率

众所周知,好的编程语言生成的代码有较快的运行速度。但是实际上,我觉得代码的运行速度不是编程语言的设计者能够控制的。高德纳很久以前就指出,运行速度只取决于一些关键的瓶颈。而在编程实践中,许多程序员都已经注意到自己很容易搞错瓶颈到底在哪里。

所以,编程时提高代码运行速度的关键是使用好的性能分析器(profiler),而不是使用其他方法,比如精心选择一种静态类型的编程语言。为了提高运行速度,并没有必要每个函数的每个参数类型都声明清楚,你只需要在瓶颈处声明清楚参数类型就可以了。所以,更重要的是你需要能够找出瓶颈到底在什么地方。

人们在使用非常高级的语言(比如Lisp)时,经常抱怨很难知道哪个部分对性能的影响比较大。可能确实如此,如果你使用一种非常抽象的语言,这也许是无法避免的。不管怎样,我认为一个好的性能分析器会解决这个问题,虽然这方面还有很长的路要走,但是未来你可以快速知道程序每个部分的时间开销。

这个问题一部分源于沟通不畅。语言设计者喜欢提高编译器的速度,认为这是对自己技术水平的考验,而最多只把性能分析器当作一个附送给使用者的赠品。但是在现实中,一个好的性能分析器对程序的帮助可能大于编译器的作用。这里又一次反映出语言设计者与用户之间发生了脱节,前者竭尽全力想要解决的问题其实方向不甚正确。

让性能分析器自动运行可能是一个好主意。它自动告诉程序员每个部分的性能,而不是非要等到程序员手动运行后才能知道。比如,当程序员编辑源码的时候,代码编辑器能够实时用红色显示瓶颈的部分。另一个方法应该是设法显示正在运行的程序的情况,这对互联网软件尤其重要,因为服务器上有很多程序同时运行,它们都需要你密切关注。自动运行的性能分析器用图形实时显示程序运行时的内存状况,甚至可以发出声音,表示出现了问题。

现在有一些语言先编译成字节码(byte code),然后再由解释器执行。这样做主要是为了让代码容易移植到不同的操作系统,但是这也可以变成一项很有用的功能。让字节码成为语言的正式组成部分,允许程序员在瓶颈处内嵌字节码,这可能是一个不错的主意。然后,针对这部分字节码的优化也就变得可以移植了。

正如许多最终用户已经意识到的,运行速度的概念正在发生变化。随着互联网软件的兴起,越来越多的程序主要不是受限于计算机的运算速度,而是受限于I/O的速度。加快I/O速度将是很值得做的一件事。在这方面,编程语言也能起到作用,有些措施是显而易见的,比如采用简洁、快速、格式化输出的函数,还有些措施则需要深层次的结构变化,比如采用缓存和持久化对象(persistent object)。

用户关心的是反应时间(response time),但是软件的另一种效率正在变得越来越重要,那就是每个处理器能够同时支持的用户数量。未来许多有趣的应用程序都将是运行在服务器端的互联网软件,所以每台服务器能够支持的用户数量就成了软件业者的关键问题。互联网软件的成本支出就取决于这个指标。

许多年以来,大多数面向最终用户的程序都不太关心效率。软件开发者总是假设用户桌面电脑的运算能力会不断增长,所以不用刻意提高软件的效率。帕金森定律被证明与摩尔定律一样颠扑不破。软件不断膨胀,消耗光所有可以得到的资源。这一切将随着互联网软件的出现发生改变,因为硬件和软件现在捆绑在一起供应。对于那些提供互联网软件的公司来说,将每台服务器支持的用户数量最大化会对降低成本产生巨大影响。

在一些应用程序中,处理器的运算能力是瓶颈,那么最重要的优化对象就是软件的运行速度。但是,一般情况下内存才是瓶颈,你能够同时支持的用户数量取决于用户数据所消耗的内存。编程语言在这方面也能发挥作用,对线程的良好支持将使得所有用户共享同一个内存堆(heap)。持久化对象和语言内核级别的延迟加载(lazy loading)支持也有助于减少内存需求。

时间

一种编程语言要想变得流行,最后一关就是要经受住时间的考验。没人想用一种会被淘汰的语言编程,这方面已经有很多前车之鉴了。所以,大多数黑客往往会等上几年,看看某一种新语言的势头,然后才真正考虑使用它。

新事物的发明者通常对这个发现很震惊,他们没想到人们居然这样对待发明创造。但是,让别人相信一种新事物是需要时间的。我有一个朋友,他的客户第一次提出某种需求时,他很少理会。因为他知道人们有时候会想要自己并不真正需要的东西。为了避免浪费时间,只有当客户第三次或第四次提出同样的需求时,他才认真对待。这个时候客户可能已经很不高兴了,但是这至少保证他们提出的需求应该就是他们真正需要的东西。

大多数人接触新事物时都学会了使用类似的过滤机制。甚至有时要听到别人提起十遍以上他们才会留意。这样做完全是合理的,因为大多数的热门新商品事后被证明都是浪费时间的噱头,没多久就消失得无影无踪。虚拟现实建模语言VRML刚诞生时曾经轰动一时,但是我决定等到一两年后再去学习它,结果一两年后已经没有学习的必要了,因为市场已经把它遗忘了。

所以,发明新事物的人必须有耐心,要常年累月不断地做市场推广,直到人们开始接受这种发明。我们就耗费了好几年才使得客户明白Viaweb不需要下载安装就能使用。不过,好消息是,简单重复同一个信息就能解决这个问题。你只需要不停地重复同一句话,最终人们将会开始倾听。人们真正注意到你的时候,不是第一眼看到你站在那里,而是发现过了这么久你居然还在那里。

再设计

著名散文家E.B.怀特说过,“最好的文字来自不停的修改”。所有优秀作家都知道这一点,它对软件开发也适用。设计一样东西,最重要的一点就是要经常“再设计”,编程尤其如此,再多的修改都不过分。

为了写出优秀软件,你必须同时具备两种互相冲突的信念。一方面,你要像初生牛犊一样,对自己的能力信心万丈;另一方面,你又要像历经沧桑的老人一样,对自己的能力抱着怀疑态度。在你的大脑中,有一个声音说“千难万险只等闲”,还有一个声音却说“早岁哪知世事艰”。

第十五章:设计与研究

设计与研究的区别看来就在于,前者追求“好”(good),后者追求“新”(new)。优秀的设计不一定很“”,但必须是“”的;优秀的研究不一定很“”,但必须是“”的。我认为这两条道路最后会发生交叉:只有应用“”的创意和理论,才会诞生超越前人的最佳设计;只有解决那些值得解决的难题(也就是“”的难题),才会诞生最佳研究。所以,最终来说,设计和研究都通向同一个地方,只是前进的路线不同罢了

在软件领域,贴近用户的设计思想被归纳为“弱即是强”(Worse is Better)模式。这个模式实际上包含了好几种不同的思想,所以至今人们还在争论它是否真的成立。但是,其中有一点是正确的,那就是如果你正在设计某种新东西,就应该尽快拿出原型,听取用户的意见。

与之对照,还有另一种软件设计思想,也许可以被称为“万福玛丽亚”模式。它不要求尽快拿出原型,然后再逐步优化,它的观点是你应该等到完整的成品出来以后再一下子隆重地推向市场,就像圣母玛丽亚降临一样,哪怕整个过程漫长得像橄榄球运动员长途奔袭、达阵得分也没有关系。在互联网泡沫时期,无数创业公司因为相信了这种模式而自毁前程。我还没听说过有人采用这种模式而获得成功。

软件领域以外的人可能没听过“弱即是强”,所以意识不到这种模式在艺术领域普遍存在。以绘画为例,文艺复兴时期就有人发现了这一点。如今,几乎所有的美术老师都会告诉你准确画出一个事物的方法,不是沿着轮廓慢慢一个部分、一个部分地把它画出来,因为这样的话各个部分的错误会累积起来,最终导致整幅画失真。你真正应该采用的方法是快速地用几根线画出一个大致准确的轮廓,然后再逐步地加工草稿。

软件开发也可以这样做。原型(prototype)并不只是模型(model),不等于将来一定要另起炉灶,你完全能够在原型的基础上直接做出最后的成品。我认为,只要有可能,你就应该这样做。这样的方式使得你可以利用在开发过程中一路产生的新想法。不过更重要的是,这样做有助于鼓舞士气。

先做出原型,再逐步加工做出成品,这种方式有利于鼓舞士气,因为它使得你随时都可以看到工作的成效。开发软件的时候,我有一条规则:任何时候,代码都必须能够运行。如果你正在写的代码一个小时之后就可以看到运行结果,这好比让你看到不远处就是唾手可得的奖励,你因此会受到激励和鼓舞。其他艺术领域也是如此,尤其是油画。大多数画家都是先画一个草图,然后再逐步加工。如果你采用这种方式,那么从理论上说,你每天收工的时候都可以看到整体的效果,不会对最后的成品一点感觉都没有。跟你说实话吧,画家之间甚至流传着一句谚语:“画作永远没有完工的一天,你只是不再画下去而已。”这种情况对于第一线的程序员真是再熟悉不过了。

士气也可以解释为什么很难为低端用户设计出优秀产品。因为优秀设计的前提是你自己必须喜欢这种产品,否则你不可能对设计有兴趣,更不要说士气高昂了。为了把产品设计好,你必须对自己说:“哇,这个产品太棒了,我一定要设计好!”而不是心想:“这种垃圾玩意,只有傻瓜才会喜欢,随便设计一下就行了。”

设计意味着做出符合人类特点和需要的产品。但是,“人类”不仅包括用户,还包括设计师,所以设计工作本身也必须符合设计师的特点和需要