Ruby 和rail:回歸框架
Ruby和 rail是非常簡潔的,很容易,很豐富。我無法避免的連續看到以及聽到以上這樣的說法。比如 說,Bill Walton 寫的Rail回顧上關於Ruby的文章提到:“如果我告訴你當你使用Rail開發一個Web應用 程序可以比你使用一種特定的Java框架開發要快至少十倍的時候,你會怎麼想?”
在嘗試了RnR之後,我發現這就是一個伴隨舊技術的非常經典的框架:
· Ruby是一種非常有力量的語言,就像Smalltalk。我選擇靜態語言。
· 搭建的材料是被動代碼生成。就像是IDE wizards或者AppFuse。我選擇動態代碼生成,或者是更好 的——根本就不需要代碼生成。
· 關系數據庫中心:編碼發生器和ActiveRecord在表中會被首先想到,然後是在類別中被想到。我選 擇一種僅僅面向對象的,就像是Hibernate、JPA 甚至是ODBMS。
· MVC:我正在尋找比舊式MVC框架更新很好的工具。
Java的問題:Java開發者
在Java的世界中,生產力是文化問題,而不是技術問題。這就是所謂的這不是Java的錯,而是我們的 錯,我們作為Java開發者需要設計出非常漂亮的體系,以適用於任何地方的GoF模式、使得任何工具都是 可再度使用的、把三層架構放到我們所有的系統中以及使用web服務器。我們不是在尋找最直接的方法, 所以我們就沒辦法發現最直接的方法。但是Java、是一種非常簡單的語言,使得我們很輕易就可以接近軟 件開發。
Java生產力:其它的方法
解決生產力的一個方法是使用驅動模型。這就是模型環節的開發,僅僅是我們應用程序中的模型環節 ,就可以使用框架來生產所有的應用程序。MDA 、OpenXava 、Trails、 NakedObjects、 Roma框架和 JMatter都是采用的這種方式。
目標
這是所需要應用程序的主要界面:
圖一
基本上,應用程序推測需要做三件事情:
· 列出所有准則的清單
· 創造新准則和編輯現有的准則
· 為某個類別指定合適的准則
Ruby on Rails第一次沖刺
使用RnR的第一步是創建一個新的項目,在命令行你需要輸入:
$ rails cookbook2
現在你必須創建以及配置你的數據庫。
現在是時間輸入你的第一行代碼了,在這個例子中使用SQL代碼:
drop table if exists recipes;
drop table if exists categories;
create table categories (
id int not null auto_increment,
name varchar(100) not null default '',
primary key(id)
) engine=InnoDB;
create table recipes (
id int not null auto_increment,
category_id int not null,
title varchar(100) not null default '',
description varchar(255) null,
date date null,
instructions text null,
constraint fk_recipes_categories foreign key
(category_id) references categories(id),
primary key(id)
) engine=InnoDB;
顯然你需要在數據庫上面執行這些語句。
最後的步驟是生成Ruby代碼,你只需要執行O.S框架的下一個命令:
$ ruby script\generate scaffold recipe recipe
$ ruby script\generate scaffold category category
現在,你已經擁有RnR應用程序的第一個版本,並且准備運行。
很少量的工作,一個簡單的“創建表格”,然後執行向導。讓我們看看結果。
Rails結果
這是應用程序的結果:
圖二
圖三
圖四
少量的工作,少量的結果。
JPA on OX的第一次沖刺
繼續使用OpenXava。使用OpenXava的第一步是創建新的項目:
$ ant CreateNewProject.xml -Dproject=CookBook
現在你必須創建以及配置你的數據庫。
現在是時間輸入你的第一步代碼了,在這個例子中使用Java代碼:
Recipe.java:
package org.openxava.cookbook.model;
import java.util.*;
import javax.persistence.*;
import org.openxava.annotations.*;
@Entity
@View(members="title; description; date; instructions")
public class Recipe {
@Id @GeneratedValue @Hidden
private Integer id;
@Required @Column(length=100)
private String title;
@Column(length=255)
private String description;
private Date date;
@Stereotype("HTML_TEXT")
private String instructions;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription (String description) {
this.description = description;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public String getInstructions() {
return instructions;
}
public void setInstructions(String instructions) {
this.instructions = instructions;
}
}
Category.java:
package org.openxava.cookbook.model;
import java.util.*;
import javax.persistence.*;
import org.openxava.annotations.*;
@Entity
public class Category {
@Id @GeneratedValue @Hidden
private Integer id;
@Required @Column(length=100)
private String name;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
最後一個步驟是生成數據庫圖表,你只需要執行項目中的一個小目標:
$ ant updateSchema
現在,你已經擁有OpenXava應用程序的第一個版本,並且准備運行。
少量的工作,簡單的POJO,以及執行“更新圖表”。讓我們看看結果。
OpenXava結果
這是應用程序的結果:
圖五
圖六
注意,用戶可以創建更新、刪除、從列表生成PDF、將列表輸入到excel、每一列的命令、大型結果和 過濾數據的支持分頁。而且你可以直接部署,不需要代碼,僅僅是執行一個小目標,JSR-168入口上的應 用程序,以及OpenXava的look & feel能夠適用於入口的look & feel。這就是一個應用程序准備 產出的第一步。
少量的工作,完美的結果。
觀察這裡RnR 與 OX之間的差別,一個冷靜的觀點是在RnR中,你先輸入表,而在OpenXava中先輸入類 別。
控制器
Rails引起basic CRUD的控制邏輯,你在下面可以看到:
圖七
另一方面,OX不會為CRUD生成任何代碼,OpenXava僅有一個屬性代碼,可以執行CRUD和打印,將自動 化配置給所有的實體。你可以書寫你自己的屬性CRUD邏輯,或者你可以為一個特有的實體書寫詳細邏輯, 但是你不會為每一個實體設置控制代碼。使用這種方法,你需要維護少量的代碼,並且你可以改變CRUD獨 立單元的邏輯。
Rails使用合成碼,OX使用屬性代碼。
你可以在OpenXava wiki上面學到更多的OX控制器知識。
增加關聯
為了規范在Ruby中從類別增加關聯,你需要在category.rb中書寫如下代碼:
圖八
以及在recipe.rb中:
圖九
相當簡單。但是,你要做更多的工作,你必須編譯。
cookbook2\app\views\recipe\_form.rhtml
增加如下代碼:
<p><labelfor="recipe_category_id">Category</label><br/>
<%= select("recipe", "category_id", Category.find(:all).collect {|c| [c.name, c.id] }) %></p>:
結果是:
圖十
在這個環節,OpenXava中,你不得不在Category.java中使用JPA規定關聯:
@ManyToOne(optional=false) @DescriptionsList
private Category category;
and in Recipe.java:
@OneToMany(mappedBy="category")
private Collection recipes;
而且你不需要接觸任何類似HTML代碼。應用程序將會顯示如下:
圖十一
你有一個為修改產生的鏈接或者從這裡創建新類別。
不增加任何輔助編碼,如果使用者使用類別單元,他將獲得每一個類別中准則的收集,如下所示:
圖十二
在這裡,RnR應用程序還是不具備這種特性,你需要書寫一些Ruby 和HTML代碼來實現一樣的結果。
在這一塊,RnR 和 OX的主要差別是,在OX中你不需要書寫任何HTML類似的代碼,事實上你連用戶界面 代碼都根本不需要書寫。
精確的基礎資料
Ruby on Rails指導的下一個步驟是為一種特性生成基礎資料。在RnR中你不得不編譯控制編碼從而達 到這個目的。讓我們開看看。
修改以及更新的方法是增加如下代碼行:
@recipe.date = Time.now
The equivalent in OX is adding the @DefaultValueCalculator annotation in model:
@DefaultValueCalculator(CurrentDateCalculator.class)
private Date date;
用一種更為公開的方法獲得一樣的結果
在這裡,盡管RnR中在控制器上放置的代碼,OX中統計基礎資料的代碼,為了確認以及業務邏輯,一般 來說是放在模型上。OX促進從控制器轉移業務邏輯到模型上。
RnR的相關文章中提到:“我改良模型文件,所以我需要重新啟動我們的web服務器”。盡管使用 Eclipse WTP 我只需要按一下Ctrl 加上B,在浏覽器上點擊刷新以便於看見OpenXava應用程序上面模型的 變化。
結論
Ruby on Rails 和 OpenXava之間最主要的差別是RnR是 MVC框架,你不得不書寫模型和控制器。OX是 模型驅動框架,你只需要書寫模型。結果就是更少的代碼,更好的程序。
另一個大的不同點是RnR使用被動代碼生成方式;這就是說,生成代碼,但是這之後如果你想要擴展或 者提煉代碼,你不得不編譯合成碼。OpenXava不需要使用代碼生成器,你所擁有的代碼都是你所書寫的。 你可以在Java的世界中找到提高生產力的方法。