我是web工程師,從剛開始學MVC就深感困惑:
Model、Controller、View三者到底如何互動?真是一個定義不明、含糊不清的名詞。
這讓我研究了很久。最後,發覺它是一個嚴重的誤會。
這個誤會導致了學習和溝通上的代價,請聽我娓娓道來。
web領域,不論前端(client-side)、後端(server-side)、不論什麼程式語言,幾乎所有framework都自稱、或被認為是「MVC」。
有哪些呢?
前端:Backbone.js、AngularJS、Ember.js…
後端:Ruby on Rails、CodeIgniter、Laravel、Django…
真的是這樣嗎?它們全都是MVC嗎?
該怎麼定義MVC呢?
我們先來看看維基百科怎麼說:
MVC模式(Model-View-Controller)是軟體工程中的一種軟體架構模式,把軟體系統分為三個基本部分:模型(Model)、檢視(View)和控制器(Controller)。
嗯,跟大家說的一樣。我們繼續往下看:
模型(Model) 用於封裝與應用程式的業務邏輯相關的資料以及對資料的處理方法。「 Model 」有對資料直接存取的權力,例如對資料庫的存取。「Model」不依賴「View」和「Controller」,也就是說, Model 不關心它會被如何顯示或是如何被操作。但是 Model 中資料的變化一般會通過一種重新整理機制被公布。為了實作這種機制,那些用於監視此 Model 的 View 必須事先在此 Model 上註冊,從而,View 可以了解在資料 Model 上發生的改變。(比較:觀察者模式(軟體設計模式))
看起來有些陌生,整段描述跟你的web開發經驗完全不同,對嗎?
最大的疑問來自這句:
那些用於監視此 Model 的 View 必須事先在此 Model 上註冊,從而,View 可以了解在資料 Model 上發生的改變。(比較:觀察者模式(軟體設計模式))
後面直接叫你去看觀察者模式(observer pattern)。
問題來了:你有在view跟model之間實作observer pattern嗎?
也就是說,你的Model在資料改變之後,能主動通知View嗎?
沒有的話,就根本不符合MVC的定義。
我們現在發現MVC有observer pattern這個必要條件了。
事情嚴重了起來。
client-side framework或許能夠符合這個條件。
以Backbone.js官網範例來說,我們可以這樣在Model上註冊:
book.on({
"change:title": titleView.update,
"change:author": authorPane.update,
"destroy": bookView.remove
});
它的確實作了observer pattern。
但server-side framework呢?
你的Model如何能在發生改變之後去「主動通知」View?
你平常開發web哪有用到server push的技術?
所有server-side framework,從Ruby的Rails;PHP的CodeIgniter、Laravel;到Python的Django,他們全都不是MVC。
它們實作的,是昇陽電腦在1998年提出的「Model 2」。
Model 2名氣不大,在維基百科連中文條目都沒有。我們看看英文條目怎麼講:
Model 2 is a complex design pattern used in the design of Java Web applications which separates the display of content from the logic used to obtain and manipulate the content.
In a Model 2 application, requests from the client browser are passed to the controller. The controller performs any logic necessary to obtain the correct content for display.
它針對web而設計,讓controller進行必要的程序之後,將資料塞進view去呈現。
正是我們server-side框架在做的事情。
也就是說,server-side目前只能實作Model 2;client-side可以實作Model 2,也可以實作MVC。
web工程師最常碰的就是client-side跟server-side框架。結果整個業界把MVC跟Model 2混為一談,都說成MVC。
這帶來了什麼後果呢?
MVC變成一個從初學者到業界工程師,永遠說不清楚、下不了定義的名詞。
這件事對於學習和討論,造成了非常巨大的成本。(參考下方的Q1和Q2)
下次有初學者詢問「什麼是MVC」的時候,怎麼回答才不會害他回家之後「越查資料越混亂」?
Rails is not MVC的作者提出了三種解決方法:
第一個方法是聲稱MVC已經從原始意義改變了,Model 2也可以稱為MVC。如此一來,我們可以用「傳統MVC」或「真MVC」來描述原始的MVC。這是現在普遍的作法,但我不認為改變定義是一個好主意。這幾乎是越搞越亂。
第二個方法是到處推廣Rails其實是Model 2,MVC就留給…MVC吧。這很困難,但至少能保持定義不變。
第三個是直接忽略這些混亂。管它那麼多?
我個人覺得MVC這個詞已經沒救了,不管怎麼解釋都會帶給別人混亂。
當對方同時學習client-side跟server-side時,混亂更強烈。
我選擇這樣回答:
「MVC有分很多種喔!網路上全部沒寫清楚,你一定看不懂。
沒關係,你只要知道View可以抽出來就好。
C跟M先別管,你先隨便瞎搞吧。」
確實有人腦袋清醒得很,它就是Python的Django。
Django的官方文件內根本沒有「Controller」這個名詞。
看看Django官網的常見問題:
Q: Django似乎是一個MVC框架,但你們把Controller命名為「View」,把View命名為「Template」。你們幹嘛不用標準命名啊?
A: (前略)…如果你真的很想要一個縮寫,你就說Django是一個MTV框架吧。Model、Template、View。這樣分比較有道理些。
Django不想變成搞亂MVC的幫凶,只好委屈地又發明了一個名詞「MTV」。
有。client-side框架也必須為MVC巨大誤會浪費一堆時間解釋。
看看Backbone.js官網的常見問答:
Backbone跟「傳統MVC」的關聯何在?
…我們來比較一下Backbone跟像是Rails這種server-side MVC框架的差別…
Backbone實作了「傳統MVC」,卻被迫用「傳統MVC」來描述server-side的Model 2,然後花一堆篇幅解釋。
沒錯,Model 2跟MVC都用到Model、Controller、View三個名詞,所以看起來類似。
但是,我們不應該再把時間花在思考「MVC怎麼如此難懂」。
我們討論的重點,應該是「如何分辨MVC與Model 2」、「在server-side如何實作Model 2才漂亮」、「在client-side實作MVC跟Model 2的優劣分別何在」。
OK,就讓我拋磚引玉一下。
分別談談Model、View、Controller吧:
兩種View有沒有很像?跟張飛、岳飛一樣像。
看看Backbone.js官網的View範例。你server-side的View哪是長這樣?
var DocumentRow = Backbone.View.extend({
tagName: "li",
className: "document-row",
events: {
"click .icon": "open",
"click .button.edit": "openEditDialog",
"click .button.delete": "destroy"
},
initialize: function() {
this.listenTo(this.model, "change", this.render);
},
render: function() {
...
}
});
兩種Controller有沒有很像?跟小狗、熱狗一樣像。
MVC的View跟Model 2的Controller可能還比較像一點。(隨便說說,千萬別這樣類比。)
Model倒是有些類似。
總之,Model 2跟MVC除了三個部份的名字一樣之外,沒什麼關聯了。
http://www.ithome.com.tw/node/77330
http://andrzejonsoftware.blogspot.tw/2011/09/rails-is-not-mvc.html
http://backbonejs.org/#FAQ-mvc
https://r.je/views-are-not-templates.html
附上幾個社群的連結,裡面有許多很棒的討論。
https://www.facebook.com/groups/javascript.tw/permalink/600136880087654/
https://www.facebook.com/groups/199493136812961/permalink/759391387489797/
https://www.facebook.com/groups/pythontw/permalink/10153760201638438/
這是我2015年寫的文章,當時(2013-2014)面試時,常常被問到 MVC,我覺得很困擾
因為我發現幾乎所有人都不知道自己在講什麼,所以寫了篇文章闡述我對 MVC 的看法
2023年不知道還有沒有公司面試會問這個。順手轉貼分享一下