1. 程式人生 > >Linux之父炮轟C++:糟糕程式設計師的垃圾語言

Linux之父炮轟C++:糟糕程式設計師的垃圾語言


眾所期待的程式設計聖經


【寫在前面】
此文貼出後,引起了大家的較多關注,是意料之中的事情。畢竟,C、C++、Linux之父,都是大家最最熟悉的東西。但是許多同學把精力放在純粹語言優劣的爭論上,就沒有太大意思了。這場爭論的主角之一,微軟的Dmitry Kakurin有一句話非常正確:“這是一種信仰問題。因此,任何講道理和爭論都會無窮無盡,而且也毫無意義……”

我想,正確的態度,應該是從高手們的爭論中汲取營養,提高和深化自己對相關語言的認識,結合自己的實際環境,想想應該怎麼學,怎麼用。孟巖雲風pongba在這方面都有“有營養的”文字,大家可以看看。

各種語言都是有自己的侷限性的,也都有自己最擅長的用武之地。今天,軟體專案中越來越傾向於採用多語言開發,所以與其花精力做口舌之爭,不如多學學對方的語言。寫《程式設計師修煉之路》的Andy Hunt和David Thomas大師早就教導我們,要在軟體開發這個行當立於不敗之地,應該“

每年學一種新的語言”。


Linux之父Linus Torvalds為了Linux核心開發而專門打造的版本控制軟體Git已經引起了業界的廣泛關注。昨天,有一位Dmitry Kakurin老兄在查看了原始碼之後,發現使用的是純C而非C++,表示不可理解,他直言:“別拿可移植性說事兒,這是屁話(BS,bullshit)。“(此外,他還批評Git蠻力地直接操作文字,既囉嗦又易錯,而且很難跟上高層程式碼邏輯。)


這個BS引起了Torvalds的強烈反應,他用*YOU* are full of bullshit.“(你才滿嘴屁話呢)作為自己反駁的開場白。接著,他先轉向了對C++的罕見的火藥味十足的炮轟:

”C++是一種糟糕的(horrible)語言。而且因為有大量不夠標準的程式設計師在使用而使情況更糟,以至於極容易產生徹頭徹尾的垃圾(total and utter crap)。老實說,選擇C就是為了把C++程式設計師踢出去。……我有這樣的結論,任何喜歡用C++而不是C開發專案的程式設計師可能都是我希望踢出去的人,免得他們來搞亂我參與的專案。C++會導致非常非常糟糕的設計選擇。你們這些C++程式設計師總是一上來就用語言的那些‘漂亮的’庫特性比如STL、Boost和其他徹頭徹尾的垃圾,這可能對你們的程式有所‘幫助’,但是卻會導致:

“——當庫無法工作時無窮無盡的折磨(別跟我說什麼STL尤其是Boost很穩定而且可移植性很好,那全是屁話,而且一點都不可笑)

"——低效的抽象程式設計模型,可能在兩年之後你會注意到有些抽象效果不怎麼樣,但是所有程式碼已經依賴於圍繞它設計的‘漂亮’物件模型了,如果不重寫應用程式,就無法改正。

【圖靈圖書推薦】近10年來最好的C語言圖書,哈佛、MIT教材:K.N.KingC語言程式設計:現代方法即將出版!!
                                C語言搖籃貝爾實驗室培訓祕笈熱賣中                                                             


”也就是說,使用優秀的、高效的、系統級的和可移植的C++的唯一方式,最終還是限於使用C本身具有的所有特性。專案限制只用C,意味著參與的人不會搗亂,也意味著會得到許多真正懂得底層問題,而不會折騰那些白痴‘物件模型’垃圾的程式設計師。

"所以,我很抱歉,但是對於Git這樣效率是主要目標的軟體,C++的所謂優點只是巨大的錯誤。而我們將看不到這一點的人排除在外卻成了一個巨大的附加優勢。

"如果你想要用C++寫的版本控制系統,去玩Monotone吧。他們確實使用了‘真格的資料庫’,使用了‘漂亮的面向物件庫’、使用了‘漂亮的C++抽象’。可是說老實話,所有這些對某些計算機專業人士而言富於吸引力的設計決定,其最終結果確是一堆可怕、難以維護的垃圾。“


【070907更新】Torvalds和Dmitry Kakurin爭論繼續中。
對Torvalds的回擊,Dmitry反脣相譏:“隨著只用C程式設計的恐龍們逐漸滅絕,你很快就會發現只剩下自己一個人在固執己見。用Git貢獻者的數量是說明不了問題的。顯然C++開發者也能夠貢獻C程式碼。但是以為他們喜歡這種方式,那可就錯了。

