消滅程式設計師需要百年嗎?

趙丹 Diana Zhao發表於2011-10-20

某天看到一篇博文,《一百年後,人類怎樣程式設計?》,只是這個題目,就勾起心中無限感慨。文章沒細看,內容大致是分析各種語言,以及其中各種語言現象,今後的發展趨勢。我對於語言的進步一直不感冒,對5年前就有很多人推崇的Ruby,至今也懶得抬眼皮看看,8年前被迫用過幾天Perl,我就斷定這是最糟糕的程式語言之一,因為它標榜自由,卻又沒法真正自由。時至今日,我仍然只用C++,C#,Java這三種語言,如果SQL也算的話就是四種。對於達到一定程度的程式設計師而言,語言已經不重要了,不管做什麼功能或者什麼平臺,只要不是初次上手,都應該有50%以上的程式碼可以自動生成出來,另外利用開原始碼和商業化構件完成30%以上的工作,真正需要自己手工編寫的部分絕對不應超過20%。不論是自動生成的程式碼,還是開原始碼或構件,最大程度的可理解性和通用性是首要追求的目標,因此最通用的,和使用人數最多的語言才是最好的語言。語言的進步對於提高程式設計效率確有一定幫助,我自己也深有體會,六年前我做C#專案的時候不得不自己寫了對IList進行查詢的功能,兩年之後,LINQ成了語言自帶的標準功能,後來的程式設計師顯然可以節省開發這個功能的時間。但是,語言帶來的效率提升,遠遠不如思考方式變化引起的程式設計效率飛躍來得大。

從第一天程式設計開始,我就不喜歡這個工作,看到同事飛快地打鍵盤,螢幕不停地吐出一行行程式,覺得這件事實在傻透了,她編的是FOXPRO,又是一種我很看不起的語言。她編的功能,無非就是橫豎畫上幾根表格線,然後把一些數字和文字填到正確的格子裡去,這就是公司裡的程式設計高手所做的事情。我曾經驚訝於這麼傻的事情竟然真的需要人來做,可是如果不用人做,又能怎樣呢?那時幸虧我利用一點小聰明,在還沒有開始從事這種傻工作的時候,就改去研究解密演算法了,後來又混上了設計師,小經理,總算沒有傻掉,那時心裡不免暗自得意和慶幸。

2000年,有幸目睹了一位當時國內最牛程式設計師的一次程式設計作業,從此徹底顛覆了我的想法。先說說牛人的業績,一個工作日,基本沒加班,完成一個複雜C/S軟體的伺服器端,用統計小工具數數程式碼,三萬多行。這個軟體經過簡單的測試,第二天就上線實際執行了,每天數千人訪問,沒出過大問題。再說開發過程,開發環境是VS6.0,牛人很少動滑鼠,大概嫌耽誤時間,各種快捷鍵運用,讓人眼花繚亂,程式基本上不是寫出來的,而是貼上過來,重新排列組合一番,再敲上幾個語句補充修正一下,就算大功告成。搞定一個程式塊的時間,基本上跟一般人寫一條語句的時間差不多。整個工作過程中,看不出明顯用於思考的時間,只要不離開座位,鍵盤的聲音就一直連續不停。我想牛人之所以牛,關鍵就在這裡,像運用語句一樣運用語句塊,程式不是寫出來的,而是裝配起來的,就產生了如同手工組裝勞斯萊斯與模組化裝配豐田之間的巨大生產率差異。我那時和牛人不在同一層辦公,平時很少機會接觸,又一次在樓下食堂吃飯正好坐鄰桌,聽到牛人講起一件往事,牛人多年來,不論在哪裡工作,都要帶一塊自己的硬碟,裡面有幾GB以往做的程式--他的 code base ,有一次這個硬碟突然卡殼了,牛人就跟老婆說,我們們準備回老家改行幹別的吧,結果沒過太久,那個硬碟自己又恢復了,所以牛人終於沒有回老家去。可見,如果沒有 code base ,牛人立刻就不牛了。後來我又見過不少優秀程式設計師,使用自己的 code base 裝配出一個個巨大複雜的程式,這種做法侷限性也很明顯,自己的 code base 終究有限,總有不夠用的時候。既然如此,利用別人的 code base 不就解決問題了嗎?理論上是這樣,但現實中卻完全不是這麼回事,我很少見到大量利用別人 code base 的程式設計高手,倒不是這些高手清高,而是他們常常覺得與其看懂人家的程式,還不如自己寫來得快,節省一點打字的時間,就要為了適應別人的思路花更多時間思考,得不償失。可以說,到了這個程度,code base 的大小基本上決定了水平的高低,頂級的牛人都有上百萬乃至數百萬行規模的code base ,俺到今天才攢了50萬左右,離牛人們還差得很遠。按照這個道理,只要時間足夠長,總會有一些牛人可以積攢一個足夠大的 code base ,窮盡當代人類能夠想象到的所有程式,這個時候就沒有編寫,只有裝配了。如果軟體由編寫變成裝配,那麼接下來一個自然的發展就是裝配也要自動化,2000年的時候,程式碼自動生成工具還不發達,到2005年,基於模板的程式碼生成工具已經遍地開花了。然而這一切似乎只是歷史的重複,模板語言似乎變成了又一種高階語言,仍然需要人工編寫,導致牛人們的 code base 當中又多了一些這種模板而已。而且也總有一些例外情況,用模板做起來複雜無比,還不如干脆留著手工完成。

