15.设计与研究

外国游客常常惊讶地发现,美国人交谈的时候,一开始总是问“你干什么工作”。我一直讨厌回答这个问题,因为一句话说不清楚。不过我最终找到了解决方法,现在如果有人问我干什么工作,我会正规对方的双眼说:“我正在设计一种Lisp语言的新方言。”如果你也有同样困扰,我推荐你也如此回答。对方就立刻转向其他话题了。

我确实是在“设计”一种编程语言,而且我不认为自己在做“研究”。我所做的工作与其他人设计一幢大楼、一把椅子、一种新字体并没有本质不同。我的目的不是发现一种“新”东西,而是做出一种很“好”的编程语言。

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

如果把创造一种编程语言看成是设计问题,而不是科研方向,那么有何不同?

最大的不同在于你会更多地考虑用户。设计的时候,一开始总是问:我为谁设计?他们需要什么?比如,优秀的建筑师不会先设计,然后强迫用户接受,而是先研究最终用户的需求,然后做出用户需要的设计。

注意,我说的是“用户需要的设计”,而不是“用户要求的设计”。我不想让读者产生一种印象,认为设计师就像厨师一样,顾客点什么菜就一模一样做出来。艺术的各个领域有着巨大的差别,但是我觉得任何一个领域的最佳作品都不可能由对用户言听计从的人做出来。

有一句话说“顾客永远是对的”,这是指评价优秀设计的标准是看它能够多大程度上满足用户的需求。如果你的小说没人爱看,或者你做的椅子极不舒服,那么就说明你的作品失败了,被一票否决了。就算你的小说(或者椅子)有着最先进的理论指导也无济于事。

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

大多数优秀设计都是这样产生的,它们关注用户,并且以用户为中心。

我说设计必须考虑用户的需求,这里的“用户”并不是指所有普罗大众。事实上,你可以选择任何想要的目标用户。比如,假定你正在设计一种工具,你可以把目标用户定为初学者,也可以定为专家级用户。一种人眼里的优秀设计可能在另一种人眼里却是糟糕无比。这里的重点是你必须选出某些人作为你的目标用户。我觉得,除非设定目标用户,否则一种设计的好坏根本无从谈起。

如果目标用户群体涵盖了设计师本人,那么最有可能诞生优秀设计。如果目标用户与你本人差别很大,你往往会假定目标用户的需求比你本人的需求更简单,而不是更复杂。低估用户(即使出于善意)一般来说总是会让设计师出错。我怀疑那些设计“公共住宅项目”(housing project)^的建筑师根本没想过自己住在里面会是什么感觉。编程语言也有这种现象。C、Lisp和Smalltalk都是设计者为了自己使用而设计的,而Cobol、Ada和Java则是为了给别人使用而设计的。

^「“公共住宅”指的是由政府出资建造的房产,用来出租给低收入家庭居住,类似于廉租房。——译者注」

如果你觉得自己在为傻瓜设计产品,那么很可能不仅无法设计出优秀产品,而且就连傻瓜也不喜欢你的设计。

不过,就算你的设计针对的是最高端的用户,你也一样是设计给人类使用。研究就不一样了。做数学研究时,你不会只为了方便读者理解而故意选择一种更麻烦的证明方式,你只会选择最直接、最简洁的证明。我想,一般来说科学研究都是这样。科学观点不需要服从人类工程学(ergonomic)。

到了艺术领域,情况就完全变了。设计必须以人为本。设计椅子的时候,你不能只考虑椅子,还必须考虑人体各种千奇百怪的特点,不可能回避掉这一点。所有的艺术都必须迎合人类的兴趣和极限。举例来说,不考虑其他因素时,肖像画就是比风景画更能引发观众的兴趣。文艺复兴时期的经典绘画作品都是画人的,这并非巧合。如果绘画艺术不能用来表现人类本身,那么绘画也不会成为今天这样受推崇的艺术形式了。

不管你喜不喜欢,编程语言也是以人为本的。我怀疑人类的大脑与躯干一样,都有着许多令人琢磨不透的特点。否则为什么有些事情人类特别擅长,而另一些事情人类干起来特别困难。比如,人类似乎不善于处理精细的工作,所以最好还是交给计算机处理。另一方面,如果人类真的擅长和细节打交道,那么我们应该都用机器语言编程才对。

另外,还要记住一点。怎么理解编程语言?你不要把它看成那些已完成的程序的表达方式,而应该把它理解成促进程序从无到有的一种媒介。这里的意思是说,成品的材料和开发时用的材料其实是不一样的。搞艺术的人都知道,这两个阶段往往需要不同的媒介。比如,大理石是一种非常良好、耐用的材料,很适合用于最后的成品,但是它极其缺乏弹性和灵活性,所以不适合在构思阶段用来做模型。

