天天看點

Rails 案例研究

Rails 案例研究

Rails 開發與 Java 程式設計的比較

Rails 案例研究
Rails 案例研究
Rails 案例研究
Rails 案例研究
文檔選項
Rails 案例研究
Rails 案例研究
Rails 案例研究
未顯示需要 JavaScript 的文檔選項
Rails 案例研究
Rails 案例研究
将此頁作為電子郵件發送

級别: 中級

Bruce Tate ([email][email protected][/email]), CTO, WellGood LLC

2007 年 4 月 24 日

Ruby on Rails 開發和 Java™ 開發有着本質的不同。在跨越邊界 系列的最後一期中,Bruce Tate 将概述使用 Rails 從頭開發一個複雜、可伸縮的 Web 站點時所發現的二者的主要差異。

Rails 開發人員常常把 Java 開發人員看作是沉悶而勞碌的老古董。而 Java 崇拜者則常常認為 Ruby on Rails 隻是一個玩具,根本不能用于任何嚴肅的軟體開發。作為一名對這兩種技術都有着廣泛使用經驗的顧問,我認為真實的情形介于這兩種觀點之間。由于跨越邊界 系列文章即将結束,是以我打算對它們再作一次比較。本文并非考察某種特殊的技術或語言,而是主要介紹我目前正在從事的項目,并将它與我以前從事的 Java 項目進行比較。另外,我建議您閱讀“跨越邊界”系列的前幾期文章,對相關主題作更深入的了解。這種直接的說明可讓您在二者之間權衡利弊,并可能使您在資料庫 Web 應用程式 green-field 的開發中通過使用 Rails 獲益。

業務問題

Rails 案例研究
關于本系列 在 跨越邊界 系列文章中,作者 Bruce Tate 提出這樣一種觀點,當今的 Java 程式員們可以通過學習其他方法和語言更好地武裝自己。自從 Java 技術明顯成為所有開發項目最好的選擇以來,程式設計前景已經發生了改變。其他架構影響着 Java 架構的建構方式,從其他語言學到的概念也可以影響 Java 程式設計。您編寫的 Python(或 Ruby、Smalltalk 等語言)代碼可以改變編寫 Java 代碼的方式。 本系列介紹與 Java 開發完全不同的程式設計概念和技術,但是這些概念和技術也可以直接應用于 Java 開發。在某些情況下,需要內建這些技術來利用它們。在其他情況下,可以直接應用概念。具體的工具并不重要,重要的是其他語言和架構可以影響 Java 社群中的開發人員、架構,甚至是基本方式。

不論是 Ruby on Rails 架構還是任何 Java 架構都不能解決所有問題。為了提高成功的幾率,需要長期、細緻地考察業務問題,了解周圍的各種假定情況,以及了解您的團隊。隻有這樣才能選出正确的語言來進行開發。

去年,Arvato Systems 聘請我帶領團隊建構 ChangingThePresent.org,它是一種新平台,用于将非赢利性團體和捐贈人組織在一起。與很多 Internet 公司一樣,我們向客戶展示了可購買的實際産品。與其他公司不同的是,這些 “産品” 指的是提供機會,比如:一名×××研究員一小時服務收費 50 美元、幫助盲人收費 30 美元,或者保護一英畝雨林一個月收費 20 美元。我們面臨兩大挑戰:一份很緊湊的時間表和長期的複雜性。

開發工作從九月份開始,要求必須在十一月份之前建立起一個站點,以便有機會趕上聖誕節期間的通信量高峰。(最終我們超出了十一月份這個期限兩星期。)在其他開發語言中,基于 Java 的解決方案可能要花費 6 到 18 個月才能完成這一任務。是以生産力是一個很重要的考慮因素,這與 Java 部署思想相悖。

通過對競争對手和項目的考察,我們了解到:我們希望能夠每天給站點帶來幾百萬次點選的通信量。而我們需要每天有幾十萬次成功的點選,是以可伸縮性也是一個考慮因素。這與 Java 部署思想相符。

