當前位置:
首頁 > 科技 > 一個程序員的審美情感

一個程序員的審美情感

作者|賈彥民

編輯|小智

周末聊些輕鬆的話題,身為程序員的你,是怎麼看待「美」的?代碼美不美?架構美不美?什麼樣的美才是技術的美?歡迎留言討論。

寫在前面

我們大概都閱讀過或聽說過類似於編程之美或架構之美或數學之美的著作,那麼,代碼到底美不美呢?如果是美的,是怎樣的美呢?又該怎樣理解和欣賞這種美呢?不妨把問題向美學或藝術的稍深層次的內涵稍稍推進一步,姑且把程序員視為藝術家,那麼,代碼有可能作為他們審美情感 (Aesthetic Emotion) 的對象嗎?程序員可以像藝術家那樣工作嗎?

如果這一切都是否定的,那麼,Donald E. Knuth 的煌煌巨著又何以稱為計算機程序設計藝術 (The Art of Computer Programming) 呢?這些問題涉及到藝術和技術的關聯,都是很大的問題,以我對藝術的粗淺認識以及對程序的有限了解,既不敢也不能給出確定的答案,這裡只是談談自己閱讀的感受和體會。

何謂藝術?

從產出的作品和結果的表面形式來看,代碼和藝術作品的相似性也許無從談起。從創作或創造的過程來看,程序和藝術,程序員和藝術家的差別似乎並沒有想像中那麼大。有關藝術的最經典的和最古典的理論莫過於 Clive Bell 在他的著作《藝術》(Art) 中提出的假說,即可視藝術如繪畫的本質屬性是有意味的形式 (Significant Form)。所謂形式即顏色和線條的組合與關係,之所以有意味,是因為在作品的形式中注入了藝術家的情感。對藝術作品敏感的人,正是因為發現了藝術作品中的有意味的形式,激發了和藝術家共鳴的情感,才被深深打動。這一假說被譽為最令人滿意的現代藝術理論,所以,我們假設它是合理的,真實的,可信的。

那麼,按照這種理論,在構思作品時,藝術家是怎樣獲得要表達的情感呢?有意味形式的靈感火花又是從哪裡來的呢?比較客觀的回答是八仙過海,各顯神通,不能一概而論。但是不可否認,確實有這樣的藝術家,他們基於客觀的物質對象或想像的虛擬對象的形式的理解和體驗,在電光石火的剎那靈光乍現,茅塞頓開。他們的訣竅和天賦在於觀察物質世界和構想虛擬世界時,統統地把所有的對象看作純粹的形式,即線條,顏色,和形狀,以及它們的關係,而完全忽略對象的功利性的標籤。

比如房間中有一把椅子,普通人首先給這東西貼上椅子的標籤,然後想到的是它的世俗的功用,可以坐在上面讀書,吃飯,聊天。當然,調皮的熊孩子們對椅子使用的想像力就更不用說了。若考慮地更遠一點,也許還會聯想到座次名位,如水滸中的頭把交椅,聚義廳,忠義堂,替天行道,朝廷招安等等。而富於天賦的藝術家僅僅忘情於椅子的純粹的形式, 而椅子是什麼,叫什麼和用做什麼根本不在於藝術家的思維光譜中。

從美學角度上看,只有純粹的形式才能揭示出物質的本質屬性和終極現實 (Ultimate Reality),用一個形而上學的術語,即物自體 (The Thing in Itself )。物質的本質屬性和終極現實不就是哲學家孜孜不倦地追求和探索的終極目標和終極真理嗎?這豈止是有意味啊,物質對象經由純粹的形式升華到形而上學的終極真理,恐怕世上再沒有比這更偉大更有意義的事業了。無論是藝術家還是鑒賞藝術的觀眾,偉大的藝術作品象紐帶一樣牽引著世俗的我們去體驗美學的出世的終極真理和終極現實,心中的情感和快感像火山一樣激烈澎湃,情不自禁,難以自己。