最后写出来的程序就像已经完成的数学证明一样,是一棵经过精心修剪的树木,上面杂乱滋生的树杈都已经被剪去了。所以,评价一种语言的优劣不能简单地看最后的程序是否表达得很漂亮,而要看程序从无到有的那条完成路径是否很漂亮。某种设计使得最后的程序非常漂亮,伹是不一定同时具备漂亮的编程过程。比如,我写过一些宏,它们的作用是自动生成另一些宏,它们看上去非常精美优雅,就像一粒粒精细的宝石。但是,开发过程非常丑陋,我就是连续好几个小时不停地试错,而且老实说,至今仍然无法完全确定它们是否百分之百正确。

我们常常采用错误的方法评价编程语言,只看一眼最后完成的程序就做出判断。同一个软件有两种不同语言开发的版本,你发现其中一个版本比另一个版本短得多,于是非常自信地认定前者的编程语言比后者的更好。但是,如果你从艺术创作的角度思考这个问题,就不太可能这样评价编程语言。因为你不想最后只剩下一种像大理石那样漂亮、又像大理石那样难用的编程语言。

比如,开发软件的时候,一个“交互式顶层解释器”(interactive toplevel)会带来巨大的优势。在Lisp语言中,这种解释器就叫做“读取-求值-打印”循环(read-eval-print loop)。有了这个解释器后,语言的设计就会受到巨大影响。静态类型语言不适合部署这样的解释器,因为静态类型语言要求在使用变量前先声明类型,这对于“交互式顶层解释器”行不通。当你在解释器中输入表达式,然后对变量x进行赋值,接着再对x做进一步处理时,你只想尽快看到结果,肯定不想很麻烦地先声明jc的类型。你也许不同意“交互式顶层解释器”为软件开发带来便利的说法,但是如果你接受它,同意易于使用的编程语言必须有一个这样的解释器,那么强制声明变量类型的做法就是与这个解释器不兼容,因此结论就是所有的静态类型语言都不易于编程。

为了做出优秀的设计,你必须贴近用户,始终寸步不离,永远站在用户的角度调整自己的构想。19世纪英国作家简·奧斯汀的小说为何如此出色?一个原因就是她把自己的作品大声读给家人听,所以她就不会陷入孤芳自赏难以自拔的境地,不会长篇累牍地赞叹自然风光,也不会滔滔不绝地宣扬自己的人生哲学。(事实上,简·奥斯汀还是在小说里宣扬了自己的人生哲学,不过她把它编进故事之中,而不是直接像贴标签那样讲出来。)你可以随便找一本平庸的“文学”读物,想象一下把它当作自己的作品读给朋友们听,这样会让你真切地感受到那些“文学”读物高高在上的视角,读者必须承受所有沉重的负担才能阅读这些作品。

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

^「“弱即是强"指的是一种软件传播的模式,由Common Lisp专家理査德·加布里埃尔(Richard P. Gabriel)于1991年在Lisp: Good News, Bad News, How to Win Big(http://www.dreamsongs.com/WIB.html)一文中首先提出。它的含义非常广泛,涉及软件设计思想的各个方面,其中的一个重要结论就是软件功能的增加并不必然带来质量的提高。有时候,更少的功能(“弱”)反而是更好的选择(“强”),因为这会使得软件的可用性提高。相比那些体积庞大、功能全面、较难上手的软件,一种功能有限但易于使用的软件可能对用户有更大的吸引力。加布里埃尔本人经常举Unix和C语言的例子,Unix和C在设计上考虑了实际环境,放弃了一些功能,但是保证了简单性,这使得它们最终在竞争中胜出,成为主流操作系统和编程语言。——译者注」

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

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

在大多数艺术领域,原型使用的材料与成品的材料一般来说是不一样的。印刷活字先画在纸上,然后才做成铅字。雕塑先用石蜡创作,然后才用青铜浇铸。地毯图案先用墨水画出纸型,然后才织成地毯。建筑物先做出木模型,然后才做成石头建筑。

为什么15世纪油画首次亮相会引起轰动并很快流行起来?原因就是油彩使得画家可以在原型上直接画出最后的样子。你可以按照自己的想法画出初稿,但是它并不对你构成限制。接下来你可以逐步加上细节,甚至对初稿做出重大修改,直到最后完成。

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

士气是设计的关键因素。令我吃惊的是,大家很少提到这一点。我的一位美术启蒙老师告诉我:如果你觉得画某样东西很乏味,那么你画出来的东西就会真的很乏味。比如,假设你必须画一幢建筑物,你决定从每一块砖头开始画起。你觉得自己可以坚持下去,但是画到一半的时候突然感到很厌倦,于是你就不再认真观察每块砖头并画出它们各自不同的特点,而是以一种机械重复的方式草草地把砖头画完了事。这样一来,你的作品效果就很差,甚至还不如一开始就不采用写实手法,只是若隐若现地暗示砖头的存在。

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

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

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