隨筆 - 312, 文章 - 14, 評論 - 1393, 引用 - 0
          數據加載中……

          微軟架構師談編程語言發展

              大約2個月前,在Herb Sutter的網站上看到了一個鏈接,內容是Channel9網站對他和其他三名微軟架構師就“編程語言發展”進行的采訪,架構師中有Anders Hejlsberg。一看之下,就被這個視頻迷 住了。這些大師站在歷史的高度,通觀全局又不失細節,高屋建瓴,有點有面地談到了多個語言的發展和語言間的相互關系。看完之后,感到視野得到了不小地開 拓,對于語言、框架、工具的關系;對于靜態(動態)類型、函數(命令)型編程;對于“可組合性”、“并發性”、“抽象層次”都有了更多的認識。

            說開點,隨著互聯網的真正深入生活,隨著“多核”時代的到來,IT技術領域正在經歷一場變革。這場變革和“可組合性”、“并發性”這兩個關鍵詞息息相關。圍繞著這兩個關鍵詞,若干新點子,新技術被提出來,而這些新技術往往與軟件產 業生產者所用的工具——編程語言緊密相關。因此,作為一個軟件職業者(或愛好者),聽聽大師的談話,對于把握這場變革的脈搏,跟上變革的潮流都不無裨益。 看完視頻,感到由于語言關系,如此好的材料無法為廣大中國程序員所知,實在是個遺憾,于是萌發了編譯的念頭。水平所限,錯誤難免,歡迎大家指正!此文在本 人博客上發布后,drdirac和pongba 兩位朋友對譯文提出了若干補充和修正,在此表示感謝!

            Charles:今天的訪談主要 討論兩個相關的論題:可組合性與編程語言。作為程序員,當我們構造系統時,總是要面對這兩個問題。你們是創設語法,搭建架構的人。所以,我想討論的一點 是,你們是如何協調工作的?三個語言——C#、VB和C++都在演進,同時又服務于不同目的,C++更多服務于系統級,C#和VB更多偏向應用層面這一切 是如何形成的?你們一起工作嗎?你們是如何決定語言創新的?你們是一起設計,還是想到什么后再與他人共享?

            Anders:我想,你說的 兩種情況都存在。早在做LINQ之前,Erik就在COmega項目上做了不少工作。LINQ和COmega相互影響,相似之處很多。我和他一直在討論相 關問題。實際上,Erik也在C#設計組中,我們總是在交換意見。VB組和C++組的人也在一幢樓里,大家經常碰到一起。

            Charles:但我的意思是,你們是否也像最終用戶一樣對自己做出區分?比如,有的事情在VB中能做,C#中就做不了。例如,VB以非常簡單的方式實現了完全的晚綁定,而C#中根本沒有晚綁定。為什么VB和C#如此不同?你們有意這樣設計的嗎?

          Anders:我認為,影響這個問題更多的是歷史原因。VB有其悠久而豐富的歷史。VB剛出現時就是晚綁定語言,沒有任何類型。很顯然,晚綁定對VB來 說有某種核心作用。但是,從那時起,VB已逐步演進為一種更“強類型”的語言,到現在,你甚至可以把VB看作一種支持晚綁定的強類型語言。呵呵。實際的過 程剛好相反。C#從一開始就是強類型語言,而且,直到現在我們都堅持早綁定。這并非說C#未來也不會支持晚綁定,但是,它很可能以不同于VB的方式來做, 而且可能會有所改進。C#是否支持晚綁定其實只是一種選擇。對于老式的弱類型對象模型來說,比如OLE,如果我們從晚綁定角度出發,會比從早綁定角度出發 好討論得多,因為這種對象模型無非就是對象若干方法的交互,反射等。

            Herb:在一定程度上,用戶造成了語言之間的差異。對于靠近底層 編程的C和C++程序員來說,性能永遠都是一個主要問題。你可能發現不同語言有不同特性,但是,更經常的,你會發現這些不同特性想要解決的是同一類問題, 比如,“并發執行”。現在,沒人能忽視這個問題。在未來5到10年,一種語言如果想留在主流編程語言的隊伍中,這個問題就無法忽視,因為這是硬件的發展方 向。我們正處于一個新時代——50年來,我們首次在非單核的機器上工作。任何人都無法忽視這點。因此,就這點來說,大家面臨相似的問題。但是,根據處理方 式、語法的不同,具體特性也會不盡相同。我也相信,不同語言推出相似特性的時間先后順序也不相同,因為不同語言服務于不同客戶群體,客戶要求不同。就像 Anders所說,各種情況都有一些。

            Erik:我給個具體例子,說明VB和C#的差異。這例子是“無名表達式(或lambda表達 式)”。我們想在VB中加入這種功能。首先就是尋找正確的語法。我們向VB項目組要到了VB的主名稱表,名稱表中的名字往往對VB和C#都適用。但是,這 次他們想要更像關鍵字的名字,而不是像C#那樣長長的名字,他們覺得像關鍵字的名字更加“VB化”一些。這里你看到的就是語法上的區別。但在語義上也有區 別。當你查看一個大函數內部嵌套很深的結構,比如for循環時,語言是何時、如何處理變量捕獲、如何進行實例保護就非常不同。在C#中,每次循環時實例都 被保護,而VB有點像JavaScript,變量被隱性提升到函數頂部。所以,在變量捕獲方面也存在語義上的區別。有時,這些區別極其細微,你必須用非常 變態的程序才能觀察到。

            Anders:只要你寫出依賴這樣的特性的程序,我們就能找出成百的Bug。

            Brian:你逃不出“作戰室”的。(譯者注:微軟“作戰室”,是產品、程序、測試人員一起確認需求、找Bug之所在。)

          Charles:這樣看來,大家都同意不同語言在相互影響,不斷演進。對于VB和C#來說,有相同的核心:處理引擎,你們必須在CLR的基礎上出發,隨 著CLR的演進而演進。很顯然,C++屬于另一個世界。但各種語言要互相影響,你們必須在C#中加點什么來吸引用戶,讓他們用C#而不是VB.NET,是 吧?應該不止是語法的區別,語言中必須還有一些核心的東西來吸引用戶。

            Herb:你說得對。但是,我不同意你提出的理由,說我們必須在 各自的語言中加點什么特性吸引用戶,從而使他們不去使用其他的微軟的語言。為什么呢?比如我更加關心使用C++或者C#的用戶到底需要什么,怎樣才能幫助 他們把工作完成得更好。也許某種語言性能強大,但我的工作是怎樣才能使客戶的工作更成功?我必須要考慮客戶會如何集成,我怎樣做才能使客戶工作得更好,這 也是CLR的核心所在,因為目前已經不是靠一種語言就能完成整個項目的時代了。我懷疑在稍有點規模的項目中,是否還有人僅僅依靠一種開發語言。

          一般說來,你用腳本語言寫代碼;其他語言寫工具和組件;系統語言寫核心——不停地在做集成。這就帶來了我們所討論的“可組合性”的問題。因為“可組合性 ”本質上就是跨語言的問題。當你寫Web瀏覽器時,你不知道某個插件是用C#、C++,某種CLR擴展,還是其他什么寫的。不管如何,這些東西必須一起工 作,這就是主要的挑戰。因為,要想使這種“可組合性”成為現實,我們必須時時將CLR和CLR以外的東西當作白盒來考慮。但是,這樣做的時候又會碰到“鎖 ”的問題。“并發執行”已經越來越重要了,但是,“鎖”完全不具備可組合性。因此,這是“可組合性”面對的主要障礙。總之,對我而言,這更多的是一個語言 交互的問題,而非語言競爭的問題。

            Brian:我在一定程度上代表了用戶。我是個物理學家,同時,我也經常寫點小程序,進行模擬和仿 真,解決一些數學問題。要想成功,“可組合性”對我的來說非常重要。我可以不在乎編程語言,但是我很在乎該語言是否有我所需要的組件。基本上,我十分愿意 使用任何能使我的工作更簡單的編程語言。

            這里,我要戴上頂“老人”帽,談談歷史上非常少的成功軟件之一:數值計算庫。這些東西是N年以 前用Fortran寫的。幾十年以來,人們用這些庫解決了許多非常重要的科學問題。任何頭腦正常的人都不會想重新寫一個“線性代數包”或者類似的東西。有 許多數學家終其一生在完善這些軟件包。我們需要的是“互操作性”,更是“可組合性”。所有人都知道,Fortran不支持遞歸,因為變量基于引用傳遞。這 就帶來了包接口的問題:如果你想要集成自身就做集成的東西,你就不能在用這個包來集成自己,這行不通。回到C++、C#和VB上,這些語言我都使用,但更 喜歡C#一些,主要因為它的操作符重載。為什么我喜歡操作符重載?因為我做奇怪的線代計算,如四元數、八元數,此時用一個小加號就能夠代表一大堆怪異的計 算。

            可能聽上去有點像是使用模板,但絕不是這樣,我一用模板就會開始想:模板的預處理器是完備的,也許我可以僅用模板就實現出一個鏈表 處理庫來解決。很快,我就會偏離真正的數學思考。在應用程序絕對需要晚綁定的場合,比如,那些小的計算模擬器。此時,我很自然地會選擇VB。至于C++, 大多數時候,它被用來實現其他的語言。在用于科學的環境下,我多次實現過Scheme。總之,就是泛談“可組合性”。

            Anders:當 我開始編程生涯時,進入編程這行的學習曲線就是:學習要使用的編程語言本身。各個編程語言幾乎在每個方面都不相同。語法是你要學習的很大一部分。但這是以 前的事了,現在你要學習巨大的框架,這個框架正越變越大,語法只是頂上的一顆“小櫻桃”,我認為這方面確實進展很大。但是,實際上起作用的東西是學習所有 的API,學習你所基于的,越來越大的平臺或者框架。如今,學習曲線的90%都耗費在這上面。掌握了這些,你就可以在C++、C#或者VB.NET什么的 之間,毫不費力地進行語言轉換,將部分項目使用這種語言,部分項目使用那種,并且找出組合這些語言的解決方案。相對于以前,實際上是不久之前,這是個主要 的進步。當然,所有這些得以出現,是由于有了通用的類型系統,以及各種語言中的那些抽象。每種語言之間的差別則是細微的,而且這些差別說不上來有什么特別 的理由。

            Brian:有時,這些語言必須綜合運用。比如,如今的Windows編程就是一大苦事:你必須懂PHP、 JavaScript、HTML、XML、SQL等等,要把這些東西全寫到名片上,你就只有小小的一塊地方可以寫自己的名字了。當然,能夠同時使用多種語 言也有好處,至少你可以選擇自己喜歡的語法。

            Erik:我們的編程語言之所以有差異,還是因為這些語言沒有能夠統一起來,在語言下面還有若干不一致的地方,我們實際上是被強迫使用不同的東西。CLR就不一樣,基于CLR上使用相同的庫,這些語言之間的排他性就要少一些,你可以選擇,而非被迫使用某種特定的語言。

            Brian:目前我們做得很多工作就是減少大家被迫使用某種語言這種情況。我們努力改進平臺,增加更多的功能,提供更多的.NET庫。

            Charles:但是,C++除之外,像VB和C#這樣的語言,確實綁定在某個框架上。這樣的話,在一定意義上是否有局限性?如函數型程序等將如何融入到我們所談的巨大的框架中呢?比如Haskell,又比如流行的F#,它們的結構與現在的語言完全不同。

          Erik:如果我們用“命令型語言”編程,我們的基本成份是“語句”。“語句”使用并且共享“狀態”,從而導致不太好的“可組合性”。你不能拿著兩段語 句,然后簡單地把它們粘合到一起,因為它們的全局狀態不能很好地交互。這就導致“命令型語言”不能很好地組合到一起。如果你看看LINQ,就會發現我們已 經更多地采用“函數型語言”的風格,所有的東西都基于表達式。“表達式”從其定義來說就是可組合的。從一定意義上來說,我認為在C#3和VB9中沒有什么 東西是Haskell或F#中沒有的。這里面有一些深奧的事情,如果你看看Haskell的類型系統,你就會發現這個類型系統跟蹤程序的副作用。這給了你 一定形式的可組合性。現在你雖然不能把有某種副作用的語句組合到有其他副作用的語句上,但是,你可以組合副作用相同的東西。F#有一個非常強悍的類型推斷 機制,它從設計之初就考慮了類型推斷。我們以前也有類型推斷,這并非什么新東西,但是現在的類型推斷要考慮很多困難因素,比如,重載,這些東西使類型推斷 很困難。如果你從這個角度來看,我認為我們已經在很大程度上采用了濃厚的“函數型”風格,并且以相當“可組合”的方式來使用表達式和lambda表達式。

            Anders:我們對“函數型編程”的興趣并非學院式興趣。實際上,當編程語言向前推進時,我們面臨兩類挑戰。一是古老的追求——不斷提高程序員的生產率,對此將沿用一直以來的方法:提升抽象的層次,給程序員垃圾回收機制、類型安全、 異常處理,甚至是全新的“聲明型”編程語言等。在提升抽象層次的過程中,正如Erik指出的,這些“聲明型”語言獲得了更高層次的“可組合型”。“函數型 ”語言之所以有魅力,因此你可以做出“沒有副作用”,或者其他承諾,這樣一來可組合性就極大地提高了。不僅如此,在如何保證多核處理器、多CPU, 比如,32個CPU始終忙碌,我們也會有所收獲。顯然,當我們更多地使用“函數型”或者“聲明型”風格的編程時,我們更有可能把運行時框架構建得能更好地 發揮多核的優勢,更好地處理并發。如果以“命令型”風格來工作,我們能夠發揮的余地就很小,因為你無法預見所有動作——這兒拿點東西,那兒放點東西,所有 動作必須串行執行,否則不可預料的事情就會發生。

            Charles:作為程序員,使用了如此巨大的一個處理引擎——比如CLR之后,當然認為這些底層的東西應該被抽象掉。你的意思也是,如果我使用了一個4核的機器,運行時引擎應該有能力負責在CPU上的分配分配進程。

          Anders:你這樣想很正常。但是,CLR以及目前我們工業中絕大多數的運行時,都是“命令型”引擎,其指令集都相當傳統,比如,堆棧增長;它們也擁 有易變的狀態,包括易變的全局狀態等等。在此之上,之所以能進行“函數型”編程,是因為“函數型”編程從本質上來說,是“命令型”編程所具備的能力集的一 個子集。現在我們想做的是最大化這種靈活性,但其實不過也就是讓“函數型”能力子集越來越相關,使其越來越主流化而已。

            Herb:我認 為有必要將“函數型”編程領域劃分成兩個部分。我非常同意Anders和Erik的意見。我不太同意的是這樣的措辭:我們之所以繼續使用“命令型”編程語 言,是因為這是大家目前所能理解的;通用程序開發者目前的工作并未取得巨大的成功;市場對于“所有的東西都是表達式,所有的語言都應該是表達式類型的語言 ”這樣的理念已經非常接受了;“函數型”語言是“串行執行”病的好藥方。我們要想使“函數型”語言運轉良好,關鍵點并不是處理好基本的表達式問題,而是處 理好lambda表達式和副作用的問題,是能夠將表達式作為第一級的編程要素來使用——LINQ也是最近才在做,關鍵是能夠指出lambda表達式和 Closure(譯者注:函數型編程語言中的一個概念,可以方便地組合函數,返回函數)的副作用。實際上,最后這點目前是缺失的。這些東西在“命令型”語 言中也是要處理的東西。我為什么提這些?因為我覺得說“函數型”語言是方向,目前的“命令型”語言不夠好,因此是垃圾,必須要拋在腦后,全面采用“函數型 ”語言這樣的說法不對。我認為,“函數型”語言到底能夠幫助程序員完成哪些工作,目前還不太明了。比如,能夠用它寫通用代碼嗎?能夠用它系統級代碼嗎?當 然,“函數型”語言有不少我們能夠借鑒的好東西,比如lambda表達式,比如Closure,C#借鑒了,C++也在借鑒,這些語言因此增色不少。關于 “函數型”語言還有另一個問題,那就是,有兩種類型的“函數型”語言。一種是沒有副作用的,因此就沒有共享、易變的狀態的問題;一種是人人都在使用的。因 為你不太可能說,“瞧,我是完全并發安全的,因為每次我都從這個“微型像冊”向量中得到一個拷貝。”或者說,“我操作這些元素的時候,我都是取得一個拷貝 ”。不錯,這時是沒有共享、易變的狀態,但是否能完全并發安全則不一定。

            Anders:我的意思是,在類似C#或VB這樣“命令型”編 程語言中加入“函數型”結構,能給我們提供“以函數型風格”寫程序庫的能力,從而我們就能夠非常明確地說,如果你能保證傳入的lambda表達式是純粹的 函數,我們就能保證正確地把它分散到若干個線程或者CPU上,最后再把它綜合起來,給出一個正確的結果。我們能保證代碼運行得更快,同時還不用作任何編碼 上的修改。然而,如果你在寫一個大大的For循環,我們永遠都不可能保證做到前面所說的,此時,“函數型”編程能夠提供給你的是一系列表達式,再加上“把 代碼當作參數傳遞”,“類型推斷和泛型編程可以正確地綁定所有的類型”等特性,這樣你就能更方便地編寫“可組合的算法塊”。

            Charles:這不就削弱了抽象嗎?

          Herb:我想指出的是當前所有語言都刻意不保證 “沒有副作用”。之所以如此的原因是,除非所有的語言都添加一些機制讓程序員可以清除副作用,我們這些做語言的人不敢打這個包票。但是,添加這樣的機制涉 及到眾多參與者,大家必須一起思考、一起討論什么是最好的方法,這個過程會很漫長。我們所做的是相信程序員,因為我們自己不知道。然而,很多情況下,程序 員也不知道,因為他寫的函數要調用其他的庫。而程序員根本不知道他使用的庫的副作用如何。這里,“可組合性”又浮上水面了。程序員可以增加一個間接層來處 理這個問題,但是,除非他擁有涉及到的所有代碼,沒有人能夠清楚地知道副作用會如何,問題依然存在。這就是難題所在。上面這些討論對“鎖”也適用,因為“ 鎖”也是全局問題,對“可組合性”是個障礙。

            Brian:在這點上Haskell做得很好,Haskell是“永遠沒有副作用”的范例。

          Erik:是的,但做到這點的過程也很痛苦,因為并非所有情況都一目了然。一旦你的庫代碼有副作用,而且因此使程序員的代碼必須按照某種順序執行,在某 種意義上,你是用匯編語言在編程,因為程序員將不再能用“表達式+表達式”的方式來寫代碼,他必須先對某個表達式求值,再對另一表達式求值,最后把值相 加。因此,我認為我們在這點上干得還是不夠漂亮。

            Brian:現在,我們在“流庫”上有例子。好消息是,我們已經有Haskell向你展示如何以“可行性”方面的代價,換取絕對純粹的方式。當然,除Haskell外,我們有各種“雜牌”語言。

            Anders:沒有純粹的好或壞,我認為,雖然進展緩慢,我們仍然快到一個令人滿意的中間點了。我完全同意說:如果我們確實能夠保證函數的純粹性,生活將會非常美好。最終我們得做到這點。

            Erik:但是,副作用也并非全然是壞事,如果函數使用了一個局部變量,這就是使用了一個狀態,但是,函數本身還可以是純粹的。我覺得很難完全避免副作用,一些東西可以是局部不純粹而整體純粹的。

          Herb:回過頭,讓我們從整體上看看“可組合性”。讓我吃驚的一件事是,很多時候,人們甚至都沒有意識到“可組合性”是個問題,以及自己實際上經常碰 到這個問題。其實,整個軟件工業乃至整個世界已經基于可組合的軟件了。在硬件會議上,我經常對硬件公司提到的是:硬件的并發問題已經被仔細地探索過了,而 且,當前消除共享、易變狀態的最好辦法就是“鎖”;但是,鎖是一種全局資源,不能被組合;“被鎖”是經常發生的事情,而當擁有“鎖”時,我還能調用任何其 他的未知的代碼;于是,“可組合性”被破壞了。說到這里,有的聽者往往一臉茫然:這有什么問題嗎?我于是會問,你們是否上網下載別人剛剛發布的,自己喜歡 的新軟件,比如,某個瀏覽器然后馬上使用呢?答案是肯定的。我于是會再問,你們是否意識到了,當你們這樣做時,這些軟件很可能都是第一次在最終用戶的機器 上被組合,被使用?既然如此,你們怎么可能對其進行測試?這時,屋子里有百分之十的人會露出恍然的表情,因為此前他們沒有想過這個問題:這些軟件是第一次 在最終用戶的機器上被組合,我們怎么進行測試?正因如此,“可組合性”是更重要的一個問題。更不用說我們現在有AJAX應用程序,以及眾多的插件經常被下 載,而且被要求在同一個用戶界面中協調工作。

          原文:http://tech.it168.com/a2009/0220/266/000000266178.shtml





          Android開發完全講義(第2版)(本書版權已輸出到臺灣)

          http://product.dangdang.com/product.aspx?product_id=22741502



          Android高薪之路:Android程序員面試寶典 http://book.360buy.com/10970314.html


          新浪微博:http://t.sina.com.cn/androidguy   昵稱:李寧_Lining

          posted on 2009-04-20 19:22 銀河使者 閱讀(614) 評論(0)  編輯  收藏 所屬分類: 雜七雜八

          主站蜘蛛池模板: 邹城市| 内黄县| 长宁县| 英德市| 洮南市| 永胜县| 商城县| 大姚县| 南漳县| 和田县| 遂昌县| 怀集县| 富顺县| 宜都市| 蓝田县| 天祝| 会宁县| 观塘区| 略阳县| 祁东县| 莱州市| 固镇县| 宜兰县| 桃江县| 龙州县| 呼伦贝尔市| 永宁县| 册亨县| 亳州市| 哈巴河县| 平远县| 澜沧| 莱州市| 兰州市| 阿拉善盟| 邹平县| 南岸区| 雷波县| 扎囊县| 富源县| 贵定县|