黑客与画家

刚看完黑客与画家,断断续续看了很久,有些语言略显絮叨,但确是一本好书。作者是硅谷创业之父Paul Graham,他本身也是一个画家,这两种职业也让他产生了思考,诠释了画家与黑客行为方式,思考方式的共通之处。这里的黑客并不是指传统意义上的破坏者,而是有探索精神的程序员。

如何编程

本科的时候老师向我们一再强调编程前需要整体构思,确认可行之后再开始敲代码,常常会陷入苦思而无法开敲。读研期间,老师告诉我们,设计一个程序的时候多使用原型系统,即先不考虑太多,保证基本的功能实现,再根据需求往上添加功能。同理,敲代码的时候是否也可以先不管所谓的整体构思,先把自己的想法敲上去,再进行修改。
敲的东西多了之后,也开始慢慢质疑本科老师的做法,因为我按之后的方法去做之后,体会到了编程的些许乐趣,不必再为漫无目的的思考耗费太多精力。其实直接去敲代码的过程实际上才是真正构思的过程,在实践中思考才不至于空泛。

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

我不是耐心地一步步写出整个程序,确保大体上是正确的,而是一股脑不管对错,先把代码堆上去,再慢慢修改。

你把整个程序想清楚的时间点,应该是在编写代码的同时,而不是在编写代码之前,这与作家、画家和建筑师的做法完全一样。

编程语言是用来帮助思考程序的,而不是用来表达你已经想好的程序。

你不能盼望先有一个完美的规格设计,然后再动手编程,这样想是不现实的。如果你预先承认规格设计是不完美的,在编程的时候,就可以根据需要当场修改规格,最终会有一个更好的结果。

好的设计

什么才算是一个好程序设计,思考这个问题就像我们去思考,什么样的画流芳百世,什么样的建筑令人称赞,它们都有着一些通性。

  1. 好设计是简单的设计。
  2. 好设计是解决主要问题的设计。
  3. 好设计是启发性的设计。英国女作家简·奥斯汀的作品几乎不带有任何描述。她不告诉读者每件东西看上去是什么样子,只是把故事讲得非常生动,让读者自己把一切都想象出来。
  4. 好设计是看似容易的设计。
  5. 好设计是对称的设计。对称也许只是简洁性的一种表现,但是它十分重要,值得单独列为一点。在写作中,你会发现对称无处不在,短语、句子、小说的情节都是如此。音乐和美术也大量使用对称。
  6. 好设计是模仿大自然的设计。
  7. 好设计是能够复制的设计。

还有一些作者非常独到的对设计的一些看法。

大多数创作者都是为人类用户而创作。为了吸引用户,你必须理解用户需要什么。举例来说,几乎所有最伟大的绘画作品都是画人的,因为人类总是对自身感兴趣的。

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

为了做出优秀的设计,你必须贴近用户,始终寸步不离,永远站在用户的角度调整自己的构想。

让用户满意并不等于迎合用户的一切要求。用户不了解所有可能的选择,也经常弄错自己真正想要的东西。做一个好的设计师就像做一个好医生一样。你不能头痛医头,脚痛医脚。病人告诉你症状,你必须找出他生病的真正原因,然后针对病因进行治疗。

essay(论文)这个词来自法语的动词essayer,意思是“试试看”。从这个原始意义来说,论文就是你写一篇文章,试着搞清楚某件事。软件也是如此。我觉得一些最好的软件就像论文一样,也就是说,当作者真正开始动手写这些软件的时候,他们其实不知道最后会写出什么结果。

大多数创作者都是为人类用户而创作,正如几乎所有最伟大的绘画作品都是画人的,因为人类总是对自身感兴趣。

创造财富

作者对如何创造财富做出了自己的思考,事实上,如何致富这个标题确实起得很诱人,虽然有些话很有启发意义,但最好还是不要觉得致富这门课有什么近路可抄。

创造有价值的东西就是创造财富。你最好先搞清楚什么是财富。财富与金钱并不是同义词。

最可能明白财富能被创造出来的人就是那些善于制作东西的人,也就是手工艺人。他们做出来的东西直接放在商店里卖。但是,随着工业化时代的来临,手工艺人越来越少。目前还存在的最大的手工艺人群体就是程序员。

如果某人坐在电脑前,写出了一个不那么糟糕的浏览器(顺便说一句,这是一件很值得做的事),世界就会变得富有得多。

一个大学毕业生总是想“我需要一份工作”,别人也是这么对他说的,好像变成某个组织的成员是一件多么重要的事情。更直接的表达方式应该是“你需要去做一些人们需要的东西”。即使不加入公司,你也能做到。公司不过是一群人在一起工作,共同做出某种人们需要的东西。真正重要的是做出人们需要的东西,而不是加入某个公司。

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

但是,如果你想同时具备可测量性和可放大性,不一定非当上CEO或电影明星不可。你只需要成为某个攻克难题的小团体的一部分就可以了。 小团体=可测量性 就算你无法测量每个员工的贡献,但是你可以得到近似值,那就是测量小团队的贡献。

