簡介:本文介紹如何使用 Eclipse 插件 Ruby Development Tools(RDT),這個插件使 Eclipse 能 夠成為一流的 Ruby 開發環境。那些希望利用 Eclipse 社區豐富的基礎設施來支持開發的 Ruby 開發人 員會從本文中受益,對有興趣使用 Ruby 的 Java開發人員也會有所收獲。
為什麼要使用 Ruby?
為什麼 Java 開發人員會關心 Ruby?Ruby 是 10 年前在日本開發出來的通用腳本語言。與流行 的信念相反,它是一種純面向對象語言。與 Java 技術不同,Ruby 沒有標量,所以所有東西(包括整數 )都是一類對象。Ruby 的語法很大程度上借鑒於 Smalltalk、Python 和 Ada。與 Java 語言相同的地方 是,Ruby 也是一種單繼承語言,但是它提供了 Java 技術所缺乏的某些高級特性,比如閉包(與 steroids 上的匿名內部類相似)和 mix-ins(與接口相似,但是它們與類的綁定不太緊密)。Ruby 也具 有很高的可移植性,可以在所有主流操作系統上運行。
Ruby 現在已經很流行了,人們開始用它建 立各種應用程序。因為它是解釋語言而且使用動態類型,所以可以在運行時做許多極其靈活的工作,而這 在 Java 中是非常困難的。動態類型和表達語法所支持的神奇功能之一是,能夠在 Ruby 中創建領域特定 的語言,這使開發人員能夠在更高的抽象級別上工作,從而脫離語言的“原始”語法。Ruby on Rails 是一個用於創建帶後端數據庫的 Web 應用程序的框架,它展示了這種優雅性。Rake(Make 和 Ant 相結合的 Ruby 版本)也展示了 Ruby 的這種強大能力。
使用 Ruby 的另一個理由是,許多 敏銳的開發人員已經開始使用它了。那些在 1996 年就認識到 Java 技術即將流行的開發人員(比如 Glenn Vanderburg、Bruce Tate 和 Martin Fowler)現在已經開始使用 Ruby。即使您還不打算全面轉向 Ruby,現在也應該研究一下這種語言了。
對於用 Ruby 進行廣泛的開發,主要的限制因素之一是 缺少一個出色的開發環境(對於那些不想學習 Emacs 的人來說尤其如此)。RDT 改變了這種狀況。在您 喜歡的 Eclipse IDE 中使用 Ruby,這會使您感到舒適。
准備
在開始使用 Ruby 之前,必 須安裝(或者驗證已經具有了) Ruby 解釋器和庫以及 Ruby Development Environment。
獲得 Ruby
可以獲得適合所有主流平台以及幾個次要平台的 Ruby 版本。實際上,您的 Linux® 或 Cygwin 發行版可能已經包含了 Ruby。轉到命令提示符下並輸入 ruby -v。
如果看到一個版本號 ,就說明 Ruby 已經有了。如果沒有看到版本號,就需要獲取 Ruby。先尋找適合您平台的 發行版。
如果您正在使用 Windows®,就更容易了。RubyForge(與 SourceForge 功能相似)有一個稱 為 One-Click Ruby Installer 的項目,這個程序會在 Windows 上建立 Ruby 環境(參閱 參考資料)。 它還包含幾個工具,包括稱為 FreeRide 的 IDE,但是如果使用 RDT,則可以不用理會大多數這些工具。
獲得文檔
在開始使用一種新語言時,文檔和其他參考資料是非常重要的。可以在 Ruby 主 Web 站點上獲得 Ruby 文檔的在線參考,但是您會發現這裡的文檔有點兒過時了(它針對 Ruby V1.6,而 當前版本是 1.8.2)。這是因為最新的文檔還沒有從日文翻譯成英文。但是在 Ruby-doc.org 上可以找到 最新的文檔。它包含 API 級文檔(與 Javadoc 等同)以及一些教程和書籍。(參閱 參考資料。)
如果您關心 Ruby 開發,那麼應該盡快獲得 Dave Thomas 和 Andy Hunt 撰寫的 Programming Ruby: The Pragmatic Programmer's Guide(參閱 參考資料)。這是對 Ruby 的標准介紹並且介紹 了 Ruby 庫的需求。在閱讀這本書的同時,還可以閱讀 Dave Thomas 撰寫的 Agile Development with Ruby on Rails,其中介紹了 Ruby on Rails。
獲得 RDT
既然已經在計算機上安裝了可以 工作的 Ruby 版本並且獲得了文檔,現在就需要 RDT 了(參閱 參考資料)。這個 Eclipse 插件提供了 許多特性,您在編輯代碼時會慢慢熟悉這些特性。RDT 是一個標准的 Eclipse 插件,具有特性和插件, 所以可以將 zip 文件直接解壓縮到 Eclipse 文件夾。存檔文件中的路徑會建立目錄結構。
現在 可以創建 Ruby 項目了(參見圖 1):
圖 1. 創建新的 Ruby 項目
與 Java 技術相比 ,Ruby 對名稱和目錄結構的要求寬松多了。在 Ruby 中創建一個項目實際上只是創建一個目錄和一個 .project 文件(這裡不需要 .classpath 文件,因為 Ruby 沒有類路徑)。與 Java 技術相比,另一個 顯著差異是 Ruby 項目向導並不創建顯式的 src 和 bin 目錄。Ruby 是解釋語言,所以沒有輸出文件夾 。如果項目比較小,那麼可以將 Ruby 源代碼文件與項目文件放在同一個文件夾中。也可以創建自己的目 錄結構。您會發現,與 Java 語言相比,Ruby 不太關心目錄結構。
接下來,需要一個 Ruby 源代碼文件。沒有專門用於創建 Ruby 源代碼文件的向導。與 Java 技術不 同,對於 Ruby 源代碼文件的結構沒有什麼要求,所以要創建 Ruby 文件,只需使用項目的右擊菜單創建 一個新文件。
圖 2. 創建 Ruby 源代碼文件
不要忘記在文件名 後面加上標准的擴展名 .rb,這是一般的 Ruby 擴展名。創建 Ruby 文件應該會打開 Ruby 透視圖。
圖 3. 創建 Ruby 源代碼文件會打開 Ruby 透視圖
Ruby 透視圖還提供 一個大綱視圖,這與 Java 透視圖提供的大綱視圖相似。與 Java 大綱視圖相似,它允許導航 Ruby 源代 碼文件的元素。在圖 4 中,raise_salary_by 方法在大綱視圖和源代碼視圖中高亮顯示。
圖 4. 大綱視圖允許在源代碼文件中進行導航
與其他復雜的插件一 樣,RDT 也在 Window > Preferences 對話框中增加了定制特性。這個首選項對話框如圖 5 所示。
圖 5. RDT 的定制首選項
首選項菜單項允許 修改語法高亮顯示方式、格式化(在 Ruby 中標准的縮進是兩個空格,不是四個,所以要做某些調整)等 等。它還允許定制編輯器模板以及選擇解釋器。
RDT 編輯器
在 Java 技術環境中,我們已 經習慣了高級的編輯器特性,這使我們在轉移到沒有提供這些特性的其他環境時不太適應。Ruby IDE 缺 乏的特性之一是 Content Assist,這種特性針對標識符進行上下文相關的查找。RDT 編輯器對 Ruby 代 碼提供了 Content Assist。
圖 6. RDT 編輯器提供 Content Assist
RDT 編輯器中的 Content Assist 沒有 Java 環境中那麼有針對性,因為 Ruby 支持動態類型。在 Ruby 中,不能將類型 賦給變量或者方法返回值。標識符上下文在運行時決定類型。Ruby 使用所謂的“duck typing” —— 也就是說,如果它接受“鴨叫”消息,那麼它一定是鴨子。 對於那些習慣於強類型語言的人來說,這可能像是一種阻礙,但是這種弱類型耦合使 Ruby 語言能夠實現 某些更強大的特性。例如,在 Ruby 中可以編寫一個異常處理程序,如果調用一個不存在的方法就會觸發 這個程序,這個異常處理程序可以動態地合成這個方法並且調用它。在強類型語言中很難實現這種元編程 。
Content Assist 彌補的特性之一是 Ruby 對標識符使用的特殊命名約定。例如,在 Ruby 中, 所有成員變量在第一次使用時才存在,而且都由 @ 符號作為名稱的第一個字符。如果使用 Content Assist 查找成員變量,那麼可以輸入 @,並且只看到成員變量。
圖 7. Ruby 中的命名約定幫助 實現 Content Assist
動態類型仍然會妨 礙 Ruby 中的上下文敏感性。在圖 7 中,合法的成員變量只是在上面方法聲明中出現的成員變量,即 @name、@salary 和 @hire_year。Content Assist 挑選出的其他成員變量來自後面定義的另一個類。RDT 編輯器還不完善,無法過濾出所有語法上正確但是語義上不正確的條目。
運行和調試
IDE 的關鍵特性之一是能夠在構建應用程序的環境中對應用程序進行運行和調試。RDT 支持這兩種功能。
指定解釋器
Ruby 是一種解釋語言,所以必須將一種解釋器與環境相關聯,然後 RDT 才能 運行或調試應用程序。這種關聯是在 Windows > Preferences 對話框中 Ruby 標題下面的 Installed Interpreters 項中設置的。
圖 8. 將 Ruby 解釋器與環境關聯起來
將 “Location”文本域指向您使用的 Ruby 版本的 bin 目錄。RDT 會找到所需的其他信息。關 聯了解釋器之後,就可以運行應用程序了。
運行 Ruby 應用程序
運行 Ruby 應用程序與運 行 Java 應用程序實際上完全一樣。使用 Run 菜單創建一個 Run 配置。
圖 9. 在 RDT 中建立 Run 配置
在運行應 用程序時,RDT 啟動 Ruby 解釋器並且在 Eclipse 工作區底部的一個控制台窗口中運行這個應用程序。
圖 10. 在 RDT 中運行 Ruby 應用程序
這個例子顯示如何 運行一個控制台應用程序,但是運行其他類型的應用程序(比如圖形化應用程序)也是一樣的。
用 RDT 進行調試
IDE 需要的最關鍵的特性之一是能夠有效地調試應用程序。Ruby 解釋器包含一 個命令行調試器,但是在這個圖形化工具的時代誰還想使用命令行調試器?幸運的是,Ruby 解釋器還通 過一個特定(可配置)的端口廣播調試信息,RDT 這樣的工具能夠監聽這個端口並且提供開發人員期望的 調試支持類型。
要調試 Ruby 應用程序,需要創建一個 Debug 配置,就像前面創建 Run 配置一 樣。然後,在左邊的空白處點擊以設置斷點,並使用調試器啟動應用程序。與 Java 技術一樣,IDE 將詢 問您是否想切換到 Debug 透視圖。回答之後,將看到下面這樣的屏幕:
圖 11. 在 RDT 中調試 Ruby 應用程序
RDT 提供了與 Java 技術相同的調試支持級別。左上方的窗格顯示當前正在執行的線程。右上 方的窗格顯示變量的值。與 Java 語言中一樣,可以深入到對象中,查看它們的底層成員變量值。左邊中 間的窗格顯示正在運行的應用程序的源代碼,右邊中間的窗格顯示大綱視圖(它在這裡的工作方式與在編 輯器中一樣,讓開發人員能夠通過點擊標識符來進行導航)。Debug 窗口的底部顯示 Ruby 解釋器在端口 1098 上廣播調試信息,RDT 在這個端口上監聽調試信息。
調試支持是 RDT 的關鍵特性。即使您 的編輯器有出色的 Ruby 支持,但是仍然必須依賴命令行調試器來調試應用程序。擁有一個功能全面的調 試器可以顯著提高生產效率。
測試
對於 Java 開發人員,Ruby 最難掌握的特性之一是動 態類型。如果您已經習慣了強類型語言,那麼動態類型看起來可能會導致混亂。動態類型支持所有高級的 元編程技巧,這在強類型語言中是很難實現的,甚至不可能。當然,還會失去編譯時檢查的安全保障。是 否有辦法同時獲得這兩種環境的優勢呢?
對於語言,單元測試是必需的,但是在動態語言中它特 別重要。單元測試能夠比單純編譯揭示出更多的問題。實際上,您應該換個角度看待單元測試和編譯之間 的關系。近來,在一個軟件開發專家討論會上,軟件開發思想家 Relevance 公司的 Stuart Halloway 指 出,“在 5 年內,我們將看到編譯成為一種比較弱的單元測試形式。”單元測試檢驗代碼是 否做了開發人員希望它做的事兒,而不只是對類型進行拼寫檢查。
既然單元測試在 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
要運行這個單元測試,應該為單元測試類創建一個 Test::Unit 類型的 Run 配置。
圖 12. RDT 包含 Test::Unit Run 配置
在運行這個測試時 ,可以獲得與 Java 單元測試相同的支持元素,包括左下角與 JUnit 相似的面板。
圖 13. 在 IDE 中運行的單元測試示例
在 Ruby 中還可以 創建 TestSuites。TestSuites 是定義套件方法的 Ruby 類,這個方法返回 TestSuite。TestSuite 由在 每個 TestCases 中自動定義的套件組成。清單 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 的例子不同,套件作為單獨的應用程序運行。Ruby 有兩種顯示 TestSuite 結果的方法。第一種是 Console Test Runner,它在控制台輸出結果。第二種是 Tk TestRunner,它創建一個對話框來顯示測試 結果。Tk TestSuite 對話框見圖 14。
圖 14. 圖形化的 TestSuite 對話框
未來的發展
RDT 的當前版本是 0.50。它的開發人員正在為下一個版本 0.60 而努力。下一個版本中計劃的改 進包括:
代碼折疊 —— 可以將類和方法的代碼折疊起來。
大綱視圖 —— 更詳細,支持局部變量。
RI 視圖 —— 從 一個 RDT 視圖使用 Ruby 的 ri 實用程序。
任務標記 —— 在 Ruby 注釋中為可配置的關鍵字(比如 TODO、FIXME)創建任務。
編輯器改進 —— 自動補齊方括號、圓括號和單/雙引號; 更好的代碼輔助。
審查的快捷方式 —— 對 Debug 會話期間經常使用的審查提供可 配置的快捷方式,比如顯示對象的所有方法、全局變量,等等。
下一個版本將更好地使用 JRuby 字節碼編譯器。JRuby 項目可以將 Ruby 代碼編譯為 Java 字節碼。這意味著 RDT 的下一版本將更容易 集成到 Eclipse 環境中,提供更好的支持。
結束語
Pragmatic Programmer: From Journeyman to Master 一書中最出色的建議之一是:您應該每年學習一種新的編程語言從而跟上潮流, 並且通過新語言學習一些新知識。Ruby 就快要廣泛流行了,這在某種程度上是由於 Ruby on Rails 項目 獲得了成功。到了將 Ruby 加進您的工具庫的時候了。RDT 是您掌握 Ruby 的好幫手。