松本行弘為什麼要開發Ruby

turingbooks發表於2011-08-23

  Ruby是起源於日本的程式語言。近年來,特別是因為在Web開發方面的效率很高,Ruby引起了全世界的關注,它的應用範圍也擴充套件到了很多企業領域。
  作為一門程式語言,Ruby正在被越來越多的人所瞭解,而作為一介工程師的我,松本行弘,剛開始的時候並沒有想過“讓全世界的人都來用它”或者“這下子可以大賺一筆了”,一個僅僅是從興趣開始的專案卻在不知不覺中發展成瞭如今的樣子。
  當然了,作為一種興趣,開發Ruby並不是我的本職工作,我是把它作為一個自由軟體來開發的。但是世事弄人,現在開發Ruby竟然變成我的本職工作了,想想也有些不可思議。
  “你為什麼開發Ruby?”每當有人這樣問我 的時候,我想,最合適的回答應該就像Linux的開發者Linus Torvalds對“為什麼開發Linux”的回答一樣吧。
  “因為它給我帶來了快樂。”
  當我還是一個高中生,剛剛開始學習程式設計的時候,不知何故,就開始對程式語言產生了興趣。
  周圍很多喜歡計算機 的人,有的是“想開發遊戲”,有的是“想用它來做計算”,等等,都是“想用計算機來做些什麼”。而我呢,則對“要用什麼程式語言來開發”、“用什麼語言開發更快樂”有很大的興趣。
  高中的時候,自己並不具備開發一種程式語言所必需的技術、知識,而且當時也沒有計算機。但是,我看了很多程式語言類的書籍和雜誌,知道了“還有像Lisp這樣優秀的程式語言”、“Smalltalk是物件導向設計的”,等等,在這些方面很著迷。上大學時就自然而然地選修了計算機語言研究的專業。10年後,通過開發Ruby實現了自己的夢想。
  從1993年開始開發Ruby到現在已經過去16年了。在這麼久的時間裡,我從未因為設計Ruby而感到過厭煩。開發程式語言真是一件非常有意思的事情。

程式語言的重要性
  為什麼會這麼喜歡程式語言?我自己也說不清。至少,我知道程式語言是非常重要的。
  最根本的理由是:語言乃人類思考的本質。在地球上,沒有任何超越人類智慧的生物,也只有人類能夠使用語言。所以,正是因為語言,才造成了人類和別的生物的區別。正是因為語言,人和人之間才能傳遞知識和交流,才能做深入的思考。如果沒有了語言,人類和別的動物也就不會有太大的區別了。
  在語言學領域裡,有一個Sapir-Whirf假說,認為語言可以影響說話者的思想。也就是說,因為語言的不同,所以造成了思想的不同。人類的自然語言是不是像這個假說一樣,我不是很清楚 ,但是我覺得計算機語言很符合這個假說。也就是說,程式設計師由於使用的程式語言不同,他的思考方法和編寫出來的程式碼都會受到程式語言的很大影響。
  也可以這麼說,如果我們選擇了好的程式語言的話,那麼成為好程式設計師的可能性就會大很多。
  20年來一直被奉為名著的《人月神話》的作者Frederick P.Brooks說過,一個程式設計師,不管他使用什麼程式語言,他在一定的時間裡編寫的程式行數是一定的。如果真是這樣的話,如果一個程式設計師一天可以寫500行程式的話,那麼不論他用匯編、C,還是Ruby,那麼他一天都應該可以寫500行程式。
  但是,彙編的500行程式和Ruby的500行程式所能做的事情是有天壤之別的。程式設計師根據所選擇程式語言的不同,他的開發效率就會有10倍、100倍,甚至1000倍的差別。
  由於低價格化和高效能化,計算機現在已經很普及了。現在基本上各個領域都使用了計算機,但如果沒有計算機軟體,那麼計算機這個盒子恐怕一點用都沒有。而談到軟體開發,就要求能夠用更少的成本,更短的時間,開發出更多的軟體。
  需要開發的軟體越來越多,但是開發成本卻有限,所以對於開發效率的要求就很高。程式語言就成了解決這個矛盾的重要工具。

Ruby的原則
  Ruby本來是我因為興趣而開發的。因為對多種程式語言都很感興趣,我廣泛對比了各種程式語言,哪些特性好,哪些特性沒什麼用,等等,都一一進行了比較、選擇,最終把一些好的特性都吸收到了Ruby程式語言之中。
  如果什麼都不考慮地去吸收的話,那麼這種程式語言只會變成過去的程式語言的翻版,從而失去它作為一種新的程式語言的存在價值。
  程式語言的設計是很困難的,需要仔細斟酌。值得高興的是,Ruby的設計很成功,很多人都對Ruby給出了很好的評價。
  那麼,Ruby程式語言的設計原則是什麼呢?
  Ruby程式語言的設計目標是,讓作為語言設計者的我能夠輕鬆程式設計,進而提高開發效率。
  根據這個目標,我制定了以下3個設計原則。
 簡潔性
 擴充套件性
 穩定性
  關於這些原則,下面分別加以說明。