計算機是否可以自己組裝程式呢?現在看來,似乎已經很接近了,至少從UML生成程式碼框架已經很成熟了,而框架裡面需要填入的東西,正是 code base 的內容。現在缺少的,只是找到正確的程式碼塊,作一些必要的修正,填入框架中正確的地方的問題。如果 code base 中所有的程式碼塊都有正確的形式化描述,程式碼框架的每一處地方也都有這樣的形式化描述,把二者做一個匹配不就完成了裝配工作了嗎?至於需要必要的修改的地方,通常用編譯器檢查就能找到。如果真是這樣,那麼這件事早就成功了,像IBM這樣的公司,一直就想做成這件事,而且他們並不乏完成這些工作所需的任何資源。

然而,時至今日,軟體開發不管怎麼自動化,總是有一些例外,需要程式設計師去手工處理。這些例外情況,通常無關乎高精尖,而是些很普通的問題。在八年以前,我還沒有接觸知識表示和人工智慧的時候,這個問題一直在腦中揮之不去。2003年,偶然接觸到cyc專案,這又一次徹底顛覆了我的想法,因為這個cyc剛好能作一些看起來很簡單,卻又非要人工才能處理的事情,而且這些事情並不像看上去那麼簡單,一個簡單的推理常常要呼叫成千上萬條斷言。當然cyc並不是一個真正的常識處理系統,它固然是十餘年積累的成果,也有很多閃光的思想,但是侷限性也很明顯。不管怎樣,它為我開啟了一個全新的視野。人工智慧是個很大的領域,其中有很多天才的創見,要理解它的全部內涵,是件艱鉅漫長的工作。然而,有一件事情從開始的時候就能得出結論,那就是,如果計算機真的具有了與人類相當的智慧,那麼必然就不再需要人來為它程式設計序,那個時候,就是程式設計師這個職業壽終正寢的時候,當然,整個軟體產業也將不復存在。所以,程式設計師以及軟體產業的生存,其實就寄託於那些為數越來越少的,必須人來處理的“例外”情況。

我們現在就來關注這些例外情況,因為它們是如此重要,將會決定各位以及產業的命運。

軟體是什麼呢?計算機發展的早期歷史上是沒有軟體的概念的,那時候只有程式,每個使用者就是他自己的程式設計師,編寫程式滿足他自己的需求。這個時候的程式設計師,不需要需求調研,不需要劃分工作階段,總之一句話,想怎麼幹就怎麼幹,他們也不會考慮複用,因為程式只是他們個人想法的表達,沒有想法的時候想也沒用,一旦有了想法,兩下就寫出來了,即使需要借鑑以前的想法,從腦子裡調出來比從故紙堆翻出來也快捷得多。也許軟體與程式的不同就在於此,軟體是做給別人用的,程式是寫給自己用的。軟體是伴隨著不會程式設計的“業餘”使用者的產生而出現的。開發軟體與寫程式第一個不同的地方就是要做需求調研,不管做多簡單的軟體,都要調研。有的時候,程式設計師看似沒有做,其實是他和使用者已經很熟悉,使用者的需求早已經都記在腦子裡了。使用者有需求就表明使用者有一些需要計算的問題,這些問題可以由計算機做,當然也可以由人來做,事實上computer最早指的是拿著紙筆或者計算尺工作的計算員們。如果由人來完成計算,使用者通常需要告訴計算員計算的公式和流程,然後提供初始資料,如果這位計算員經驗豐富的話,有時候不必如此羅嗦,只需要告訴他算什麼題目就可以了,計算員自己知道公式和流程,或者即使當時不知道,也可以自己找資料學習。使用計算機就享受不到如此的便利了,計算機不會自己學習查資料,即使硬碟裡存有以往的計算程式,它也不會自己去使用,一定要人手工調出來執行。人與計算機的根本差別不在於處理資訊的能力,而在於處理資訊的主觀能動性。

