首頁‎ > ‎電子期刊‎ > ‎Ruby on Rails‎ > ‎

重新探討Cakephp,Ruby on Rails與MVC(上)



摘要

  • 投稿日期:2007/04/12
  • 作者:李開文

重新探討Cakephp重新探討Cakephp,Ruby on Rails與MVC(上)

關於Model的問題

去年,我還在用cakephp的時候,我注意到這篇文章

http://mk.netgenes.org/archives/230/

當然那個時候,我相當贊同這篇文章的論點,也有回應他。 接著我就開始進行大概半年的專案,當然最後也有成果,我是使用cakephp,所以那個時候也有寫了這一篇。

[1]

其中一張圖,我也有提到MVC的寫法,很明顯地我那時候還是認為Model是形同於表格的快取。之所以會這樣認為,也是跟上面的文章一樣。不能否認現在大多數做Web的都還是偏向做做網站,簡單的資料CRUD,將資料庫的資料撈進Controller,簡單地處理就可以達成需求,根本不需要啥複雜的商業邏輯。

那個時候確實知道這跟傳統的MVC觀念根本不一樣,但硬要去說不一樣不如說是一種適應在Web Framework上的變形。畢竟現在cakephp還是用這樣的方式。

我的專案雖然看起來是簡單的管理系統,但確有複雜的程序控制,資料檢查產生的商業邏輯。隨著專案進行,我逐漸發現這樣是不能解決問題的。 Cakephp的Model傳回來的是Array,並不是物件,這樣讓我完全無法將商業邏輯寫在Model,在這種情況之下,Model就真的只剩下 table快取的功能。


Cake Blog Tutorial我們可以看見

<php> class PostsController extends AppController {

 
var $name = 'Posts';
function index()
{
$this->set('posts', $this->Post->findAll());
}

} </php>

輸出

 
// print_r($posts) output:
Array
(
[0] => Array
(
[Post] => Array
(
[id] => 1
[title] => The title
[body] => This is the post body.
[created] => 2006-03-08 14:42:22
[modified] =>
)
)
...
)

這樣子的情況下,是無法撰寫出$posts[0]->submitToGoogleBlog()這樣的事情的。我只好乖乖地將這些功能全部寫在controller裡。

此外,我再仔細觀察了Cakephp對於Model Behavior的支援,發現他也只是將一些常見的Model CRUD的支援function提取到Behavior,讓設計師可以彈性的自訂。不過這樣是不夠的,因為這麼做就好像是將Model 1的時候一直線的程式撰寫,進行重構,將重複使用的function利用framework及class分群組而已。

而在重新看了三個php Framework的程式碼後,我大概重新整理了一下他們在model上的差異。


Cakephp Symfony PHP on Trax
受...技術影響 基本上是Ruby on Rails 不過也參考了許多MVC的實做 基本上是Java Struts 不過也參考了許多MVC的實做 與Ruby on Rails幾乎一樣
Model對資料庫存取方式 自行撰寫各個資料庫抽象層函示庫 使用Propel ORM函示庫 MDB2資料庫抽象層函示庫加上一些修正
Model對資料庫設定方式 簡單設定 複雜的XML 簡單設定
Model是否能進行 非資料庫的外部資料來源存取
Model是否能即時取得 資料庫Schema
Model回傳型態 Array Object Object
Model物件取回效率 (依照執行的程式碼數量)
Model物件快取

 MVC觀念釐清

接下來我會從軟體工程的Waterfall Model探討,為啥需要這些東西。

我們先看看Wikipedia怎樣講。

http://en.wikipedia.org/wiki/Model-view-controller

ModelViewControllerDiagram.png

MVC在1979年就由Reenskaug發 明,當時他還在Xerox寫smalltalk。接著這個pattern就影響了Microsoft的MFC,他的Document/View架構就是 MVC。而實際上如果嚴格地去看,如果你發現某一個語言有類似畫面,程式碼,資料來源拆開的作法,多半都是MVC的觀念。例如說C#的視窗程式使用了 partial class,利用這來讓你盡量不要看見Form的程式碼。但實際上form的程式碼你還是可以改,IDE也還是自動產生C#程式碼。有些人認為MVC一定 要使用三種不同的語言或技術,也是不對的觀念。

就以前Model 1 的寫法,是將邏輯資料與畫面混雜在一起。而在MVC(Model 2),就利用控制器(controller)分開畫面(view)及資料(model)。Controller有幾項工作

  • 將Model物件取回,傳遞給View來產生實際頁面
  • View的驗證
  • Model的例外狀況
  • 處理View的輸入
    • 新增:建立一個Model的實體
    • 修改:修改特定ID的Model物件
    • 刪除:刪除設定ID的Model物件
    • 最後都是得儲存

Model在MVC裡有一個重要的工作,本來就不是拿來做table快取用。Model的全名可以說是「應用程式領域物件模型」(Application Domain Object Model),通常都是代表你的應用程式所使用的類別。如果採用ORM(Object Relational Mapping)的觀念,也就是物件的屬性會對應到資料庫的欄位,而每一筆記錄就是一個物件了。

但是物件光有屬性是不夠的,物件的方法要從哪來呢?實際上當你在設計的時候,就應該要考慮到你的Model類別應該要進行怎樣的程式行為。這些行為我們通常都叫做商業邏輯(Business Logic),也叫做領域邏輯(Domain Logic)。換句話說就是專為你的Model類別所寫的方法。在三層架構(3-tier architecture)中,通常會提到表現層,邏輯層,資料層。資料層就是熟知的資料庫,表現層大家也都會認為就是View,可是有些時候邏輯層大家 會誤以為就是Controller,而將Business Logic寫在Controller,一旦頁面變多,就會發現過多重複混亂的程式碼。

依照軟體工程的方式,大概會是以下的流程

  1. 需求分析
  2. 設計
  3. 實做

權限系統的實例

在介紹實例之前,要先提到幾個前提。通常小的應用程式都不會發生以下我說的事情,除非真的寫的亂七八糟了。但是如果是中大型的應用程式,例如說三人 以上共同開發,或是有20個table,或是上百個頁面...當然這個準則見仁見智,只是當你覺得你的應用程式越寫越複雜的時候,就要注意了。而且通常這 個情況也會發生在許多快速開發的專案上,如果沒有經常重構,也會很容易陷入這種泥沼中。

需求分析

假設我要做一個系統,裡面必須包含權限控制,這個系統有100個頁面。有關檢查頁面是否已登入的情況,幾乎全部的頁面都一定需要。有關使用者認證,我必須有選擇性第三方認證的功能。

實做的部分,我打算採用Ruby on Rails。

DB範例 雖然資料庫實做不應該先討論,但為了後面程式實做可以對照,我先放在這。

根據需求,我應該要有以下table:users,roles。 users table:

id username password name role_id
1 admin $5$dhdsf43d4f3as8d4f3 Kiwi 1
2 guest $1$a6s4df86asd4f8asd4 Guest 2

roles table:

id name
1 Administrator
2 User
3 Guest


 結語

本集我們說明了使用cakephp進行Web應用程式開發的觀念問題,最後也以一個設計實例引導各位瞭解實務上的問題。下一集將為各位詳細說明使用Ruby on Rails來開發,在實務上到底和cakephp有啥不一樣。


Comments