簡潔性
  以Lisp程式語言為基礎而開發的商業軟體Viaweb被Yahoo收購後,Viaweb的作者Paul Graham也成了大富豪。最近他又成了知名的技術專欄作家,他寫了一篇文章就叫“簡潔就是力量” 。
  他還撰寫了很多擁護Lisp程式語言的文章,在這些文章中他提到,程式語言在這半個世紀以來是向著簡潔化的方向發展的,從程式的簡潔程度就可以看出一門程式語言本身的能力。上面提到的Brooks也持同樣的觀點。
  隨著程式語言的進化,程式設計師已經可以更簡單、更抽象地程式設計了,這是很大的進步。另外隨著計算機效能的提高,以前在程式語言裡實現不了的事情現在也可以做到了。
  用物件導向程式語言舉一個例子。把資料和方法作為物件來看待是物件導向的設計方法。但是在執行一個方法時需要做額外的判斷處理,而在以前,由於計算機的效能低,這種額外的處理是實現不了的。
  而現在,由於計算機效能大大提高,只要可以提高軟體開發效率,多少浪費一些計算機資源也無所謂了。
  再舉另外一些例子。比如記憶體管理,不用的記憶體現在可用垃圾收集器自動釋放,而不用程式設計師自己去釋放了。變數和表示式的型別檢查,在執行時已經可以自動檢查,而不用在編譯時檢查了。
  讓我們看一個關於斐波納契(Fibonacci)數的例子。圖1-1是用Java程式來計算斐波納契數的。演算法有很多種,我們用最常用的遞迴演算法來實現。
  圖1-2是基於完全一樣的實現方法,用Ruby程式語言寫的程式;演算法完全一樣。和Java程式比較的話,可以看到構造完全一樣,但是程式就更簡潔。Ruby不做明確的資料型別定義,不必要的宣告都可以省略。所以,程式就非常簡潔了。
  演算法的教科書總是用模擬語言來描述演算法。如果像這樣用實際的程式語言來描述演算法,那麼像型別定義這樣的非本質程式碼就會佔很多行,會讓人不能專心於演算法。
  但是,如果把模擬程式語言中非本質的東西去掉,只保留描述演算法的部分就直接可以執行的話,那麼這種程式語言不就是最好的嗎?Ruby的目標就是成為開發效率高,“能直接執行的模擬程式語言”。

擴充套件性
  下一個設計原則是“擴充套件性”。程式語言作為一個軟體開發工具,最大的特徵就是要實現的功能事先沒有限制。“如果想做就可以做到”,這聽起來像小孩子說的話,但在程式語言的世界裡,真的就像這句話所說的一樣。不管在什麼領域,不管做什麼處理,只要用一種程式語言編寫出了程式,我們就可以說這種程式語言適用於這一領域。而且,涉及領域之廣會遠遠超出我們當初的預想。
  1999年,最初的關於Ruby的書籍《物件導向指令碼語言Ruby》出版的時候,我在裡面寫到了“Ruby不適合的領域”,包括“以數值計算為主的程式”和“數萬行的大型程式”。
  但是幾年後,規模達幾萬行、幾十萬行的Ruby程式被開發出來了。氣象資料分析,乃至生物領域中也用到了Ruby。現在,美國國家海洋和大氣局(NOAA,National Oceanic and Atmospheric Administration)與國家航空和航天局(NASA,National Aeronautics and Space Administration)也在不同的系統中運用了Ruby。
  情況就是這樣,程式語言開發者事先並不知道這種程式語言都會用來開發什麼,都會在哪些領域中應用。所以,程式語言的擴充套件性非常重要。
  實現擴充套件性的一個重要方法是抽象化。抽象化是指把資料和要做的處理都封裝起來,就像一個黑盒子,我們不知道它的內部是怎麼實現的,但是可以用它。
  以前的程式語言在抽象化方面是很弱的,要做什麼處理首先要了解很多程式語言的細節。而很多物件導向或者函式式的現代程式語言,都在抽象化方面做得很好。
  Ruby也不例外。Ruby從剛開始設計時就用了物件導向的設計方法,資料和處理的抽象化提高了它的開發效率。我在1993年設計Ruby時,在指令碼程式語言中採用物件導向思想的還很少,用類庫方式來提供程式語言的就更少了。所以現在Ruby的成功,說明當時採用物件導向方法的判斷是正確的。
  Ruby的擴充套件性不僅僅體現在這些方面。比如Ruby以塊這種明白易懂的形式給程式設計師提供了相當於Lisp高階函式的特性,使“普通的程式設計師”也能夠通過自定義來實現控制結構的高階函式擴充套件。又比如已有類的擴充套件特性,雖然有一定的危險性,但是程式卻可以非常靈活地擴充套件。關於這些物件導向、程式塊、類擴充套件特性的內容,後面的章節還會詳細介紹。
  這些特性的共同點是,它們都表明了程式語言讓程式設計師最大限度地獲得了擴充套件能力。程式語言不是從安全性角度考慮以減少程式設計師犯錯誤,而是在程式設計師自己負責的前提下為他提供最大限度發揮能力的靈活性。我作為Ruby的設計者,也是Ruby的最初使用者,這種設計的結果表明,Ruby看重的不是明哲保身,而是如何最大限度地發揮程式設計師自身的能力。
  關於擴充套件性,有一點是不能忽視的,即“不要因為想當然而加入無謂的限制”。比如說,剛開始開發Unicode時,開發者想當然地認為16位(65 535個字元)就足夠容納世界上所有文字了;同樣,Y2K問題也是因為想當然地認為用2位表示日期就夠了才導致的。從某種角度說,程式設計的歷史就是因為想當然而失敗的歷史。而Ruby對整數範圍也不做任何限定,盡最大努力排除“想當然”。