程序員是怎樣看的?

回過頭來,看看程序員是怎樣觀察物質世界的。從面向對象的角度分析,我們把給定的問題域或應用域內的所有的一切都看作對象和對象之間的關係。對象中包括成員變數和方法,繼承、組合和關聯是對象之間最普遍的關係。對象和對象的關係也是面向對象的編程語言所能處理的全部。所以,需求可以千變萬化,萬變不離其宗,把需求描述的問題域或應用域抽象成對象和對象的關係,是以不變應萬變的唯一的解決之道。因此,反過來講,面向對象的方法為程序員提供了一種觀察世界,或更具體地講,描述應用域和問題域的抽象框架。

那麼,程序員是怎樣做到把問題域或應用域抽象為對象和對象的關係的呢?較為客觀的回答是八仙過海,各顯神通,不能一概而論。並沒有確定的,機械的,可操作的流程把需求轉換成對象和對象的關係。否則,一旦這一轉換過程掉入邱奇圖靈論題可計算的範疇,程序員的工作馬上就可以被機器取而代之了。某些程序員在某些項目上做的好一點,某些程序員在某些項目上做的差一點,還有些所謂的程序員在所有項目上都做的一團糟。這種不確定性不就是程序創作的藝術性嗎?

在面向對象的課程里確實提到了一種簡單的方法:假設給定一段描述需求的文本,把其中的名詞當作備選的對象,把其中的動詞當作對象包含的方法,把形容詞當作對象可能的屬性即成員變數。事實證明,沒有程序員可以嚴格按照這種方法得到應用域或問題域的抽象對象模型。因為,需求的文本常常是模糊的,似是而非的。你若當真,那就傻了。

可能有人會說,對象建模更像是軟體架構師的工作,關程序員何事?從抽象的角度看,程序員和架構師在解決問題時毫無疑問都會用到同樣的抽象思維方法,即他們都是具有抽象思維能力的軟體工程師,若再做進一步的抽象,大概沒有人反對,在軟體這個行業,研發一線的程序員 (開發工程師)、測試工程師、架構師和項目經理都是會用腦子解決問題的人。如果你像程序員一樣工作,你就是程序員;如果你像架構師一樣工作,你就是架構師;軟體工程師角色的界限是模糊的,不能也沒必要分的清清楚楚。我不知道是否有完全不會寫代碼的架構師,但很少有程序員承認自己不懂架構和設計。

因此,到目前為止,我們可以發現,藝術家和程序員的思維方式起碼有一點是相同的,即抽象。藝術家把物質世界和想像的虛擬世界抽象到形而上學的哲學高度,因此,藝術是普適的,永恆的。而程序員只要把問題域和應用域抽象為對象和對象的關係,進而轉換為代碼。抽象的高度決定了抽象的難度,優秀的程序員雖是稀缺資源,但並不鮮見,而偉大的藝術家,絕對都是不世出的天才。這就不難解釋:雖然計算機擊敗了國際象棋和圍棋的人類頂尖高手,引起了人工智慧可能代替或超越人類的憂慮;但人工智慧在藝術領域卻毫無作為,最多就是拙笨的模仿而已。

其實,就算是下棋,計算機使用的模型和人類使用的模型也是完全不一樣的。當前布局到分出勝負的終局經過成千上萬個中間布局存在無數條路徑,組成一棵龐大的樹,終局是樹的葉子節點。因此可能的路徑的數目相對於路徑的長度是指數級的。計算機判斷當前布局的優劣的依據是該布局導致最終勝局的概率,可以簡單地看作是當前布局到勝局的路徑的數目和到所有終局的路徑的數目的比例。

