天天看點

學習和使用多種程式設計語言的感想

寫這篇短文,是想表達一下自己對學習和使用過多種程式設計語言的認識和感想,我要說的不是網絡上那些不理性的口水仗和無腦噴,那很無聊。我想說的是語言本身之外的和方法論有關的東西,希望能給你帶來些幫助或啟發。

在繼續之前,我還要坦誠另一層原因,那就是之前聽到有人說他們招聘人時,隻要看到使用過多種程式設計語言的人,直接PASS, 理由是泛而不精。這讓我感到不安,因為我就是使用過多種程式設計語言的人。也許懷有這種理由的招聘方不占少數,也許由于涉獵其他而被枉殺的求職者也不占少數, 思考了良久,我覺得有必要站出來做些解釋,稍微緩和一下招聘方這種非黑既白的僵硬的認識。

(以下觀點全是我基于個人經曆,僅代表個人觀點)

不同的語言有不同的設計哲學,其方法論差别也很大。我講個很久前的一件事,有一個純文字的含有大綱資訊和表格元素資訊的文檔,要求提取出這個檔案中的所有大綱和元素并轉儲成xml文檔,如果按照傳統的C程式員的思維,要逐行讀入,每行都做首字母比較,判斷是大綱還是表格元素還是注釋,處理方法各不相同:大綱有主有次,表格元素有不同屬性,注釋要過濾掉……處理起來相當複雜. 我當時用Perl處理,方法是首先拼接所有行,把整個檔案變成一條長串,接着用比對大綱的正則式把單個長串分割為多個大綱短串,再過濾掉不含有效資訊的短串,(這些動作用join,split,grep函數連起來,一行就搞定)然後周遊剩下的所有短串,依間隔符分割短串,再過濾掉空白行,然後提取每個表格元素,(這些動作用split,grep,map+split函數連起來,同樣一行搞定)然後把每個元素的屬性及值存儲在Hash表中,最後用xml庫函數把清單和哈希結構輸出成嵌套格式的xml檔案,(總共20幾行)這是Perl教我的思維方式,如果我使用C語言的思維來做,無論是代碼量,還是調試時間,都要高出很多。不同的語言其強項和短闆不同,在你學習和使用這門語言的過程中,它的常見運用方式和思考方式會逐漸入駐到你的大腦中,自然而然地你在考慮問題時就會從不同的角度來看待和衡量。我再講個近期的事,要做一個表達式解析器,它要能支援數值的四則運算,字元串基本操作,如拼接,取子串,大小寫轉換等,還要能支援變量,自動類型轉換等。我的腦袋中閃現出兩種實作方式,一種是傳統式的過程思維(單詞序列,符号表,運算優先級棧,文法樹等)也就是學校裡編譯原理課程的知識,另一種是對象思維,抽象出個體,給個體添加行為。我選擇了對象方式,因為它簡潔、優雅。在設計和實作過程中,我采用了Ruby語言的消息式對象方式,一切皆對象,然後向對象發送消息。核心思想是:對任何表達式元素,都可詢問它是否能相應某個消息,“HI,你能響應這個消息嗎?”,“YES”,“GOOD,那你響應一下這個消息。”或者“NO”, “AH...主人,它不認識這個方法,是不是你寫錯了?”。(加減乘除是數值元素可響應的消息)可向任意元素發送任意消息,元素可根據期望的傳回類型傳回具體的(也就是派生類)表達式元素。表達式元素的派生類,如字元串元素,數值元素,變量元素等重寫消息響應的實作,這樣一來,無論具體值還是嵌套計算式都屬于表達式元素,都按同樣的方式求值。這種思路和傳統思路差異很大,但更簡潔優雅,更易擴充和維護。我雖然用的是C#語言,但采用的是Ruby的思維,思維是可以移植的,如果我沒有這種思維,實作代價會高很多,不知不覺就給自己和團隊帶來了損失。除了思維,還有慣用法,我在C#中,多次采用C語言慣用法,比如用位操作來設計和處理開關标志,巧用整數的大小端表示以及負數補碼表示的特點 來檢測資料流錯位等,然而這些用法對于周圍C#和Java的同僚們就像哥倫布發現新大陸一樣。 通過這些事,我想你應該能接受這個事實了:不同的語言會傳達給你不同的方法論,當你從多種語言學到多種思維方式之後,再遇到問題時,就可以博取衆長,以創新的方式,更加高效地解決問題。