“沒有C的時候我用匯編程式設計。然後在C++誕生之前,我轉向了C。現在我使用C++和C#,而且不再走回頭路。差勁的程式設計師用任何語言都寫不出好程式。但是為了將差勁的貢獻者拒之門外這樣一個沒譜的理由而懲罰優秀的開發者,這簡直是胡鬧。”

只過了10幾分鐘,Torvalds就回貼了:“和你不同的是,我實實在在地給出了不喜歡C++的原因,而且指出了它可能導致的各種問題的一些例子。而你呢,沒有給出一條像樣的使用C++的理由。事實上,Git比其他軟體配置管理軟體都要好,而好的品味(taste)和C正是原因之一。

        對上面的最後一句話,Torvalds後來又做了如下補充:
        ”說得更具體一些:
        “——簡單和清晰的核心資料結構, 非常精益(lean)且頗具雄心的程式碼管理著它們,將”簡單勝於花哨”
                 這一方法發揮到極致。
        ”——有意識地不抽象資料結構和演算法,因為它們恰恰是Git核心的全部要素(whole point)。

        ”如果你想用更花哨的語言,C++絕對是最糟糕的選擇。如果想要真正的高階特性,那就選擇有垃圾回收或
                  者好的系統整合的,而不是既缺乏C的簡約(sparseness)又缺乏C的直接而且沒有重要概念的高層                  繫結(high-level bindings to important concepts)的東西。

        “一言以蔽之,C++正處在困境當中,它既無法幫助原型化或者簡單的GUI程式設計足夠簡化從而真正可用,又                  不是C那樣積極地鼓勵你使用簡單和直接的語言構造的精益系統程式語言。

                   (另一位同學插了一句:這還沒有提到很難找到兩個C++編譯器支援同樣的特性。)

“這與什麼恐龍毫無關係。好的品味永遠不會過時。將C與組合語言相提並論,恰恰說明你對自己所討論的問題缺乏起碼的概念(don't have a friggin idea)。"

【070908繼續更新】
爭論還在繼續。半個小時之後,半小時後,Dmitry回帖

“我說過,這是一種信仰問題。因此,任何講道理和爭論都會無窮無盡,而且也毫無意義,就像任何其他宗教問題一樣。"

”我來講講Git開發應該使用C++的理由(而不是一般意義上C++對任何專案都更好的理由,這種說法同樣也是毫無意義的):

“1. 好的String類能夠大大提高程式碼的可讀性(而且程式碼也會顯著減少)
"2. 好的Buffer類——理由同上
”3. 管理記憶體和檔案/套接字/鎖控制代碼的智慧指標和智慧控制代碼
“就目前而言,通過這種繁瑣的巨集管理字串和記憶體,很難看出高層邏輯。

接下來他的語氣變得緩和,甚至最後還用了一個笑臉:
"以我之見,Git具有非常漂亮的高層設計(物件資料庫,使用雜湊,資料和元資料的簡單而且容易訪問的儲存。)向你贊一個!

“但是具體實現方式——C和shell指令碼的混合、自底向上發展出來的命令列介面就很一般了。

”我可沒有將C與組合語言相提並論。我只是要指出我曾經用許多不同的語言程式設計,目睹了糟糕的程式設計師用任何語言都會寫出差勁的程式碼。因此這實際上是與語言無關的。:-)

Torvalds則依然怒氣未消,他反駁Dmitry對Git用巨集管理字串和記憶體的批評
"完全是屁話。字串/記憶體管理根本無關緊要。還是去看看原始碼吧(我敢打賭你沒有看過)。這不是重要的部分,而且也不復雜。唯一真正重要的部分是設計。有些部分之所以是用 ' 原型化語言 ' 編寫,恰恰是因為它們不是核心部分,而且會被C慢慢地替換掉。C++可沒有辦法替換shell指令碼或者Perl程式碼。而且C++也沒辦法讓真正核心的部分變得更好。

"顯然你這一輩子已經經歷了 ' 彙編-> C -> C++/C# ' 的轉變過程,你將我這樣一直堅持用C的比作 ' 恐龍 ',似乎這是一種向更好/更現代的語言不可避免的演進。這是毫無根據的,因為C在很多方面都遠遠優於C++(更優於C#),包括可移植性,還有介面和低層支援。

"你當然可以用任何語言編寫糟糕的程式碼。但是,有些語言,尤其是帶有一些心理(mental)包袱的語言本身就非常糟糕。你這樣的新手跑來指出一些絕對無關緊要的補丁特性(【劉江按】此處應該指C++對C的增強特性),用它們作為一種語言優越的論據(這些東西語言原作者都不喜歡),這一事實本身恰恰說明你滿腦子都是糊塗概念,應該好好醒悟一下了。