自從引入了客戶,引入了需求,軟體開發開始變得複雜了,最早的客戶還比較好應付,他們都是懂一些計算機技術的人,那時候完全不懂的人根本不會想到用計算機做事情。最初的需求都很具體,輸入什麼,做哪種計算,結果怎麼輸出,都講得清清楚楚,所以最初搞需求分析的人都畫資料流圖,只要資料流清楚了,軟體就確定了,今天的程式設計師就沒這麼幸運了,工作流程、訪問許可權、使用者體驗等等,撞得滿頭都是包,如果光盯著資料流圖的話,什麼也做不出來。那時候的分析員和設計師基本上是同一個人,因為沒有什麼好設計的,就是把功能分解一下,列張表1234寫出來,再往後稍微複雜一些,所謂結構化方法,也就是功能多了一些,列表不好使改用層次樹。今天的設計師,最慘的時候UML14種圖全都畫遍,可能也還有沒描述清楚的地方。

軟體出現之後,因為商業的驅動,很快就泡沫一般膨脹起來,各位今天目睹了各種泡沫之後,大概會總結出來一條規律,凡是泡沫一定沒有好結果。軟體一旦開始膨脹,所需的人工自然不斷地加倍,於是以IBM為代表(IBM確實養了不少傑出的科學家,但是養了更多豬頭,當科學家和豬頭一起研究問題的時候,通常豬頭不會變成科學家,而科學家卻會變成豬頭),採用了工業時代提高效率的不二法則--增加人手,擴大規模,精細分工,流水作業,至於結果嘛,各位學過軟體工程第一課的話,恐怕就知道他們的事蹟了。

扯IBM的糗事看似和我們的主題沒多少關係,其實當中有著深刻的聯絡。我們前面所說的那些可以自動處理的部分,他們用人工都做得很完美,而在那些例外的地方,卻幾乎無例外地犯錯誤。那麼,裡外到底是什麼呢?為何總是揮之不去呢?要解決這個問題,我們就需要從更深層次挖掘軟體的本質。不管怎麼說,軟體的核心功能就是計算,那麼計算是什麼呢?今天網際網路上充斥著各種各樣的計算,僅僅用數學來概括是不足以涵蓋其外延的。在數字系統之外,也存在各種各樣的計算,比如模擬計算機的計算,軍事上的兵棋推演,商業上的決策方法等等。如果要概括所有這些計算共同的特徵,就只有三點:第一,都有一組初始的資料,代表著某個現實的或者抽象的系統在某一時刻的狀態;第二,都有一組理論或者公式(或者二者兼具),規定了各個資料如何相互作用;第三,經過計算的過程,最終都得到另一組資料,描述系統在另一時刻可能的狀態。如果把第一、第二兩條中的要素加在一起,稱之為一個模型的話,計算就相當於模型的一次推演。模型推演是人腦最基本的思維方法,人類發明計算機來分擔思考的負擔,因此計算機當然必須能夠擔負這樣的計算工作。然而計算機並不懂得什麼是模型,只是一個執行程式的機器,因此必須由人來將模型程式化,軟體簡單地說就是程式化了的模型。物件導向的方法其實就是一種模型表示法,而近年更有人提出模型驅動的開發,這都與軟體的模型性質密不可分。