我猜,AlphaGo 的深度學習演算法可以多快好省的得到每個棋局的更準確的取勝的概率。不管怎樣,在下棋方面,計算機比人類高明強大的地方是海量的存儲和快速的查找。而人類下棋使用的是更高層次的模型,我對圍棋一竅不通,用 google 搜索了一下,圍棋表示下法的術語至少有幾十個如擋、並、頂、爬、沖、打劫、點眼、鬼手等等,沒有一個和數字相關。

我們完全不必為人類敗於計算機而作杞人之憂,這和我們跑不過汽車飛不過飛機跳不過袋鼠本質上還是一個道理,計算機還沒有聰明到像人類那樣下棋。人類若像計算機那樣下棋大概會是這樣:對於當前的布局,符合規則的落子有 168 種,其中第 88 種下在「平位二八路」導致的新的布局的取勝概率是 18.68%,大於其他 167 種下法,因此,採用第 88 種下法。這樣的基於冷冰冰的數字的弈棋,沒有任何不確定性,比拼的只是記憶力,看誰記得多,記得准,還有什麼樂趣可言呢?

簡化與抽象

悟性和靈感這些只有人類才有的智慧,另外,還有不可或缺的好運氣。不乏這樣的藝術作品,他們的抽象的形式到了太高的境界,遠遠超越了時代的理解能力,經過了漫長的歲月世人才最終認識到他們的價值。而此時,創造他們的藝術家早已在窮困潦倒中鬱郁地作了古人,比如梵高。

幸運的是,程序員不是什麼「聖賢」,大可不必有這樣的擔憂。程序員在做軟體的設計和架構時,建立面向對象的抽象模型的目的是為了去除需求中與問題域和應用域無關的東西,抓住問題的本質,便於理解,從而更容易寫出高質量的代碼。另外,更重要的是,對象模型無論多麼抽象,最後要落地變成可運行的二進位程序,成功與否由用戶體驗說了算。所以,程序員最終的勞動成果是功利的,世俗的,可理解的,可驗證的。而藝術作品是主觀的,精神層面的,其價值是無法用邏輯證明的。

無論是藝術家還是程序員,都不是為了抽象而抽象,也不是為了故作高深而抽象,抽象是為了簡化,把問題弄的更簡單。Clive Bell 在《Art》中寫道:

「To instance simplification as a peculiarity of the art of any particular age seems queer, since simplification is essential to all art. Without it art cannot exist; for art is the creation of significant form, and simplification is the liberating of what is significant from what is not.」

可見,簡化是一切藝術的不二法門。藝術是通過有意味的形式來傳遞超越語言的表達能力和表達範疇的信息,只可意會,不可言傳。因此,只有那些和有意味的形式相關的細節才值得保留。而所有可用語言描述的內容都是無關的,必須刪去。

Apple 公司的產品向來以藝術性的設計著稱於世。而 Apple 公司奉之若圭臬的設計理念就是簡單,力求做到無論是老婦還是稚童皆能很容易的理解和使用 Apple 的產品。在 Apple 公司早期的宣傳手冊中就明確寫道:

「Simplicity is the ultimate sophistication.」

簡單的設計必須讓產品的外形體現出產品的本質,其他一切皆是多餘,為此,必須謹慎的用心處理每一處細節。比如手機的顯示器是呈現信息的介質,要在有限的空間盡量最大可能地增加它的面積。強調簡單和注重細節現在變成了一切互聯網公司產品設計的座右銘。

找到問題的最直接有效的解決方案就是程序員可以創造的簡單。在這方面,編程語言的設計是個典型的例子。一般地,編程語言設計的重心是定義數據和過程的最基本的表示,操作與組合,這構成了語言的基礎部分,不能也不會輕易改變。而語言的高層次的功能如各種應用程序庫都可以從這些基礎元素派生而來。數論和歐氏幾何都只有五條公理作為基礎,其他所有的定理可以從這五條公理中推導出來。類似地,一方面,我們希望編程語言的基礎元素越少越好,簡單且容易理解;另一方面,又必須要保證這些基礎元素足夠強大和靈活,能夠支撐起語言的其他部分以開發出有用的軟體功能。

