Knuth:將計算機編程視作藝術

《ACM通訊》在1959年發行的時候,其社員發表過以下評論,在後來成爲了ACM的追求:

編程如果能在計算機研究和發展方面成爲一個重要的部分,必然存在着從藝術到一門嚴謹科學的過渡。

這個目標在接下來的幾年中不斷重現。例如,1970年“將編程從藝術過渡到嚴謹科學的第一步”發表了。同時,我們也成功地以最簡單的方式將規則變成科學,稱之爲“計算機科學”(computer science).

一個領域一旦被歸爲藝術,就會產生一些讓人不愉快的東西,在具備實質性的聲望之前,必須先被認作科學。另一方面,我花了十二年寫的系列叢書就叫做“計算機程序設計藝術”(The Art of Computer Programming)。經常會有人問我,爲什麼起了這麼一個標題。甚至還有人不相信我用了這麼個標題,在很多引用中,我發現他們錯把書名引用爲“計算機程序行爲”(The Act of Computer Programming,這裏,錯把art當做act)。

在這次演講中,我想解釋一下爲什麼我覺得藝術是最合適的詞、藝術和科學什麼不同、藝術是好是壞以及正視這門學科對我們有什麼幫助。

我第一次談論起這個標題是在1966年。那是在加利福尼亞舉辦的世界性ACM會議上。那時候我的書還沒有出版,我和一個早已瞭解我的自負朋友一起在酒店吃午飯的時候,他打趣道,“新書打算叫做高德納導論嗎”,我回擊道,“恰恰相反,我打算用你的名字。”他叫Art Evans。

這個故事告訴我們,藝術(“art”)一詞可以有不同的意義。實際上,最有趣的地方是,幾乎所有的意思多多少少都和計算機編程有關。準備演講的時候,我去圖書館查了一下有多少和用了“藝術”一詞的出版物。幾天之後得出結論,“藝術”可能是語言中最有意思的一個詞了。

舊的藝術

如果追溯到拉丁文中,ars,artis表示技巧,和希臘的τεχνη有差不多的意思——技術和技巧的詞根。

現在提起藝術,可能你的第一印象就是美術,例如繪畫、雕塑之類的。但在二十世紀之前,藝術的意思和現在大不相同。即使現在,某些方言中還保留這藝術原來的意思,特別是和科學相比較的時候,我想花幾分鐘介紹一下藝術的經典含義。

中世紀時候,第一所大學是爲教授七門學科建立的:語法,辯論,邏輯,算數,幾何,音樂和天文,叫做“liberal arts”。注意,這和今天的文科大學有很大不同,七門課中至少有三門是和計算機密切相關的。那個時候,藝術一詞指的就是人類設計製造的東西,反抗自然和天性。“liberal”就是自由和解放,和耕種等勞動是對立的。中世紀的時候,藝術本身的意思是邏輯,即三段論的學習。

科學 vs 藝術

很多年來,“科學”一詞和“藝術”有着差不多的含義。比如,人們講七門學科統稱作“自由的藝術”,有時候也叫做“自由的科學”。15世紀時Duns Scotus稱邏輯是“科學的科學,藝術的藝術。”隨着文明和科技的進步,它們才逐漸有了區別,“科學”代表知識,“藝術”代表知識的運用。比如,天文科學研究原理,藝術就是研究如何利用其進行導航。和今天科學與工程的差別差不多。

19世紀有很多有關科學和藝術的討論,我覺得最好的是John Stuart Mill,他寫道:

很多時候,幾門不同的科學相互聯繫,來完成一件事情。人們要結合不同的事物,來做到一件事,這需要懂得不同方面的知識。從某種意義上說,藝術就是組合不同方面的科學,將其付諸實踐,而不止於空想。將不同的科學組合在一起,我們纔有了探索宇宙真理的可能。藝術將關係偏僻的學科聯繫在一起,運用到現實生活中,來滿足我們的需求。

在我研究藝術的意義時,我發現從藝術到科學的過渡持續了至少兩個世紀。比如,1784年的一本礦物學教材的序言中有下面一句話:“在1780年之前,礦物學被認爲是藝術,還不算作科學。”

大多數字典中,科學的意思是邏輯、系統地組織一般規律。科學就是可以讓我們從更高層次的概念上來思考問題。就像John Ruskin在1853年寫的,科學的工作就是將現實的現象進行抽象。

假如這些人能生活在我們這個時代,他們也許會同意以下觀點:科學就是我們瞭解透徹的知識,我們能夠把這些只是教授給計算機。如果我們沒瞭解到這個程度,那麼就還處在“藝術”的認知階段。算法或者計算機程序的概念,提供了一種可以測試我們對某一領域瞭解有多深的方法,從某種意義上說,從藝術到科學的過渡階段,也就是我們學習如何在這一領域實現自動化的階段。