僅僅認識到軟體具有模型的性質還不夠,首先,模型本身是複雜的,雖然所有的模型都可以用一組規律加一組資料來概括,但是實際做過系統的人,特別是做行業系統的人都知道,行業知識本身就是複雜的,相互之間常常有說不清道不明的關係,如果不是自己真正理解了這些知識,僅僅以書本和專家言語為基礎,做一些表面(形式化)的推理,是幾乎一定會出錯的。其次,初始資料也不是簡單的,今天的系統,資料來源多種多樣,精度、可信度各不相同,非結構化的資料常常見到,單是把這些資料轉換到適合模型推演的形式,就要費九牛二虎之力。第三,模型程式碼化本身也不是件輕鬆的工作,今天的計算環境空前複雜,各種平臺,各種支撐系統都要考慮,今天的架構師要掌握的知識比以往任何時候都多。最後,軟體雖然以模型為核心,但絕不僅僅是模型,為了讓模型進行有用的工作,各種輔助系統也必不可少。

輔助系統相對獨立,我們先從這裡說起。軟體中最重要的輔助系統就是人機介面,人機介面到底有多重要,看看微軟如何發家,以及今天微軟Google為什麼打破頭就知道了,只要真正的人工智慧還沒有實現,人機介面就是最有利可圖的領域。然而剛入行的程式設計師通常都不理解這一點,我自己十多年前也只喜歡編寫命令列程式和系統服務,功能複雜不要緊,只要介面少到沒有就好。人機介面常常被認為是美工們的工作範圍,是沒有技術含量的體力活,然而事實總是無情地教訓他們,最近編FLASH的平均工資已經高過編JAVA和C#的了,這就足夠說明問題了。程式設計師們之所以有這種偏見,主要是他們腦子裡計算機技術裝得太滿,而應用場景少到幾乎不存在。人機介面是軟體中比較難以自動生成的部分,特別是如果追求個性化使用者體驗的話。我曾想過把使用者介面都做成主視角遊戲的形式,人們可以自然地走進並探索賽博空間,或許比較接近使用者介面的終極形式。這當然還沒實現,如果實現了,以後老闆們恐怕就再也搞不清楚員工是在工作還是在玩遊戲了吧。在系統中,使用者介面的作用無與倫比,首先,不管做什麼計算,使用者總是從使用者介面得到計算結果;其次,模型通常是反覆滾動計算的,經常需要通過使用者介面輸入、補充或者修正資料;最後,模型未必完全由計算機實現,模型中有些部分常常不適合今天的計算機處理,比如說影像內容識別,需要把這部分處理負擔轉移給人,然後人在把處理結果返回計算機,以便計算機繼續計算,這樣就變成了人機配合完成整個模型的計算,這種人機結合的地方也必然需要使用者介面。在軟體系統的所有部分中,人機介面可能將會是是程式設計師最後的領地。其他的輔助系統主要是人機介面以外的各種輸入輸出介面,這是最容易實現自動程式設計的領域,無需細說。

資料來源的問題也相對簡單,而且有TBL等牛人一直在推動資料標準化和互操作,這件事情看起來是無需我們操心了。如果他們最終成功(我毫不懷疑這一點),最終任何資料都可以按物件組織起來,並且得到一個人類能看懂的標籤,而且標籤的編寫方法符合嚴格的形式化定義,我們只要等著到時候從w3c下載解釋程式就足夠了。至於這些物件該放到系統裡的什麼地方去,那就與他們無關了,是構造模型的人考慮的事情。

模型程式碼化不僅取決於模型本身,更受計算環境的制約,這是絕大多數程式設計師所認可的“純技術”活,需要調動程式設計師最多的關於計算機系統的知識來完成。模型程式碼化的工作包括寫出使計算機可以完成模型運算的程式碼,以及把模型與周邊輔助系統銜接在一起的程式碼。高手和軟體廠商通常都會編寫一些程式框架,以便抹去計算環境不同帶來的複雜性,讓程式設計師專心處理模型,語言虛擬機器,應用伺服器都屬於這一類。模型中有一些功能是比較容易自動程式設計的,比如各個物件的屬性定義和CRUD方法,這部分程式碼的自動生成今天已經基本實現了。至於模型規則的程式碼化,這個麻煩可就大了,要先解決了模型本身的複雜度才行。

