26 November 2005

RoR 最近熱的不得了,看看現在這個新的 java roller,好像也被 ruby 化了 ^^;

雖然不曾寫過 Ruby 語言,昨天還是花了一個晚上,硬生生的把 The Pragmatic Programmers Agile Web Development with Rails 前面幾章掃過一遍。Rails 的開發的確非常非常的簡單,而且非常的快速,最讓我驚奇的是 (1) 不需要 deployment, restart server (2) 網頁的欄位 "直通" database 欄位。所有改變都是即時的,這真是讓生活在 heavy java 的我羨慕不已。

Rails 的架構很簡單,就是 MVC 而已,可以想像成是 "jsp 加上 servlet 再減去一堆 xml 設定" 的架構。這樣的架構... 呃... 這... 不是好幾年前 java 做過的事嗎? jsp 裡面內嵌 java scriplet (相對於 Rails 的 RHTML),然後 servlet 負責 control (相對於 Rails 的 Controller )。scriplet 寫起來是很快沒錯,但是難看 + 難維護 + 考倒 web designer,java 界早就遠遠避開這樣的 "bad practice",朝向 JSTL,或甚至是 component-based 的方向前進。怎麼 Rails 還是這樣搞咧?

Rails 的 Controller,它可以做所有的事情,所以一不小心就可將所有的 business logic 或是 SQL 都擠到 Controller 裡面,也許這樣對快速開發很好,但長期來看,維護性似乎很差。當然,這在 java 界也是一樣,Servlet 或是 Struts's Action 都有可能會出現這種狀況。所以後來便衍生出 EJB, Spring...etc,把所有的 logic 集中到更後端,讓 MVC 的 C 只做簡單的事。對經驗夠的 Rails developer 來說,自然也會將 business logic 和 SQL 塞到 Model 裡去,而不是寫在 Rails Controller 裡。那麼,Rails 的 Model 會長成什麼樣子呢?

我們先來看看在 Java 的 Model 裡,對一個 Entity,我們假設是銀行帳戶 "BankAccount" 好了,多半會有一堆相關的成員:

  • BankService -- Bank 相關 use case 的 facade,處理多個 BankAcconnt 物件的方法都在這裡,也包含 transaction,security 等的控管。代表性的方法:transfer(acountA, accountB)
  • BankAccount -- BankAccount Entity 本身,有一些屬性和一性與自己相關的行為,例如 changeBalance()
  • BankAccountDAO -- BankAccout 資料庫存取相關的程式
  • BankAccountDTO (or BankAccountActionForm) -- View 端或遠端使用的純資料物件 (視情況可有可無)

反觀 Rails 的 Model,它的大部份成員都是直接由 Active Record (O-R Mapper) 所構成的。Active Record 提供 Model 存取 DB 的能力,所以設計下來會變成只剩一個物件:

  • BankAccount -- BankAccount Entity 本身,同時也是 DAO,同時也是 Service,同時也是 DTO。

很簡單,就通通塞在一起就是了。所以你會在 Rails 裡寫 BankAccount.find_by_name(), BankAccount.transfer(...), my_bank_account.change_balance()... 等等。method 通通屬於 BankAccount 一個物件所有。啊~~~ 看起來很簡單... 但是你可以想像到最後,一個物件會變的有多大?一些 method 有 transaction,一些 method 會動到資料庫,一些 method 只是改改 attribute,然後再互相 call 來 call 去... orz... 如果混在一起寫比較好,Java 界早就這樣做了,也不會再去衍生 Service/DAO 之類的東西了。

再來是 Active Record,一個簡化版的 O-R mapper,先不論它的設計是否好不好... 它欠缺一個很重要的功能:跨 database 的能力。如果你的產品要跨 DB,那麼 Rails 現在跟你是無緣的...

嗯?我有提到 i18n 嗎? 整本書裡沒看到一個 i18n 相關的字眼... 所以一樣... 如果你的產品要支援 i18n,那麼 Rails 現在跟你是無緣的... (不曉得中文 Big5/UTF-8 的支援能力如何?有人試過嗎?)

ok... 基於從來沒寫過 Ruby on Rails... 所以我也只能對書上看到的寫一些感想... Ruby on Rails 與 java 比起來簡化了許多,不過,感覺起來那只是 Rails 將 "需求" 簡化後自然而然的結果... 試想如果你想用舊的 database (舊的schema, 一堆 store produce)、你想 parse 或是產生 word 或是 excel 的檔案、你想 i18n、你想... etc。這些東西用 Rails 來做,那 Rails 就沒辦法這麼簡單了...

Ruby on Rails 紅歸紅,但是能適用的場合似乎還是不多。