人工智能已經取得了重大進步,但是在可預見的將來,計算機能做的事情,和普通人類還有着巨大的鴻溝。人類能夠語言,視聽甚至編程的奧祕仍未解開,所以某種意義上,我們所做只可稱之爲“藝術”。

從這個方面說,將計算機編程變成一門科學是可行的,而且從演講開頭的地方我引用的那段評論起,已經過去了十五年,我們走了很長一段路。十五年之前,我們對編程瞭解的還很少,甚至不知道如何證明一段程序是正確的——直到程序正常運行之前,我們都是在盲目地嘗試。只有在近幾年我們才明白計算機處理的抽象過程。儘管只有很少的程序能夠嚴謹地被證明正確性,這些理解還是帶給了我們很多好處。重點是,我們今天在寫程序的時候,我們知道,如果想要證明程序的正確性,是可能的。比起以前寫程序,現在要可靠的多。

“自動化編程”是人工智能方面一個很火的分支。其倡導者或許會做這樣的演講:“將編程視作手工藝品(編程是很久之前的歷史文物了)”。因爲他們的目標是製造可以自動化編程的機器,代碼寫的比人類好,只要給出特定問題,就可以生成程序。個人來說,我這個目標是不可能的,但並不是說這個課題不重要,因爲我們做的每件事都可以提高我們的“藝術技巧”,從這方面說,我們要力爭將藝術的方方面面都轉爲科學:在這個過程中,我們不斷推動着藝術的發展。

科學和藝術

從上面我們的討論來看,計算機程序可以看做是藝術和科學,二者相輔相成。但是顯然,很多人不管他們的領域是什麼,都會得出這樣的結論。我看過一本寫於1893年的初級攝影的書,開篇說:“攝影的發展既是一門科學,又是一門藝術。”事實上,當我翻開字典查“藝術”和“科學”的時候,就看見字典的序言上寫着,編著字典既是一門科學,又是一門藝術。數據和單詞的整理歸類是嚴謹的科學,而斟酌字句和定義則是一門藝術。科學失去了藝術也就失去了作用,藝術沒有了科學則缺乏準確性。

準備演講的時候,我在斯坦福圖書館的目錄裏面看別人都是怎麼在書名裏用“藝術”和“科學”的。結果相當有趣。

比如,我找到幾本這樣的書:《鋼琴彈奏的藝術》、《鋼琴演奏技巧的科學》、《鋼琴練習的科學》,還有一本是《鋼琴彈奏藝術:一種科學的方法》。

還有一個比較有才的標題是《數學的高雅藝術》,至少我覺得計算機編程算不上是“高雅藝術”。幾年之前,我看過一本叫做《計算的藝術》的書,1879年在舊金山出版,作者是C. Frusher Howard。這本書是將使用的商業計算的,1890年之前,賣出了40萬冊。序言中作者的理論和我的截然不同,他說:“數字計算的科學並不重要,但是認知的藝術技巧不可或缺。”

還有一些書同時用了科學和藝術兩個詞,例如Maharishi Mahesh Yogi 的本體科學和生活的藝術。還有一本叫做“科學探索的藝術”,討論的是科學如何做出重大探索發現的。

從上面可以看出,藝術可以有如此多的含義。但說實話,我在取書名的時候,並沒有特意地去考慮這些。有一本很有意思的書,Robert E. Mueller的《藝術的科學》,所表達的意思最接近我今天的主題。他說:“曾經有人認爲,搞藝術的絲毫不懂邏輯,而搞科學的在藝術方面就是呆瓜。”他解釋了綜合藝術和科學所帶來的收穫。

科學的方法是關乎語言邏輯,系統條理,客觀,冷靜,理性。而藝術關乎審美,創造,主管,激情,不合邏輯。對我而言,兩者在編程方面都有價值。

Emma Lehmer在1956年寫道,她覺得編程是“一門令人激動的科學,又是一門迷人的藝術。”H.S.M. Coxeter 在1957年寫道,他感覺自己更像一個藝術家而不是科學家。同時,C.P. Snow也在反對兩極分化,聲稱如果我們如果想做出真正的進步,就必須將科學和藝術相結合。

藝術的工作

我聽長演講的時候,一個小時左右注意力就開始不集中了。所以現在大家是不是也有點累了?不過希望接下來大家集中注意力,因爲這是我最深入的部分了。

當我談到計算機程序是一種藝術的時候,我說的是一種藝術形式,一種感官的審美。作爲教育工作者和作者,我的工作就是幫助人們學習如何編寫優美的程序。鑑於這個原因,最近我得知我的書被康奈爾大學放在美術圖書館的時候格外高興。(顯然,不會有人到這裏翻這本書,八成是圖書館管理員因爲署名弄錯了吧。)

