期刊/重新探討Cakephp,Ruby on Rails與MVC(上)
出自台灣中等學校資訊管理人學會
目錄 |
[編輯] 摘要
- 投稿日期:2007/04/12
- 作者:李開文
[編輯] 重新探討Cakephp重新探討Cakephp,Ruby on Rails與MVC(上)
[編輯] 關於Model的問題
去年,我還在用cakephp的時候,我注意到這篇文章
http://mk.netgenes.org/archives/230/
當然那個時候,我相當贊同這篇文章的論點,也有回應他。 接著我就開始進行大概半年的專案,當然最後也有成果,我是使用cakephp,所以那個時候也有寫了這一篇。
其中一張圖,我也有提到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
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,一旦頁面變多,就會發現過多重複混亂的程式碼。
依照軟體工程的方式,大概會是以下的流程
- 需求分析
- 設計
- 實做
[編輯] 權限系統的實例
在介紹實例之前,要先提到幾個前提。通常小的應用程式都不會發生以下我說的事情,除非真的寫的亂七八糟了。但是如果是中大型的應用程式,例如說三人以上共同開發,或是有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有啥不一樣。