小团队在如今这个时代可谓如鱼得水,因为他们不受官僚主义和繁琐管理制度的拖累。而且,技术的突破往往来自非常规的方法,小团队就较少受到常规方法的约束。

真正重要的是做出人们需要的东西,而不是加入某个公司。所以有那么多优秀的人愿意从大公司中跳出成为某个创业团队的一部分,他们能够比在大公司中创造更多的价值。

未来的编程语言

这里最让我印象深刻的是作者对我从前的一个顽念的批判。

某个看上去饱经风霜又酷的黑客往酒吧里一坐,“你用什么语言并不重要,重要的是你对问题是否有正确的理解。代码以外的东西才是关键。” 这当然是一派胡言。各种语言简直是天差地别。

不同的语言使用习惯会对你的思维方式产生巨大的影响。
同时作者也指出了未来的编程语言的趋势,随着计算机硬件速度的加快,效率的问题会日益减弱,那些方便快捷,并且能满足程序员奇思妙想的功能的语言将脱颖而出。浪费程序员的时间可比浪费计算机的时间不划算得多。

不过,硬件的运行速度越来越快了,所以使用C这样的低层次语言开发应用程序的必要性正在不断减少。

有些人认为编程语言应该防止程序员干蠢事,另一些人则认为程序员应该可以用编程语言干一切他们想干的事。Java语言是前一个阵营的代表,Perl语言则是后一个阵营的代表。

在静态类型语言中,写代码时必须知道每个变量的类型。而在动态类型语言中,随便什么时候,你都可以把变量设为任意类型的值。

我认为,编程语言就像生物物种一样,存在一个进化的脉络,许许多多分支最终都会成为进化的死胡同。这种现象已经发生了,当我说Java不会成功时,我的意思是它和Cobol一样,进化之路已经走到了尽头。

在长期的职业生涯中,我发现冗余的代码会导致更多冗余的代码。

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

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

如果我们把一种语言的内核设想为一些基本公理的集合,那么仅仅为了提高效率就往内核添加多余的公理,却没有带来表达能力的提升,这肯定是一件很糟的事。没错,效率是很重要,但是我认为修改语言设计并不是提高效率的正确方法。

语言设计时,对实现方式少作限制还会使得程序具备更大的灵活性。语言的规格发生变化不仅是无法避免的,也是合理的。

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

我觉得,除了某些特定的领域,这种编程方法其实没有为优秀程序员带来很多好处,但是它对大公司有不可抗拒的吸引力。面向对象编程使得你有办法对一团乱码似的代码进行可持续性开发。通过不断地打补丁,它让你将软件一步步做大。

但是实际上,我觉得代码的运行速度不是编程语言的设计者能够控制的。高德纳很久以前就指出,运行速度只取决于一些关键的瓶颈。

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

正如许多最终用户已经意识到的,运行速度的概念正在发生变化。随着互联网软件的兴起,越来越多的程序主要不是受限于计算机的运算速度,而是受限于I/O的速度。加快I/O速度将是很值得做的一件事。

这种语言干净简练,具有最高层次的抽象和互动性,而且很容易装备,可以只用很少的代码就解决常见的问题。不管是什么程序,你真正要写的代码几乎都与你自己的特定设置有关,其他具有普遍性的问题都有现成的函数库可以调用。

代码的运行速度不是编程语言的设计者所能控制的,关键是用好性能分析器。而且现在的运行速度的概念发生了变化,更多地受限于I/O的速度。

其他

书中还有很多很有意思的观点。
比方说对未来软件形式的看法

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

设计桌面软件就像设计一幢大楼,而设计互联网软件就像设计一座城市。

如果你写过互联网软件,你会发现“后退”按钮是设计中最费脑筋的问题之一,很有意思。

对行为方式的思考

如果别人告诉你应该相信什么,你就真的相信了,那么你就会和别人一样犯下同样的错误。

训练自己去想那些不能想的事情,你获得的好处会超过所得到的想法本身。

这时你要明白,自由思考比畅所欲言更重要。如果你感到一定要跟那些人辩个明白,绝不咽下这口气,一定要把话说清楚,结果很可能是从此你再也无法自由理性地思考了。我认为这样做不可取,更好的方法是在思想和言论之间划一条明确的界线。在心里无所不想,但是不一定要说出来。

研究与设计的不同

研究就不一样了。做数学研究时,你不会只为了方便读者理解而故意选择一种更麻烦的证明方式,你只会选择最直接、最简洁的证明。我想,一般来说科学研究都是这样。科学观点不需要服从人类工程学(ergonomic)。 到了艺术领域,情况就完全变了。设计必须以人为本。设计椅子的时候,你不能只考虑椅子,还必须考虑人体各种千奇百怪的特点,不可能回避掉这一点。

方法论

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

最后

正如作者自己所说,你只有非常熟悉某一块领域,你才能知道这一块领域有哪些不足,需要做出哪些修改。也只有经历过,才能更深刻地去思考问题。作者的经历以及阅历让我佩服,虽然书中很多观点带有强烈的主观意识,但是这份思考却是给了我很大的启发。

推荐阅读更多精彩内容