簡介 本文介紹如何在Eclipse中使用Ruby開發工具(RDT)外掛程式進行Ruby開發。本文將有益於那些想學習如何使用Eclipse基礎架構來進行Ruby開發的Ruby開發人員,也有益於對Ruby開發感興趣的Java開發人員。
一、 為什麼使用Ruby?
現在,為什麼眾多的Java開發人員都關注Ruby?Ruby,是10年以前在日本建立的一種通用目的指令碼語言,這是一種純物件導向的語言。不同於Java技術,Ruby中的一切都是對象。Ruby的文法主要來源於Smalltalk,Python和Ada。象Java程式設計語言一樣,Ruby是一種單繼承的語言,但是它提供了一些Java技術所沒有實現的進階特徵,例如閉合(可以認為是一種匿名的內部類)和mix-in(類似於介面,但是較松地綁定於類上)。Ruby也是高度可移植的,能夠運行在所有主流的作業系統之上。
現在,Ruby正十分熱門。人們正在開始把它應用於各種類型的應用程式。因為它是解釋型並且使用動態類型化,所以你可以在運行時刻實現在Java中很難實現的技巧。由動態類型化和富於表達的文法所實現的令人吃驚的能力之一是它能夠用Ruby建立域特定的語言(DSL)-它們允許你在更進階別的抽象層上工作,從而遠離最原始的語言文法。Ruby on Rails是一種建立基於資料庫支援的Web應用程式的架構,這也展示了Ruby的力量。Rake,作為Ruby的Make和Ant合二為一的版本,是這種語言強有力的應用的又一個證明。
使用Ruby的另一個原因是,所有的編程發燒友都在使用它。現在,許多Java高手(如Glenn Vanderburg,Bruce Tate和Martin Fowler)都在使用Ruby。即使你不打算把你的所有開發轉向Ruby,這種語言也值得你瀏覽一番。
限制Ruby發展的主要因素之一是,它缺乏一個良好的開發環境(對於那些不想學習Emacs的使用者來說)。如今,RDT改變了這一切,而使用Eclipse對此進行實驗則最好不過。
二、 安裝
在使用Ruby之前,你必須安裝Ruby解譯器,相應的庫和Ruby開發環境。
三、 取得Ruby
Ruby可用於所有主要的平台上。事實上,你的Linux或Cygwin分發包中可能已經包含了它。請開啟一個命令提示字元,然後輸入"Ruby-v"。
如果你得到一個版本號碼,那麼你已經準備好。否則,你需要檢查你所選擇的平台的分發包。
如果你正在運行Windows,則選擇更容易。RubyForge,作為SourceForge上的Ruby特定的等價物,有一個工程稱為One-Click Ruby Installer,這個程式用於在Windows平台上搭建Ruby環境。它還包括另外一些工具,如一個稱為FreeRide的IDE;但是如果你使用RDT的話,你在安裝過程中可以跳過這些這項。
四、 取得文檔
當你開始使用一種新語言時,文檔及有關參考材料是至關重要的。你可以在主Ruby網站得到Ruby文檔的線上參考材料,但是你會發現這些文檔有點過時(它們是針對於Ruby 1.6版本的,而目前的版本是1.8.2)。問題是,更新的文檔目前還沒有從日語翻譯過來。然而,你可以在Ruby-doc.org上找到最新的協助文檔。它包括API級的文檔(Javadoc的等價物),還有其它一些教程和書籍。
如果你是一位嚴肅的Ruby開發人員,那麼你應該閱讀一下《Programming Ruby:The Pragmatic Programmer's Guide》(作者是Dave Thomas和Andy Hunt)一書以取得最佳編程效果。這是一本有關Ruby及Ruby庫編程的經典指南。如果你得到此書,那麼你還可以參考也是Dave Thomas編寫的《Agile Development with Ruby on Rails》一書。這是一本有關Ruby on Rails的入門性書籍。
五、 得到RDT
現在,既然你在自己的電腦上安裝了一個可工作的具有良好協助文檔的Ruby,那麼接下來你需要安裝RDT了。這是一個Eclipse外掛程式,它提供了許多你可能在編輯代碼時已習慣的特徵。RDT是一個標準的Eclipse外掛程式;因此,你可以直接把壓縮檔解壓到Eclipse檔案夾下,由文檔中的路徑來處理其它一切。
現在,你已經準備好建立一個Ruby工程了(見圖1)。
與Java相比,Ruby在命名和目錄結構方面要求並不嚴格。在Ruby中建立一個工程實際上只建立一個目錄和一個工程檔案(不需要.classpath檔案,因為Ruby沒有classpath)。另外一個與Java技術的顯著區別是,Ruby工程嚮導並不建立顯式的src和bin目錄。Ruby是解釋型的,因此沒有輸出檔案夾。如果你有一個小工程,那麼你可以把Ruby源檔案放在與工程檔案相同的檔案夾下。作為選擇,你還可以建立你自己的目錄層次。你會發現,與Java相比,Ruby很少關心這些。
接下來,你將建立一個Ruby源檔案。沒有特定的嚮導用於建立一個Ruby源檔案。與Java技術相比,Ruby源檔案中僅需要較少的結構,所以,為了建立一個Ruby檔案,你需要右擊工程來建立一個新檔案(見下圖2)。
別忘記把標準副檔名.rb添加到該檔案(它是正常的Ruby副檔名)。建立一個Ruby檔案應該會開啟如圖3所示的Ruby視圖。
Ruby還提供了一個Outline視圖(類似於Java提供的那種)。就象它的Java對應物一樣,它允許你在Ruby源檔案的元素之間進行導航。在圖4中,raise_salary_by方法在Outline和源碼視圖中都被加亮。
就象其它複雜的外掛程式一樣,RDT也允許通過"Window>Preferences"對話方塊增加定製特徵。這個定製對話方塊見圖5。
圖5.RDT安裝"Preferences"以便實現定製 |
參數選擇"Preferences"功能表項目允許你改變文法加亮,格式化(Ruby世界中的標準縮排是兩個空格,而不是四個空格,所以請準備好作一些調整),等等。它還允許你定製編輯器模板並選擇你自己的解譯器。
六、 RDT編輯器
在Java世界中,我們已習慣於進階編輯器特徵-這使得在轉到其它不提供同樣支援的其它環境時比較困難。Ruby IDE中所缺乏的特徵之一是沒有提供內容助手(它能夠提供上下文相關的標識符尋找功能)。幸好,RDT編輯器中含有針對Ruby代碼的內容助手,見下圖6。
在Ruby中,你不能把一種類型賦值給一個變數或一個方法的返回,而由標識符上下文確定在運行時刻的類型。Ruby中引入了一種被親切地稱為"duck typing"的方法。這種方法的思想是,如果它接受一個假(quack)訊息,那麼它必須是一個"duck"。這看起來似乎妨礙了那些已經習慣了強型別化語言的使用者,這種鬆散類型耦合能夠支援Ruby語言中一些更強有力的特徵。例如,你可以用Ruby編寫一個異常處理器-當你調用一個並不存在的方法時啟用它,然後由該異常處理處理器來自由分析這個方法,然後再調用它。這種元編程級在強型別化語言中是很難實現的。
針對內容助手的一個挽回特徵是,Ruby在使用標識符時使用特定的命名慣例。例如,在Ruby中,所有的成員變數在第一次使用它們時就存在,並且全部由一個@符號所標識,作為其名字的第一個字元。如果你使用內容助手尋找成員變數,那麼你可以輸入@,這樣以來你就只能看見成員變數了。
動態類型化仍然妨礙在Ruby中的上下文敏感問題。在圖7中,唯一有效成員變數是正好出現在方法聲明上面的那些,也就是@name,@salary和@hire_year。內容助手所提供的另外一些成員來自於另一個類(後面定義)。目前,RDT編輯器還不足夠複雜以過濾所有的正確文法但語義上不正確的入口。
七、 運行與調試
IDE的特色之一是在同一個環境下運行和調試你構建的應用程式。RDT能夠啟用這兩項功能。
八、 指定一個解譯器
這一任務的實現位於Ruby上部和"Installed Interpreters"入口的"Windows>Preferences"對話方塊中。
Ruby是一種解釋性的語言,因此,在RDT能夠運行或調試你的應用程式之前,你必須把一個解譯器與你的環境關聯。這種關聯位於Ruby頂部的"Windows>Preferences"對話方塊中的"Installed Interpreters"入口處。
對於你正在使用的Ruby版本,你要把"Location"文本域指向bin目錄,之後由RDT來選取所有其它所需要的資訊。一旦你關聯瞭解釋器,那麼你就為運行應用程式作好了準備。
九、 運行Ruby應用程式
運行一個Ruby應用程式實際上類似於運行一個Java應用程式。你可以使用Run菜單來建立一個Run配置,見下圖9。
當你運行應用程式時,RDT將把控制切換到Ruby解譯器,然後在Eclipse工作區底部的控制台視窗內運行應用程式,見下圖10。
這個執行個體顯示了運行一個控制台應用程式,但是運行其它類型的應用程式(如GUI程式)的方式與此相同。
十、 用RDT調試
一個IDE要求實現的最關鍵的特徵之一是有效地調試你的應用程式的能力。Ruby解譯器包括一個命令列調試器,但是,在如今的圖形工具時代有誰會使用一個命令列調試器?幸好,Ruby解譯器還通過一特定(可配置)連接埠來廣播其調試資訊,而就象RDT這樣的工具能夠聽取該連接埠並且提供開發人員們期望的調試支援類型。
為了在RDT中調試一個Ruby應用程式,我們要象上面建立的Run配置一樣建立一個Debug配置。然後,你可以通過點擊左邊的溝槽設定一個斷點並使用調試器來啟動應用程式。就象在Java技術中一樣,IDE將詢問你,是否你想要切換到調試視圖下。如果你願意,則你將看見類似下面圖11所示的內容:
RDT中支援與Java技術調試相同的調試層級。左上邊的格子顯示出當前執行的線程,右上面的格子顯示出變數的值。就象在Java程式設計語言中一樣,你可以進一步分析對象以觀看它們內在的成員變數值。中間左邊的格子顯示當前正啟動並執行應用程式的原始碼,中間右邊的格子顯示Outline視圖-它在這裡擔當編輯器的作用,允許你通過點按一個標識符來進行導航。Debug視窗的底部顯示出Ruby解譯器在連接埠1098上廣播的調試資訊,而由RDT在該連接埠上聽取調試資訊。
調試器支援是RDT的特色。就算你有一個具有優秀的Ruby支援的編輯器,你仍然必須依靠命令列調試器來調試你的應用程式。擁有一個具有全面功能的調試器將會大大提高軟體的生產效率。
十一、 測試
作為Java開發人員最難實現的Ruby特徵之一是動態類型化。如果你習慣於一種強型別化語言,那麼動態類型化看上去似乎有點混亂。DT允許各種進階元編程技巧-這在一種強型別化語言中是很難或不可能實現的。當然,你可以放棄編譯時間刻類型檢查的安全設定。那麼,是否有一個方法能夠實現兩種世界的最佳結合呢?
單元測試應該是每一種語言必須實現的,但是它在動態語言中特別關鍵。單元測試比編譯揭示了更多的內容。事實上,你應該改變在單元測試和編譯之間的關係上的觀點。最近,一位進階軟體開發專家認為,"在今後的五年內,我們會把編譯作為單元測試的一種弱的實現形式"。單元測試能夠提供證實(verification)-編碼將如期實現,而不是僅僅進行你輸入內容的語法檢查。
考慮到單元測試在Ruby世界中的極端重要性,你一定會希望RDT能夠使得單元測試易於運行。的確如此!單元測試被包括在Ruby內,因此你不必下載任何其它的擴充。Ruby庫中包括了一個TestCase類和一個TestSuite的概念。你可以象建立任何另外的Ruby類一樣來建立你的單元測試,從Test::Unit::TestCase中子類化你的測試。列表1是一個Employee類的執行個體。
列表1.Employee類
class Employee def initialize(name, salary, hire_year) @name = name @salary = salary @hire_year = hire_year end attr_reader :name, :salary, :hire_year def raise_salary_by(perc) @salary += (@salary * (perc * 0.01)) end def to_s "Name is #{@name}, salary is #{@salary}, " + "hire year is #{@hire_year}" end end |
相應的單元測試如下:
列表2.相應於Employee類的單元測試
require 'test/unit/testcase' require 'test/unit/autorunner' require 'hr' class TestEmployee < Test::Unit::TestCase @@Test_Salary = 2500 def setup @emp = Employee.new("Homer", @@Test_Salary, 2003) end def test_raise_salary @emp.raise_salary_by(10) expected = (@@Test_Salary * 0.10) + @@Test_Salary assert( expected == @emp.salary) end end |
為了運行這個單元測試,你可以為該單元測試類建立一個Run配置-作為一個Test::Unit類型,見圖12。
圖12.RDT包括一個Test::Unit Run配置 |
當你運行這個測試時,你會得到與Java單元測試相同的支援元素,包括在左下角的類JUnit格子。
你還可以在Ruby中建立TestSuites。TestSuites是Ruby類,它定義一個返回TestSuite的suite方法。這個TestSuite由自動地在每個TestCases中定義的suite組成。列表3是針對幾個類的一個樣本TestSuite。
列表3.一些類的樣本TestSuite
require 'test/unit/testsuite' require 'test/unit/ui/tk/testrunner' require 'test/unit/ui/console/testrunner' require 'TestEmployee' require 'TestManager' class TestSuite_AllTests def self.suite suite = Test::Unit::TestSuite.new("HR Tests") suite << TestEmployee.suite suite << TestManager.suite return suite end end #Test::Unit::UI::Tk::TestRunner.run(TestSuite_AllTests) Test::Unit::UI::Console::TestRunner.run(TestSuite_AllTests) |
不同於前面運行單個TestCase的執行個體,這裡的suite作為一獨立的應用程式運行。Ruby有兩個方法可以顯示TestSuite的結果。第一個是"Console Test Runner"-它在控制台輸出它的結果。第二個是"Tk TestRunner",它建立一個熟悉的對話方塊來顯示測試的結果。圖14顯示了一個Tk TestSuite對話方塊。
十二、 新版本中的改進
RDT的目前的版本是0.50。目前,其開發人員正在開發0.60版本。下一個版本中將改進的方麵包括:
· 程式碼摺疊功能功能-提供針對類和方法的程式碼摺疊功能功能。
· Outline視圖-提供更詳細的資訊,包括對局部變數的支援。
· RI視圖-從一個RDT視圖中使用Ruby的ri工具。
· 任務標籤-以Ruby注釋形式為可配置的關鍵字(如TODO,FIXME)建立任務。
· 編輯器方面的改進-自動添加大括弧,圓括弧和單/雙引號;還有更好的代碼助手。
· 檢查器捷徑-在一個偵錯工作階段期間,針對經常使用的檢查器提供可配置的捷徑,如顯示一個對象的所有方法,全域常量,等等。
接下來的版本將更好地使用JRuby位元組碼編譯器。JRuby是一項工程,它允許把Ruby代碼編譯為Java位元組碼。這意味著,RDT的以後版本將更容易地加入到Eclipse世界中,甚至提供更好的支援。
十三、 總結
Ruby最終為業界人士所廣泛認可和應用。其中,部分原因應該歸功於Ruby on Rails工程的成功的驅動。如今,已經到了考慮如何把Ruby加入到你的"競爭工具箱"中的時候了。當然,RDT也是吸引你加入這一領域的一個重要因素。