我認爲,當我們寫程序的時候,就好像在寫詩或者譜曲,如Andrei Ershov所說,編程可以給我們理性和感性的雙重享受,因爲它的目標就是控制複雜的東西,用不同的規則建立龐大的系統。

還有,當我們讀別人的程序的時候,就如欣賞藝術品一般來理解它們。我仍然記得1958年在SOAP II上讀彙編代碼的感覺。可能這聽起來有點瘋狂,但是我很好奇如此龐大的程序是怎樣的。手寫漂亮的代碼是完全可能的,即使是用彙編語言。這就是我涉足計算機程序的原因。

有些代碼很優雅,有些很精妙,有些則閃耀着智慧。我認爲,寫出宏偉、壯麗、高雅的代碼就是一種藝術。

口味和風格

編程的風格在近幾年成了熱門的話題,推薦讀一下Kernighan和Plauger的《編程格調》。需要強調的是,沒有什麼最好的“風格”,每個人都有自己的喜好,強迫別人適應一種風格是錯誤的。我們經常聽說:“我不懂藝術,但是我知道自己喜歡什麼。”重點是,你要喜歡自己所採用的風格,那應該是你表達自己的最好的方式。

Edsger Dijkstra在他的《計算機程序設計藝術導論》的序言中說:

我的目的是讓人們認識到編碼風格的重要性,但是特定的風格僅僅只能讓人意識到風格化的好處。就像教授譜曲的老師,老師不會去教學生如何譜寫特定風格的曲子,而是教他們如何挖掘自己的風格,表達自己。

現在,必須來談談什麼是好的風格,什麼是壞的。我們不能用死板的眼光來評判別人的工作,19世紀的哲學家Jeremy Bentham是這樣說的:

評判風格和口味就是把自己放在了全人類的領袖的位置上,其實能影響的只有自己的風格而已。沒有什麼是最好的,除非你的工作是滿足僱主的需求;沒有什麼是最壞的,除非你在故意惡作劇。

當你按照自己的喜好糾正別人的風格的時候,可能從潛意識裏干涉了別人的權益。這就是我一般不去反對大多數程序員的原因。重要的是,他們在創造他們認爲美的東西。

Bentham提出了一個關於審美的很好的建議——“實用性”。我們有選擇風格的自由,但是如果能在符合我們自己的審美的同時,別人用起來又很方便,就更好了。我承認我很享受編程,但是更享受寫性能良好的程序。

當然,評價一個程序是不是好的方面也有很多。首先,程序能夠正確肯定是好的。其次,如果程序修改起來簡單,能夠自如應對以後的需求改變就更好了。如果在保證這兩點的同時,程序又具備可讀性,就完美了。

產品型的程序還有一個重要的地方——與用戶的交互性,特別是處理用戶輸入數據的錯誤時。組織有意義的錯誤信息和引導減少錯誤的設計的確是一門藝術。

另一個重要的方面是程序運行時候的性能和佔用的資源。但是現在很多人在譴責關注程序性能,稱這得不償失。現在的計算機進步了,不需要在乎那點性能。而過去的程序員因爲過度關注性能, 寫的代碼極其複雜,導致以後維護和debug的時候非常困難,不足以彌補性能所帶來的優點。

真正的原因是,程序員在錯誤的時間和錯誤的地方過度關注了性能。過早做優化是罪惡之源。

我們不能反對勞動,提倡懶惰,既不能疏於優化,也不能迷失在斤斤計較的時間和內存中。當我們買一輛車的時候,可能對50塊或100塊不怎麼在乎,但是在商店買東西的時候,對幾毛錢都會斤斤計較。我觀點是,考慮性能要考慮時機和地點。在我的結構化編程的論文中詳細討論了這個問題。

更少性能,更多快樂

我發現,當我們用有限的工具完成了事情的時候,所獲得預約會更多。例如,我曾經寫過的一個非常自豪的編譯器,僅僅使用了4096個字,每個字16比特。在限制之下做事情會讓人有記憶超羣的感覺。

同樣的道理適用於很多場合。比如,比起加長型林肯,人們更愛他們的大衆汽車。當我學習編程的時候,那還是一種消遣,程序是寫在打孔紙帶的上的,那時候大家在比誰用的紙帶更短。現在我們教授編程的時候,如果不讓學生在計算機上親手實驗的話,就很難激發他們的學習熱情。大規模計算機以及他們的操作系統和編程語言很難從一開始就引起他們對編程的熱愛。

如何將這些準則用於提高程序員工作上的預約比較模糊。如果經理突然宣佈,新的機器內存只有之前的一半,肯定所有的程序員都會抱怨。任何人,即使是非常熱愛編程的人,都不會願意損失不必要的性能。一個很好的例子是,很多電影製片人在1920年的時候抵制有聲電影,因爲他們很自豪沒有聲音也能很好地傳達電影的意思。相同的,可能有程序員也抵制性能更好的機器。今天機器性能的進步可能多少毀了一些代碼的優雅性,但是卻沒有人願意回到默片時代,不是因爲懶,而是因爲他們知道利用先進的科技,製作多彩的電影是可能的。藝術的形式改變了,但是供藝術家發揮的空間依然很多。