最後,我們了解到:釋出初始站點隻是一個開始。我們隻實作了總體規劃的百分之三。是以我們所選的技術需要根據複雜性和負載作出一些調整。我認為 Ruby 語言在複雜性方面會更易于調整,因為它提供了對更進階語言和特性(如開放類)的支援,以及具有更少配置需求和更簡單、內建化程式設計模型的 Rails 架構。

雖然我們面臨着時間和可伸縮性方面的挑戰,但是也擁有一些其他的有利因素。我們擁有一張完全空白的候選名單:可以選擇想要的任何技術、任何團隊。可以定義項目、教育訓練和全部的技術。我們可完全自由地作出選擇。

Java 語言是一種優秀的通用語言。它總是應用于新的技術領域,如嵌入式系統和移動裝置。Java 語言在廣泛關注的內建方面也表現優秀。它具有高性能、流行并受到平台的良好支援。但是正如您在本系列中所了解到的那樣,Java 語言并不是用于資料庫支援的 Web 應用程式的 green-field 開發的最佳選擇(請參閱文章 “動态類型語言中的 Web 開發政策”)。

相比之下,Ruby on Rails 架構則是新的。并沒有很多人使用 Rails 開發高通信流量的站點,并且幾乎不存在什麼使用 Rails 多年開發項目的經驗。但它仍然是一種高生産力的資料庫支援的 Web 應用程式開發的架構。最後,盡管我們對 Rails 缺乏開發長期項目的經驗和并未得到廣泛部署有所顧慮,但那份緊湊的時間表驅使我們選擇了 Ruby on Rails。

作出這個決定之後,我們發現招募項目人才非常容易。我們還發現早期的生産力優勢非常顯著 —— 甚至比預期的還要好。我們确實遇到了一些早期的穩定性問題,是以加強了測試工作的力度(請參閱文章 “在內建架構中進行測試,第 1 部分” 和 “在內建架構中進行測試,第 2 部分”)。此後穩定性得到了極大的改進。

Rails 案例研究
Rails 案例研究
Rails 案例研究
Rails 案例研究
回頁首

原理

每個架構設計者都使用一組假定來構造該架構的重寫原理。學習遵守該原理的限制可使您愉快地進行程式設計,而挑戰這些限制則會使您的程式設計受挫。Rails 架構和 Java 架構擁有很多不同的原理。

Rails 是一種內建架構,需要使用高度利用 Ruby 語言的動态本質(請參閱 “Ruby on Rails 的秘笈是什麼? ”)。Rails 開發人員強調架構的生産力特性而不是工具特性,并且常常将 Web 架構看得非常簡單,在本系列的前幾篇文章中您已了解到這一點。Java 設計者通常必須分塊地組合開發環境,獨立地選擇持久性、Web 和內建層。他們通常嚴重地依賴工具來簡化核心任務。Web 架構設計趨向于較為複雜。

完全內建

Java 架構往往是解決一個小問題(比如持久性或檢視組織),而 Rails 則是一個內建環境。Rails 開發人員的優勢在于不必解決與許多不同架構內建的問題。大多數 Hibernate 開發人員陷入了過早關閉與 Java Web 架構之間的連接配接的陷阱。Rails 視圖架構是從頭建構的,以便與 ActiveRecord 內建(Rails 持久性架構)。當您考察用于 Web 服務、配置和插件的 Rails 架構時也會發現類似的經驗。Java 程式設計支援各種不同的架構,對于所有這些架構使用不同的內建政策。

Java 開發人員的優勢在于選擇。如果您需要從頭建構一個架構,則可能要考慮使用基于 SQL 的解決方案用于資料庫內建(如 iBATIS 或 Java 程式設計中基于 JDBC 的包裝架構之一)。反過來,如果要使用一種古老的模式進行程式設計,則可能要使用對象關系映射架構(如 Hibernate)。相比之下,如果您使用 Rails,則擁有一個主要選擇:ActiveRecord。這意味着 Java 架構提供了更多的選擇,有時能提供更好的內建開發項目的解決方案。但是由于我們要開發一個 green-field 項目,是以選擇算不上是一個問題。

一種動态語言