處理這種簡單與強大的衝突的做法還是抽象,把貌似不一樣的東西看做一樣的東西。比如,scheme 是 lisp 的一種方言,它把過程當作數據,反過來,把數據當作過程。如果過程可以用變數命名,可以用作過程的參數,可以作為過程的結果返回,可以包含在數據結構中,那麼過程不就是數據嗎?過程抽象為數據,就可以像數據一樣被操作。我們引用 MIT 計算機教材《計算機程序的構造和解釋》(Harold Abelson, Gerald Jay Sussman, Julie Sussman 著,裘宗燕譯) 中的一個平凡的例子來說明過程怎樣象數據一樣被用作過程的參數:

map 根據傳遞給它的過程參數 proc,對錶 items 中的元素做不同的操作。比如,返回表中元素的平方:

結果是:(1 4 9 16)

對每個元素乘一個倍數:

結果是:(10 20 30 40)

proc 作為 map 的參數,建起了一道抽象屏障,把對表中元素的處理的過程從提取表的元素 (car) 和組裝處理的結果 (con) 的過程分離開來。這樣,我們就不需要針對不同的表處理寫不同的過程,而只要把對元素的處理過程如平方和倍乘作為參數傳遞給 map 即可。抽象把變的東西 (表中元素的處理) 和不變的東西 (提取表的元素和組裝處理後的結果) 分開來,不變的東西是可重用的,保證了一致性;變的東西是可定製的,提供了靈活性。

另外,schema 把數據看作是滿足一組約束條件的過程。如整數、有理數、實數和複數都支持加減乘除的算術操作,於是,把他們統統抽象為支持加減乘除過程的數。上層應用在對這些數做加減乘除的操作時,底層的實現會根據數的類型,調用不同的過程。這聽起來,其實就是面向對象編程語言的虛函數、純虛函數和抽象類這一系列概念的濫觴。

賦予過程一個抽象的名字,過程可以調用其他過程,也可以被其他過程調用。這樣,軟體就能夠實現為由下至上的不同層次,不同的層次使用不同級別的抽象語言。上層的過程調用下層的過程,只要下層提供的介面不變,即使實現改變了,也不會影響上層的功能。同樣的道理,軟體模塊化也是過程抽象的結果。毫無疑問,層次和模塊化是管理軟體複雜性基礎。

過程還可以調用自身,即為遞歸。自己調用自己,多少讓人感到不安。實際上,遞歸不僅僅是編程語言的功能,更為重要的是,遞歸是程序員特有的思維的工具和表達的方法,簡潔而優雅,許多著名的演算法都離不開遞歸,如回溯演算法,快速排序演算法,分而治之演算法,深度優先搜索演算法等。lisp 中大量使用遞歸,甚至用遞歸替代循環。

總而言之,lisp 是計算機最早的編程語言,歷經半個多世紀,依然枝深葉茂,長盛不衰。所憑藉的正是這些化繁為簡少即是多的抽象機制,數據即過程,過程即數據;表達式即語句;語句即表達式。

即使具有再好的技術的或藝術的抽象思維能力,程序員和藝術家都還是不可能漫無目的的憑空創造出好的作品。假設一個程序員的目標就是要創造最好的程序,假設一個藝術家的目標就是要創造最好的有意味的形式,最終都會一事無成。這就好像一個探險家要尋找寶藏,像任何人一樣,他當然知道,在地球的某個角落一定埋有寶藏,但是沒有任何線索和地圖指向藏寶之地,結果只能是滿世界遊盪,一無所獲。所以,藝術家以特定的主題作為審美情感的皈依,程序員以問題作為創造引擎的原始驅動力。

