### 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),不等于將來一定要另起爐灶,你完全能夠在原型的基礎上直接做出最后的成品。我認為,只要有可能,你就應該這樣做。這樣的方式使得你可以利用在開發過程中一路產生的新想法。不過更重要的是,這樣做有助于鼓舞士氣。
士氣是設計的關鍵因素。令我吃驚的是,大家很少提到這一點。我的一位美術啟蒙老師告訴我:如果你覺得畫某樣東西很乏味,那么你畫出來的東西就會真的很乏味。比如,假設你必須畫一幢建筑物,你決定從每一塊磚頭開始畫起。你覺得自己可以堅持下去,但是畫到一半的時候突然感到很厭倦,于是你就不再認真觀察每塊磚頭并畫出它們各自不同的特點,而是以一種機械重復的方式草草地把磚頭畫完了事。這樣一來,你的作品效果就很差,甚至還不如一開始就不采用寫實手法,只是若隱若現地暗示磚頭的存在。
先做出原型,再逐步加工做出成品,這種方式有利于鼓舞士氣,因為它使得你隨時都可以看到工作的成效。開發軟件的時候,我有一條規則:任何時候,代碼都必須能夠運行。如果你正在寫的代碼一個小時之后就可以看到運行結果,這好比讓你看到不遠處就是唾手可得的獎勵,你因此會受到激勵和鼓舞。其他藝術領域也是如此,尤其是油畫。大多數畫家都是先畫一個草圖,然后再逐步加工。如果你采用這種方式,那么從理論上說,你每天收工的時候都可以看到整體的效果,不會對最后的成品一點感覺都沒有。跟你說實話吧,畫家之間甚至流傳著一句諺語:“畫作永遠沒有完工的一天,你只是不再畫下去而已。”這種情況對于第一線的程序員真是再熟悉不過了。
士氣也可以解釋為什么很難為低端用戶設計出優秀產品。因為優秀設計的前提是你自己必須喜歡這種產品,否則你不可能對設計有興趣,更不要說士氣高昂了。為了把產品設計好,你必須對自己說:“哇,這個產品太棒了,我一定要設計好!”而不是心想:“這種垃圾玩意,只有傻瓜才會喜歡,隨便設計一下就行了。”
設計意味著做出符合人類特點和需要的產品。但是,“人類”不僅包括用戶,還包括設計師,所以設計工作本身也必須符合設計師的特點和需要。