Rails 原理的下一個主要部分是動态程式設計語言(請參閱文章 “Java 模型以外的類型政策”)。Java 工具往往可以有效地使用 Java 類型模型提供的額外資訊。工具可以識别錯誤和有效地重構代碼。Rails 還可有效地利用程式設計語言的優點。Ruby 是一種建構特定于域的語言(DSL)的理想語言(請參閱文章 “活動記錄和 Java 程式設計中特定于域的語言”)。Rails 集中使用 DSL 來完成從構模組化型對象之間的關系到指定自定義元件(如狀态機器或可上傳的圖像)的所有工作。動态語言常常更加簡潔,是以 Rails 項目比 Java 項目要簡練得多,可讓使用者更簡練地表達代碼和配置。在 ChangingThePresent.org 項目中,我們發現技術頂尖的程式員可達到更高的生産力,但是我們确實需要招募經驗更豐富的開發人員。我對這種妥協非常滿意。

傳統的 Java 程式員對 IDE 有着近乎虔誠的熱愛,造成這一現象有充分的理由。IDE 提供了文法的完整性檢查、修正了小錯誤并提供了增量編譯以便更快地完成編碼、編譯、部署和測試這樣的周期。最近幾年來,開發環境開始更好地利用編譯循環和靜态類型提供的資訊。IDE 現在編輯抽象文法樹(AST),而不是(或者同時)編輯代碼的文本表示。這一政策允許使用強大的代碼重構工具,而使用靜态類型語言的同樣方法來實作此功能則困難得多。

靜态類型确實能更好地使用工具,但是也存在缺點。強制使用靜态類型通常需要編譯器,而編譯步驟必然會降低生産力。使用 Rails,我可以更改一行代碼并重新加載浏覽器,就可立即看到更改的結果。與 Java 開發人員相比,大多數 Ruby 開發人員隻使用一種很好的編輯器。TextMate 是最流行的 Ruby on Rails 編輯器,它提供了文法突出顯示、代碼完整性檢查,以及一些頻繁使用的結構的良好的模闆支援。而當發現可将所有簡單的基于 Ruby 的腳本(用作基本的 Rails 工具包)放入編輯器中時,您會更加喜出望外。與純粹的調試器不同的是,我可以使用斷點腳本,該腳本可停止特定的應用程式,進入一個 Ruby 解釋程式,我可在其中調用方法、檢查變量的值,以及甚至在恢複執行之間修改代碼。

簡單的架構

傳統的 Web 端 Java 架構包括:一個用于域對象和資料通路對象的層、一個提供業務級 API 的外觀層、一個控制器層和一個視圖層。此架構比典型的 “模型-視圖-控制器” 架構(使用 Smalltalk 語言最早建立)稍微複雜一些。相比之下,Ruby on Rails 包括一個使用 ActiveRecord 設計模式的模型層、一個控制器層和一個視圖層。我們喜歡易于獲得的 Rails 方法。它更加簡練并且帶來額外的複雜性和錯誤的機會更小。

慣例優先原則

Java 架構通常可以自由地使用 XML 配置,而 Rails 主要使用慣例來避免可能的配置。在程式員必須指定配置的位置,Rails 通常依賴 Ruby(常常以 DSL 形式)來提供配置。對于 green-field 開發,我發現慣例優先于配置是很有意義的。該政策為我省去了很多行代碼,更簡化了必須編寫的代碼。估計我們所需的配置隻有傳統 Java 應用程式中所指定的十分之一。我們有時會損失一點靈活性,但這并不足以抵消使用此政策帶來的節省。

總而言之,Rails 架構的原理适合解決 ChangingThePresent.org 項目中的問題。內建的各種工具讓我可以利用架構實作更多的功能而無需自己進行過多的內建。“慣例優先原則” 為我節省了配置站點的時間。動态語言為經驗豐富的開發人員提供了更多的能力和靈活性,同時也使他們能夠利用更少的代碼表達更強大的思想。該架構适合于我們團隊的能力和要解決的業務問題。

Rails 案例研究
Rails 案例研究
Rails 案例研究
Rails 案例研究

持久性

Java 和 Ruby 語言的最流行的持久性架構可以比任何其他特性更好地闡明 Java 和 Ruby 經驗之間的差別,Java 開發人員通常使用 Hibernate,它是一種對象關系映射架構。通過 Hibernate,您可擷取現有的模型和模式并使用注釋或 XML 表達二者之間的映射。Hibernate 類是簡單傳統 Java 對象(POJO),它的每個對象派生自一個通用的基類。大多數配置是顯式的,使用注釋、XML 或二者的某種結合。