那麼他們是如何提高自己的技術的?多年來,最好的製片人往往生活在電影工業不是很發達的國家,在藝術方面有很多限制。近年來,對編程事業推動較大的人都不是有很多機會接觸大型計算機的人。這個故事告訴我們,應該在教育中限制資源,當我們認爲設限,纔會被迫將自己的能力超這個限制進步。我們不能永遠生活在奢華的環境中,那會讓我們喪失激情。竭盡所有的資源來解決問題會給我們磨練,當面對真正的問題時才能遊刃有餘。而且在限制下解決問題也會帶來更多快樂。

同樣都是藝術家,我們沒必要因爲有趣去做一些事感到有負罪感。我迷上編程就是因爲一個解決素數問題的ALGOL程序,而不是產品化的東西。以前我有一個斯坦福的學生,發現了最短的可以打印出程序本身的源代碼的FORTRAN程序而激動不已。我並不認爲研究這種問題是一種浪費,上面提到的強調“實用性”的Bentham也不反對,他說“相反,這其中的實用性是無可爭議的,快樂的源泉不就是最大的實用性嗎?”

提供優美的工具

現代藝術還強調的一個方面是創造性。現今大多數藝術家都期望創造出美麗的東西,只有有創新性的想法才有價值。我不是說程序在這方面完全一樣,只是這帶給了我一方面的靈感。有時候我們會被分配一些很枯燥的工作,甚至幾乎是不可能完成的,沒有絲毫創造性。這時候有人可能會說:“編程還是美妙的嗎?你沒有壓力,可以隨便寫優雅的代碼,可以這樣說。像我一樣要處理這些東西,還能說編程是藝術嗎?”

的確,不是所有的編程工作都是有趣的。比如家庭主婦,每天要一遍又一遍地打掃相同的地方,這種工作沒有創造性。但是即使在這種情況下, 依然可以有樂趣:如果我們有漂亮的同居,那麼即使是例行工作,也會有趣的多。想象一下,如果桌子是精心設計過的,非常漂亮,那麼每天去擦也不會枯燥。

我想要呼籲所有設計系統和機器給我們用的系統工程師和計算機工程師們,求你們給我們方便的工具,尤其是那些常用的,而不要我們每天跟它們做鬥爭。請給我們有動力寫出好代碼的工具,讓我們在編程中享受更多快樂。

對我來說,讓大學新生接受“編程很有趣”的觀點多少有些困難,因爲一開始我就要教他們“xxxx任務等於這樣這樣和這樣”,即使批處理語言可以設計的方便易用,而不是像現在這樣這麼死板。

硬件工程師可以將機器設計地更加易用,例如提供符合數學規律的浮點運算。現在機器上的運算讓調試和分析異常困難,但是設計良好的運算可以鼓勵數字分析源提供更好的子運算,具備更高的精度。

軟件工程師可以做什麼呢?一個絕佳的方式是,給系統用戶提供可以交互的進程管理程序。系統不應該過度自動化,不能讓太多的動作在後臺默默進行,應該讓程序員可以監視進程的運行。有些任務可以讓系統自動完成,有些則應該讓程序員手動操作。如何在兩者之間取捨?這就是一個優秀的操作系統應該權衡的事情了。

程序度量工具也是一個重要的方面。多年來,程序員對自己程序的性能和開銷大多估計有誤。那時工具及其有限,也難怪性能總會和預期出入很大。這種工作就像是,新婚夫婦在不知道柴米油鹽價格的情況下,做家庭開支預算一樣。程序員所有的就是一個優化編譯器,而且它的細節也不得而知。幸運的事,我們現在有了系統的監控工具,能實時反映程序指令和開銷。這種系統已經取得了巨大的進步,不僅僅因爲度量工具的成果,還因爲使用起來非常方便。我相信不就的將來,普及只是時間問題。

衆所周知,編程語言對風格的影響很多。所以語言設計者也有義務將程序語言超鼓勵良好風格的方向發展。現在的語言在程序和數據結構方面的表現都不盡如人意,所以我很期待接下來紀念語言設計的發展。

總結

我們將編程視作藝術,是因爲它需要知識的積累,需要技巧和才智,更因爲它創造美的東西。將自己當做藝術家的程序員,在工作中能享受到更多的快樂,也會更加出色。我期待能在將來的計算機大會看到人們用這樣的標題:藝術的現狀。


這是Donald E. Knuth的Turing Award Lecture演講,原文發表於1974年《ACM通訊》,譯者賴信濤。

發佈了70 篇原創文章 · 獲贊 8 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章