"對於Git核心程式碼真正重要的,是諸如這樣的事情:編寫自己的物件分配程式碼,使記憶體佔用儘可能小,從而能夠高效地記錄百萬物件的標誌。這實際上是為樹形關係的多個物件編寫本質上非常優化的分析程式,因為這裡沒有任何抽象。這絕對是在原始記憶體位元組一級上的。

"這些事情能夠用C之外的語言編寫嗎?當然可以。但是那些認為C++字串處理這樣的高階特性很重要的人肯定是寫不出來的。

"事實上,這正是C擅長的事情。不僅指語言本身,還包括一種必需的心態(mentality)。C最大的優點之一,就是它不會使你認為程式是什麼高層的東西。正是後一種心態會使你明顯偏向其他語言,但實際上從Git的角度看來,所謂 ' 高層 ' 恰恰是錯誤的。"

Dmitry回帖:
我不僅看過原始碼,而且還做過很多除錯工作。我發現的問題大多數都與處理Windows上的路徑(也就是字串處理)有關。

他表示不再糾纏於“C與C++孰優孰劣”的討論,而是介紹了一下自己的出發點:

我的目的是使用Git。當有些功能無法使用時,我想能夠在儘可能最短時間和花費最小的力氣進行改正並貢獻改正的程式碼。對我來說,這只是我主要工作的一種消遣而已。

而Git用C編寫這一事實,對這一目的毫無好處。建議使用C++是現有C程式碼基礎的唯一出路。所以,雖然C++可能從學術上來講並非最佳選擇,但是唯一切合實際的選擇。

“除了其他已經嘗試過了的政體之外,民主是政體的最差形式。”
——溫斯頓 丘吉爾

現在,我認識到自己只是一個不太活躍的貢獻者,但我希望自己的聲音能夠被人聽到。而那些承擔開發和維護Git主要重任的人也應該發出自己的聲音。

此後,Torvalds沒有再發言,大概是認為自己已經大獲全勝。而另外一些Git貢獻者繼續對Dmitry進行反駁,可以看出,Torvalds的看法並不是他的私見。Theodore Tso說

“我認為字串處理是C++會找來大麻煩的地方之一。糟糕的程式設計師(原文為idiot)會這樣寫程式碼:

	a = b + "/share/" + c + serial_num;

“其中你肯定無法弄清到底分配了多少記憶體,因為有型別強制轉換、過載的操作符(感謝上帝,在C++中你可以過載逗號操作符!),而當這種東西出現在內迴圈中,結果將是效能上的大災難,而且原因還不明顯!

另外還有同學諷刺,說的確有不少C++程式設計師貢獻程式碼,但是反而需要核心的C程式設計師花費更多時間去修改和刪除。

【劉江按】以下是我的一點門外之見,做引玉的磚頭之用。

Dmitry有一點是肯定正確的,語言之爭更多的是一種類似宗教信仰上的,所以很難有結果,也沒有太多實際意義。這種爭論因為出自高手之間,所以還是會透露出很多重要的資訊。比如:

1. 對於要求效能高的系統程式設計領域,C++其實未必勝過C,而且事實上,也確實有很多此類專案是選擇C作為主要語言的。C的生命力目前仍然毋庸置疑。更多的資訊可以讀這裡

2. C++目前確實處於一種被夾攻的態勢,一方面在企業級系統開發(資料密集、業務規則複雜多變)中,C++已經基本被Java和C#等淘汰出局,另一方面在系統程式設計和嵌入式等更接近硬體的領域,又遭到C的強烈狙擊。

3. OO技術並非one-size-fits-all。
……(大家補充)

必須看到的是,C語言作為一種古老的語言,其侷限性也是很明顯的,比如已經成為安全問題淵藪的緩衝區溢位。C的標準庫也存在各種各樣的問題。對於更加貼近現實世界的眾多專案,沒有面向物件機制,顯然會影響開發效率。(有關C標準庫原始碼層次的分析,圖靈將出版著名C/C++專家Plauger的《C標準庫》一書。)而且,即使是C程式設計師所引以為豪的效能優勢,現在也岌岌可危了(參見C++之父Stroustrup的文章中相關的比較)。

C++目前的困境,很大程度上是由於此前的圖書和文獻曾經一度傾向於炫技,陶醉於對語言各種細節的深入探索,有華麗化、複雜化的趨勢,語言設計者們苦心設計出來各種豐富的特性和多範型的程式設計風格,卻成了學習者和使用者的負擔,加上微軟等開發工具又用MFC之類的糖衣,結果造就了大批基礎不牢、半桶水叮噹響的C++程式設計師,而且因為自以為掌握了世上最難的語言,往往有目空一切的傲氣。這樣開發出來的程式碼質量,可想而知。對C++的各種誤解和不良使用習慣,可以說是漫天飛舞。而這種局面繼而造成C++逐漸成為一般人心目中望而生畏、學不好教不好更用不好的“專家語言”,越來越無法吸引新入行的程式設計師。老人毛病多多,新人青黃不接,C++社群的確面臨危機。