而 ActiveRecord 是一種包裝的架構,就是說每個類都是現有類的包裝器(請參閱文章 “研究活動記錄”)。ActiveRecord 根據關聯表的内容(如表中每列的一個屬性)自動地向模型對象添加特性。所有的類都從一個通用的基類繼承。ActiveRecord 主要利用通用約定來推斷配置。例如:

  • ActiveRecord 利用類名的複數形式來推出表名。
  • 主鍵的名稱為

    id

  • 清單的排序順序由

    position

    字段決定。

對象關系映射是使用遺留模式(可能定義時沒有考慮對象模型)時的最佳解決方案。但是當您能為應用程式顯式地設計資料庫模式時,您通常不需要映射架構了。我們将 ActiveRecord 看作我們的一個巨大優點。我們可以包含關系資料庫,需要時轉入 SQL 并在适當的時候退出。

遷移

Rails 遷移使我們能夠用代碼表示模式的兩個版本之間的差别,和它們所包含的資料之間的差别(請參閱文章 “Rails 遷移”)。對每個遷移都進行了命名和編号。可在任何時候恢複到任何版本。遷移有以下一些确切的優點:

  • 産生錯誤代碼時可恢複到一個舊版本的模式。
  • 用代碼而不是 SQL 來表達模式,更便于我們使用。
  • 在最大程度上與資料庫獨立。

但是遷移也有一些限制。如果兩個開發人員同時建立遷移,則編号會出現混亂,是以我們必須手動處理。我們通過有效的通信來使這些問題最小化:團隊成員建構需使用遷移的新模型時發出通知。但是這個模型依賴于團隊的開發人員較少或遷移進展較慢的情況。

ActiveRecord 還有其他的限制,其中一些是故意作出的。Rails 的建立者認為:資料庫的限制群組成應歸入應用程式而不是資料庫,這種思想帶來了一些副作用。ActiveRecord 使用視圖的情況不是很好:建構過程(克隆模式、複制測試資料并運作測試)并不能正确地進行複制。ActiveRecord 在使用參考完整性限制的某些場合也會出現問題,因為某些類型的關聯可能連接配接到多個資料庫表。跨越複雜模型進行預先加載很複雜,通常在連接配接多行時需要使用 SQL。繼承也受到限制:使用 ActiveRecord 時,我被迫使用單表繼承 映射政策,而該政策并不總是最佳選擇。(參見 參考資料)

所有的持久性政策都充滿了妥協。我認為 ActiveRecord 實作了一組有效的妥協,常常選擇了簡單性。總而言之,ActiveRecord 和遷移是我們的積極推動。我們可以快速地建構解決方案,我們擁有足夠的 SQL 通路權可在需要時改進系統性能。但是當 ActiveRecord 并不總能應對挑戰時,最好将 Rails 應用于使用老舊模式的項目。一些替代的持久性模型正在出現,包括 RBatis,一種 iBATIS Java 架構的端口(參見 參考資料)。現在讨論 RBatis 的有效性還為時過早。

Rails 案例研究
Rails 案例研究
Rails 案例研究
Rails 案例研究

結束語

對于我的團隊和項目來說,Ruby on Rails 被證明相當有效。我還不知道這個項目的最終規模如何,因為撰寫本文時該系統才運作 3 個月。現在隻是開始增加通信量。但是我們對生産力卻很了解。我知道團隊的預算比競争公司(這些公司常常使用 Java 解決方案)的要低得多。我對我們的生産力也很有信心。

通過跨越邊界 系列,我向您介紹了 Java 領域以外的語言和解決方案。但程式員畢竟是技術人員。每個高明的技術人員的工具包中都應包含适用于每個解決方案的廣泛的工具集。除工具外,本系列中介紹的觀點也為您展示了一些其他思路。現在一些架構設計者甚至将 Seaside、Rails 中的技術甚至 JavaScript 應用于 Java 架構中。找機會進行同樣的應用,繼續 “跨越邊界”。

繼續閱讀