構造模型是人腦的一個基本功能,所以我們常常覺得這很容易。然而一旦交給計算機,其中的複雜性就顯現出來了。人腦中最簡單的模型是場景模型,也就是所謂的形象思維,具像思維。這是每個人在小時候,能夠使用語言進行抽象思維之前,唯一可用的思考模型,有一定思維能力的高階動物也具有使用場景模型的能力。場景模型是最常用的思考模型,在其他模型無法解決問題的時候,場景模型總是作為最後的手段。場景模型的推演是基於經驗的,因此只要能夠構造出來,就總是能夠有效地完成推演,而不必擔心沒有理論可用。然而場景模型並不簡單,世界上對場景模型認識最深刻的人群莫過於影視導演了,他們幾十年的功力都花在營造讓大多數人感到真實可信的場景上了,只要看看成為高水平的大導演的難度,就知道全面認識場景模型有多困難。今天的計算機系統是不具備像人類這樣的場景推演能力的,不過人工視覺的研究近年來進展很快,其中相當大的一部分就是解決計算機對視覺場景自動建模的問題,而視覺又是人類獲得場景資訊的主要資訊源,可以說只要解決了視覺場景的建模,機器理解場景就至少成功了一半。這方面我樂觀一點估計,20年後技術基本就成熟了。比場景模型高階一點的是語言邏輯模型,這種模型的理論都是用語言表示的,模型本身也都可以用語言精確描述出來,相比之下,場景模型雖然也可以用語言來描述,但是很難做到完全不丟失和歪曲資訊,特別是當其中有些物體無法對應到被人們廣泛熟知的概念上的時候。語言邏輯模型的推演就是我們平常所說的邏輯推理,也就是用語言形成一條邏輯因果鏈的過程。這類模型因為本身就是形式化的,能用語言外在地表達,而且較少模糊與歧義,因此傳統人工智慧領域研究得比較深入透徹,剩下的工作主要是與其他模型如何結合的問題。如果一個問題可以建立語言邏輯模型,那麼一定比針對這同一個問題所建立起來的場景模型運算量小很多,這就是抽象的優勢,因此效率大大提高了。在場景模型和語言邏輯模型基礎上,人腦發展出了稱為“數學”的東西,這是更高階的模型系統,具有更高的推演效率,心理學家把感官訊號稱為第一訊號系統,這個系統對應著場景模型,把語言稱為第二訊號系統,這個系統對應語言邏輯模型,照此推理,數學應該稱為第三訊號系統才對。數學因為具有邏輯模型的抽象特點,因此很多數學問題可以形式化,非常適合計算機處理,然而,因為數學又有一些部分以場景模型為基礎,所以也有一些數學問題很難用計算機處理,這些不好處理的特例,恐怕要等計算機處理場景模型成熟起來之後才有望解決,我認為30年是個合理的預期。

在解決了模型自動構造的基礎上,就有希望創造出具有人類思維能力的計算機系統,然而,計算機比人腦還缺一樣重要的東西,我們前面說過,計算機沒有主觀能動性,因此處理資訊的工作需要人來驅動。如果要象人腦那樣完成複雜的工作,計算機必須要自我驅動。今天的計算機有時候也能完成很複雜的計算任務,但是這是以軟體複雜性的極度增加為代價的,而這增加的複雜性,其實所做的只不過是把啟動程式時人類賦予的那個初始驅動力,不斷的轉換成各種形式,傳遞給各個計算單元而已。人類這種神奇的初始驅動力,來源於自身的生命力,或者說具體點,來源於人腦的情感慾望系統。生命力並不是什麼神奇的東西,動物也都一樣具有,只不過地球上的人類以外的動物還都沒有聰明到能夠學會計算機,所以它們不能驅動計算機幫他們做事情。情感慾望在計算中所起的作用,至今一直都被學界忽視了,這個系統看似與理性無關,卻是產生智慧所需的核心部件,人工智慧至今沒有實現,恐怕和科學家們還沒有想到這一點大有關係。再說句題外話,這恐怕和研究資訊科技的以男性為主大有關係,男性大多在情感上遲鈍,慾望又簡單直白,沒有深度,所以想不到這其中的關聯也在情理之中。未來的智慧計算架構,應當是一大群計算單元,具備各種模型處理能力,在一個模擬人類情感慾望驅動機制的核心的驅動之下,不斷碰撞組合,相互競爭,優勝的計算單元獲得更多資源和信任,從而推動整個計算體系不斷進化,最終產生出智慧。50年後,在我離開這個世界之前,或許能夠看到這樣的系統最終成熟起來。

模型的自動組合,其實就是軟體的自動組合,在有了這樣的系統之後,任何軟體都能自動組合出來,等到那一天,最後一位人類程式設計師就終於可以退休了。

相關文章