穩定性
  雖然Ruby非常重視擴充套件性,但是對一個特性,儘管明知道它能帶來巨大的擴充套件性,也一直都將其拒之門外。那就是巨集,特別Lisp風格的巨集。
  巨集可以替換掉原有的程式,給原有的程式加入新的功能。如果有了巨集,不管是控制結構,還是賦值,都可以隨心所欲地進行擴充套件。事實上,Lisp程式語言提供的控制結構很大一部分都是用巨集來定義的。
  所謂Lisp流,其語言核心部分僅僅提供極為有限的特性和構造,其餘的控制結構都是在編譯時通過用巨集來組裝其核心特性來實現的。這也就意味著,由於有了這種無與倫比的擴充套件性,只要掌握了Lisp基本語法S式(從本質上講就是括號表示式),就可以開發出千奇百怪的語言。Common Lisp的讀取巨集提供了在讀取S式的同時進行語法變換的功能,這就在實際上擺脫了S式的束縛,任何語法的語言都可以用Lisp來實現。
  那麼,至於我為什麼拒絕在Ruby中引入Lisp那樣的巨集,那是因為,如果在程式語言中引入巨集的話,活用巨集的程式就會像是用完全不同的專門程式語言編寫出來的一樣。比如說Lisp就經常有這樣的現象,活用巨集編寫的程式A和程式B,只有很少一部分是共通的,而從語法到詞彙都各不相同,完全像是用不同的程式語言寫的。
  對程式設計師來說,程式的開發效率固然很重要,但是寫出的程式是否具有很高的可讀性也非常重要。從整體來看,程式設計師讀程式的時間可能比寫程式的時間還長。讀程式包括為理解程式的功能去讀,或者是為維護程式去讀,或者是為除錯程式去讀。
  程式語言的語法是解讀程式的路標。也就是說,我們可以不用追究程式或庫提供的類和方法的詳細功能,但是,“這裡呼叫了函式”,“這裡有判斷分支”,等等,這些基本的“常識”在我們讀程式時很重要。
  但是一旦引入了巨集定義,這一常識就不再適用了。看起來像是方法呼叫,而實際上可能是控制結構,也可能是賦值,也可能有非常嚴重的副作用,這就需要我們去查閱每個函式和方法的文件,解讀程式就會變得相當困難。
  當然了,我知道世界上有很多Lisp程式設計師並不受此之累,他們正是通過面向特定程式定製語言而最大限度地提高了開發效率。但是在我個人看來,他們只是極少數的一部分程式設計師。
  我相信,作為在世界上廣泛使用的程式語言,應該有像不隨風飄蕩的燈芯那樣穩定的語法。

一切皆因興趣
  當然,Ruby不是世界上唯一的程式語言,也不能說它是最好的程式語言。各種各樣的程式語言可以在不同的領域中應用,各有所長。我自己以及其他Ruby程式設計師,用Ruby開發效率很高,所以“覺得Ruby最為得心應手”。當然用慣了Python或者Lisp的程式設計師,他們會覺得那些程式語言是最好的。
  不管怎麼說,程式語言存在的目的是讓人用它來開發程式,並且儘量能提高開發效率。這樣的話,才能讓人在開發中體會到程式設計的樂趣。
  我在海外講演的時候和很多人交流過使用Ruby的感想,比較有代表性的是“用Ruby開發很快樂,謝謝!”
  是啊,程式開發本來就是一件很快樂、很刺激和很有創造性的事情。想起中學的時候,用功能不強的BASIC程式語言開發,當時也是很快樂的。當然,工作中會有很多的限制和困難,程式設計也並不都是一直快樂的,這也是世之常情。
  Ruby能夠提供很高的開發效率,讓我們在工作中擺脫很多困難和煩惱,這也是我開發Ruby的目的之一吧。

 

摘自:《松本行弘的程式世界》

相關文章