在《精通Perl》的引言中有這麼一句:“如果不能列出5個讨厭Perl的理由和事實,就說明你對Perl的了解還不夠。這并不是Perl的問題,所有的語言都有缺陷。……你之是以是大師,是因為你知道問題的兩個方面、能做出合理的選擇、能給别人合理的解釋。” 我認為這句話可以延伸到任何語言,即 如果不能列出你使用的語言的三到五個缺點,就表示你對這門語言的了解還不夠。 但當你仔細思考這句話時,會發現話裡隐含了一個前提,那就是你已經掌握了第二種或更多的語言,隻有拿它們對比,你才能真切地體會到兩者的強項和短闆,做出合理的選擇,同時感歎以前“不識廬山真面目,隻緣身在此山中”。 還有一句:“你應該花時間讀一些關于程式設計的‘元’程式設計的書,而不是滿足于文法......你須要學點别的語言。作為大師,你須要一直學習。”  這一句是我後來學習更多語言的精神動力。 雖然很久了,但我一直記着這兩句話。

曾經有這麼一句話,差不多是這樣說的:“程式設計語言全都一個樣兒,隻要掌握一種,其他就都通了”。最初(07年)我以為這句話是對的,直到大約三年前(12年),我開始懷疑這句話的正确性,大約又過了一年(13年),我發現這句話大錯特錯,錯得離譜。直到現在,我都敢很不客氣地說:“說這類話的人,幼稚、狂妄,且很不負責。”,說其幼稚狂妄,是因為一類是沒有親身實踐過,“沒有實踐,沒有發言權”,人雲亦雲,另一類是“穿新鞋,走老路”,甚至生搬硬套,發現可行,就以為是一樣的,淺嘗辄止;說其很不負責,是因為誤人子弟,一個錯誤的思想不斷傳播、漫延,其危害不可估量。 我希望這類話沒有影響到你,也請你再聽到有人這麼說時,反駁他,糾正他。

願意去嘗試其他語言,說明人有好奇心,好奇心是優秀程式員的特質。另一方面,有多種思維方式的人更具創造性,更容易給團隊想出更多更好的點子,提出建設性意見,避免潛伏的危險等。一個團隊若清一色的一種語言,一種思維,那其實是低效的,也是危險的,隻是他們身在廬山中,認識不到而已。

程式員們大多狂妄自大,多學幾種語言會讓他們謙虛起來,學得越多越謙虛。因為接觸得越多,就會發現自己不懂的東西越多。接觸面就好像井口,半徑越小,青蛙看到得星星就越少,越會覺得自己全部都懂,而半徑越大,看到的星星就越多,越會覺得自己不懂。當半徑大到能看到銀河時,感歎自己隻是滄海一粟,無比渺小。 認識到自己的不足,在讨論問題時,就會少一些面紅耳赤,少一些針鋒麥芒,代之以互相欣賞,博取衆長。

其實我在說這些話時,也已經狂妄自大了,問題都是有兩面性的,有對有不對,有好處也有壞處。比如C#和Java相似性很高,掌握一種另一種就很容易了。對于同一種系别(同一種思維)的語言,确實是能舉一反三的,但同一系别就學不到另一種思維方式了。另一方面,通過學習不同語言來學習不同思維方式 有好處,也有壞處,壞處就是所謂的“泛而不精”,因為你沒有時間去精通,精通是需要長期鍛煉的。然而如果沒實踐過其他語言的話,單一語言即使長期鍛煉,也無法完全地精通。(說不出優缺點,說不出适用和不适用的原因,怎能算精通)

總體來說,我認為學習和使用多種程式設計語言是絕對有好處的,雖然也有不好的地方,但好處比壞處多得多。對于“泛而不精”和“一通百通”這兩種思想,我想你已經明白我是怎麼看待的了。

好了,就說到這裡,希望此短文帶給了你幫助和啟發。謝謝閱讀。