我想,每個真正的程序員的腦子裡面都有一大堆已解決的和要解決的問題,否則,作為程序員的價值豈不就讓人懷疑了。程序員在工作的時候,如果不是在解決問題,就是在製造問題,測試工程師就是幫助發現程序員不小心製造的問題。對於一個困難的問題,通往答案的每一步都可能存在多條路,即多個選項,有的路是顯而易見的,有的路是隱晦不明的,整個問題的解空間構成了一幅像迷宮一樣複雜的多邊有向圖。尋找問題的答案就像在迷宮中探險一樣,行路難!

聰明的程序員喜歡獵奇和發現,在迷霧重重中尋尋覓覓,從不吝惜自己的腦力和體力。解決問題的同時,享受著思考的快樂。與之相反,拙笨的程序員喜歡生活在熟悉的和舒適的安樂窩裡,最好每一步都事先由別人設定,最害怕的就是面對各種不確定,並為之承擔責任和風險。這樣的程序員只能做一些機械化的工作,不用動腦筋,安全舒適省心。但是,如果有一天,程序員的工作有可能被 AI 替代,他們就會首當其衝地被淘汰。所以,激勵程序員的最好的方式,就是不斷地給 TA 有價值的問題。

寫在最後

現在,可以回答本文開頭提出的問題了。代碼對於機器而言,當然談不到美,因為機器是機械的,沒有情感的。但多數時候,代碼是寫給人看的,這才可能存在美不美的問題。藝術家創造的美是有意味的形式,包括線條和顏色,以及他們的組合。

其實,如果把代碼看做一幅畫,代碼的結構或描述模塊和層次的關係就是它的線條或輪廓,代碼的模塊或層次就是它的顏色。藝術家通過純粹的形式,從美學的角度去探索形而上的終極真理和終極現實。同樣地,程序員藉助於抽象,去蕪存真,去繁就簡,找到問題的最直接有效的答案。

代碼的美在於以至簡克至繁,水銀瀉地般從程序員的思維中自然流出,清晰優雅的表達了問題的本質和答案。閱讀代碼的人象看地圖一樣,即能從大處概覽代碼的全貌,按圖索驥,也能找到每個層次的每個模塊的細節。那麼,這樣的代碼比之那些雖然實現了同樣的功能,卻混亂的象一堆麥秸的代碼,誰能說它不是美的呢? 藝術家的審美情感可以提升程序員的品味,高貴的品味不能容忍粗鄙不堪,觀之可厭的代碼。我們不一定總能寫出最美的代碼,但只要不放棄對美的追求,雖不能至,然心嚮往之,則近道矣。

今日薦文

點擊展開全文

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 InfoQ 的精彩文章:

如何成為機器學習工程師?
我曾以為我的意中人不會是程序員,直到有一天他背上了它
Facebook否認AI失控:忘記設置英語語法;開發者發起請求Adobe開源Flash;樂視雲視頻伺服器宕機
探秘SendCloud如何助力7W 用戶點郵成金
阿里如何實現高性能分散式強一致的獨立 Paxos 基礎庫?

TAG:InfoQ |

您可能感興趣

一個女程序員的編程之路
對不起,我的代碼評審毀了一個程序員!
小程序的兩種情緒
優秀的程序員和一般的程序員差別在哪?
做程序員的五年狀態
一個引發程序員們干架的問題
一個程序員開始優秀的 3 種跡象
哪本書是對程序員最有影響、每個程序員都該閱讀的書?
當你問一個程序員地址
編程地震!這個事情影響到@所有程序員!
編程地震!這個事情影響到所有程序員!
有哪些程序員的梗
一個程序員幹掉一家遊戲公司?程序員回應:編的,我沒那能力
趣圖:一個程序員被抓進了監獄
程序員們的腦迴路真的不一樣
不要做一個只會面向搜索編程的程序員!
程序員是一個怎樣神奇的職業?
程序員學習過程的幾個困惑?
編程超模小kk的晚間護膚秘訣分享,做一個能熬夜的最美程序員
一個程序員的「養生」桌面