2.Rails應(yīng)用程序的架構(gòu)

Rail的有趣點(diǎn)之一是它對你的web應(yīng)用程序架構(gòu)實施了一些強(qiáng)制性規(guī)定。令人驚訝的是,這些規(guī)定反而能讓你很容易地創(chuàng)建應(yīng)用程序-非常地容易。讓我們看看為什么?

2.1模型,視圖和控制器

追溯至1979年,Trygve Reenskaug 提出一種開發(fā)交付式應(yīng)用程序的新架構(gòu)。在他的設(shè)計中,應(yīng)用程序被分為三種類型的組件:模型,視圖和控制器。

模型負(fù)責(zé)維護(hù)應(yīng)用程序的狀態(tài)。有時候這種狀態(tài)的持續(xù)時間是短暫的,僅存在與用戶的交互過程中。但有時候這狀態(tài)又是持久的,它存儲在應(yīng)用程序之外,經(jīng)常是在數(shù)據(jù)庫。

一個模型通常不只是數(shù)據(jù);它還執(zhí)行了應(yīng)用在數(shù)據(jù)上的規(guī)則。例如,若規(guī)定少于$20的訂單不予折扣,則模型將實行此規(guī)則。這是很有意義的。在模型中貫徹這些業(yè)務(wù)規(guī)則,我們能確保在應(yīng)用程序中數(shù)據(jù)的有效性。 因而模型扮演著數(shù)據(jù)檢查及其數(shù)據(jù)存儲雙重角色。

視圖負(fù)責(zé)產(chǎn)生一個用戶界面,其通常是基于模型數(shù)據(jù)。例如,一個網(wǎng)上商店在分類中顯示一列商品。這些列表通過模型被訪問,但它是作為一個視圖(此視圖從模型中讀取列表)展示在終端用戶面前。雖然根據(jù)不同的輸入數(shù)據(jù)可以在用戶面前展示不同的視圖,但視圖本身無法改變這些數(shù)據(jù),它要做的唯一工作就是顯示數(shù)據(jù)。為了達(dá)到不同目的,多個視圖也可能存取同一個模型數(shù)據(jù)。對在線書店,在分類頁面有個視圖用于顯示產(chǎn)品信息,同時也有若干視圖供管理員新增和編輯產(chǎn)品。

控制器從外部世界接收事件(通常是用戶的輸入),和模型進(jìn)行交互,并給用戶顯示適當(dāng)?shù)囊晥D。

這三種,模型,視圖,和控制器――形成了大家熟悉的MVC架構(gòu)。

MVC最初來源于傳統(tǒng)的GUI應(yīng)用程序,在那里開發(fā)人員發(fā)現(xiàn)分離關(guān)注點(diǎn)可以減少耦合,而這反之又可以使代碼變得容易編寫和維護(hù)。每個概念和動作將在一個眾所周知的位置被表達(dá)。使用MVC就象建造已搭好鋼架的摩天大樓――只需進(jìn)一步填充剩余零件。

在軟件開發(fā)世界中,我們經(jīng)常在往前趕路時忽視了過去好的想法。當(dāng)開發(fā)者第一次開始建造web應(yīng)用程序,他們退回到寫集成電路程序了,在一個大的代碼塊中混雜著展現(xiàn),數(shù)據(jù)存儲,業(yè)務(wù)邏輯,和事件處理。但是想法慢慢又回到了原來上了,人們開始把已經(jīng)存在了20幾年的MVC思想應(yīng)用在web應(yīng)用程序的架構(gòu)上。這樣的結(jié)果就出現(xiàn)了WebObject,struts和Java Server Faces 等框架。所有的這些都是基于MVC的思想上的。

Ruby on Rails也是一個MVC框架。Rails強(qiáng)調(diào)應(yīng)用程序的模型,視圖和控制器之間的分離――在應(yīng)用程序執(zhí)行的時候把它們組織在一起。關(guān)于Rails有趣的是它把這些組織在一起是基于智能的默認(rèn)設(shè)置而不需要你編寫任何的外部配置文件。這就是Rails哲學(xué)的一個例子,約定俗成優(yōu)于配置。

在一個Rails應(yīng)用程序中,接收到的請求首先被發(fā)送到一個路由器上,它用于決定在此應(yīng)用程序中,請求將發(fā)送至哪里,及如何解析請求本身。最終,這個過程在控制器代碼中決定了一種相應(yīng)方法(在Rails中通常稱為“動作”)。動作將根據(jù)請求查找數(shù)據(jù),它可以和模型進(jìn)行交互,并且它也可能導(dǎo)致其它的動作被執(zhí)行。最后這個動作給視圖準(zhǔn)備了信息,呈遞給用戶。

在下一頁的圖2.2上顯示了Rails是如何接收一個請求的。在這個例子中,假設(shè)在分類中顯示產(chǎn)品,用戶剛剛點(diǎn)擊了其中一個產(chǎn)品的“Add To Cart”按鈕。這個按鈕返回了一個http://my.url/store/add_to_cart/123鏈接給我們的應(yīng)用程序,123是我們選擇的產(chǎn)品的內(nèi)部編號。

路由器組件接收了請求并把它分為若干部分。在這個簡單的例子中,路徑(指的是/store/add_to_cart/123)的第一部分store作為控制器的名稱,第二部分add_to_cart作為動作的名稱,最后部分123,約定俗成為內(nèi)部變量稱為編號。根據(jù)分析的結(jié)果,路由器在控制類StoreController中調(diào)用了add_to_cart方法。

add_to_cart()執(zhí)行了用戶的請求。從而它查找到了當(dāng)前用戶的購物車,并要求模型查找產(chǎn)品編號為123的信息,最終把產(chǎn)品添進(jìn)購物車。

現(xiàn)在購物車?yán)锒嗔藗€新產(chǎn)品,我們要把它顯示給用戶看。控制器安排視圖從模型中取得了購物車的對象,并且調(diào)用視圖代碼。在Rails中,這個調(diào)用通常是隱含的。再次依據(jù)約定把視圖和已知動作連接起來。


以上所述就是一個MVC web應(yīng)用程序。通過一些約定以及功能性的適當(dāng)分割,你將發(fā)現(xiàn)你的代碼更易于操作,你的程序更易于擴(kuò)展和維護(hù)。這看起來是一個良好開端。

如果MVC僅僅涉及如何通過一特定途徑分割你的代碼這個問題,你可能會質(zhì)疑為什么還需要象Ruby on Rails這樣的框架。答案很簡單,Rails為你處理所有低級別的事務(wù),包括所有冗長細(xì)節(jié),使你能集中精力關(guān)注應(yīng)用程序的核心功能。