這幾年,C++界的核心人物,包括Bjarne Stroustrup、Herb Sutter、Stan Lippman、Andrei Alexandrescu和Andrew Koenig、Stephen Dewhurst等,對此局面有過較多的反思,痛定思痛之後,寫作了Learning C++ as a New Language中譯文)、《C++ Primer》第四版《C++程式設計規範》、《Accelerated C++》和《C++必知必會》等返璞歸真的文章和圖書。其核心變化,是對標準庫(Torvalds語氣中對STL和Boost也很不屑,不知是何原因,請方家告我)、規範化、領域概念和設計的強調,弱化底層語言細節,或者說強調更規範地選擇使用語言特性。

比較同一作者的《C++ Primer》第四版和第三版、《C++程式設計規範》和《Modern C++ Design》以及Exceptional C++系列,可以清楚地看到這一點。

比如Primer第三版一上來就突出C++的多種程式設計風格(程序式程式設計、基於物件程式設計、面向物件程式設計、泛型程式設計),並且以此作為佈局謀篇的主線,很容易使初學者暈倒。到了第四版,則更多地把力氣花在打好紮實的基礎,介紹那些實際開發中通用的、行之有效的程式設計技術,在特定場合,C++提供的豐富“武器庫”中應該選擇哪些設施、應該注意哪些問題、業界已經總結了哪些優秀的程式設計實踐和易犯的錯誤等,成了書中的主幹。這使此書成為目前最適合的C++學習和使用的百科全書。

與此配套的,當然應屬《C++程式設計規範》,用條款形式說明了C++各種語言設施的正確用法和適用場合。如果你在學習C++的時候,就能結合其中的相關條款,瞭解所學特性的正確用法,當然是最理想的。而《C++必知必會》則選取了對C++程式設計師非常重要的知識點,進行一番貼近實際的討論。

C++圖書推薦請參見:
Dmitry Kakurin同學經查應該是一位微軟公司的工程師(參考這裡最後的Thanks to),致力於Git on Windows的開發。——但是不許聯想啊,免得又引起另外一個門派之爭。

【070909更新】好像是和Linus Torvalds呼應似的,有相當權威性的TIOBE的程式語言指數最近一期的結果顯示,C++下降了兩名,落後於(Visual) Basic和PHP,成了老五。而C則穩居第二。

Position
Sep 2007
Position
Sep 2006
Delta in Position Programming Language Ratings
Sep 2007
Delta
Sep 2006
Status
1 1 Java 21.701% +0.17%   A
2 2 C 14.908% -3.15%   A
4 5 PHP 10.204% +1.08%   A
5 3 C++ 9.938% -0.82%   A
6 6 Perl 5.416% -0.01%   A
7 8 C# 3.583% +0.59%   A
8 7 3.025% -0.12%   A
9 9 2.722% +0.28%   A
10 13 Ruby 2.065% +1.13%   A

【070910更新】
剛才看到,有兩位資深同學寫了相關的討論文章,用姜文的話說,屬於“有營養”的好文字,大家可以去看看:
孟巖:Linux之父話糙理不糙
雲風:C的迴歸

【070910夜更新】
今天偶然翻到《Unix程式設計藝術》一書,其中第4章中“Compactness”(緊湊性)部分裡,Eric Raymond寫道:

在通用程式語言中,C和Python是半緊湊的;Perl、Java、Emacs Lisp和shell則不是(尤其是真正的shell程式設計要求你知道半打sed和awk這樣的其他工具)。C++是反緊湊的——語言的設計者承認,他並不指望任何一個程式設計師能夠完全理解這一語言。

【070911更新】
剛才看到一張Linux核心開發者峰會照的全家福,有歷史價值,給大家分享一下。上面有Torvalds(大致在中間)、Andrew Morton(目前的核心主要維護者,第二排右數第二個)、Alan Cox(Linux貢獻最大的黑客之一,為《Linux程式設計》寫序的老大,兩個柱子之間個子不高的大鬍子)、Jonathan Corbet(《Linux裝置驅動程式》一書的作者,第一排左數第一個)和寫書的夥伴Greg Kroah-Hartman(中間的柱子
左邊)、上面發言的Tso(中間的柱子右邊,看簡歷也是個大牛呢,IBM的)、Olaf Kirch(《Linux網路管理員指南》的作者)等等。有位中國人Yang Li,飛思卡爾的。Herbert Xu是澳洲的,那個坐在地上的華人女士Mingming Cao是IBM美國的。



Monotone也是一個自由的CVS,網站在這裡

C和C++的比較是一個非常有趣的話題。你怎麼看呢?