一、學習背景
由于公司業務日益龐大,很多老項目需要維護,由于這些項目的前端基本都是jQuery+jQuery plugins搞定的,編寫的代碼可謂是:無組織、無紀律,導致前端維護成本越來越高,為了解決這一難題,決定引入前端MV*框架。從瀏覽器兼容性、與其他組件方便集成的角度考慮,最終選擇了backbone.js。因為之前接觸過AngularJS,backbone.js我只看了一天文檔,就能開發實際項目了;但是有個問題一直耿耿于懷,由于backbone.js沒有明確指出自己的架構模式,所以它不屬于MVC、MVP、MVVM中的任何一種,而是介于它們之間的某個變種,這一點讓我極度郁悶,因為這導致我無法精確的組織JavaScript代碼。而這一問題的根本原因是我對MV*架構模式的理解不夠深刻,所以我決定:先將MVC、MVP、MVVM的定義與區別理解透徹,再回過頭來審視backbone.js。
MVC是一種架構模式,說白了就是一種組織代碼的方式,將代碼根據職責劃分成三塊區域,這樣的好處很明顯:易于閱讀、便于維護。回想一下沒有引入MV*框架前的那一坨JavaScript代碼,我相信大部分人都會表示:我碰都不想碰了。就算你引入了模塊加載框架(requirejs、seajs等),你的代碼仍然是“凌亂”的,只不過范圍縮小到模塊內部而已,前端MV*框架就是為了解決這個問題出現的。
二、經典MVC
2.1 MVC誕生
20世紀80年代,mvc作為smalltalk-80(傳說中的“面向對象編程之母”)的一個類庫走進人們的視野。那個年代瀏覽器還沒出現,計算機的圖形用戶界面(GUI)還相當的簡陋。為了將UI組件代碼從業務邏輯代碼中剝離出來,人們嘗試對應用程序進行分層,產生了最初的MVC模式。當今的MVC(本文稱為MVC的變種)已經與經典MVC大相徑庭,由于經典MVC的某些特征并不適合如今的富客戶端應用(后面會有解釋),所以從某種意義上來說,經典MVC已經消失了,本文的描述針對的是經典MVC。
2.2 經典MVC的工作流程
經典MVC根據職責將代碼劃分為三個區域:Model(模型)、View(視圖)、Controller(控制器)。不考慮特殊場景,大部分的工作流程是這樣的:

首先從M、V、C各自的職責說起:
- Model:代表業務邏輯層,它無視表現層的存在,只專注處理業務。
- Controller:接受用戶的輸入,將輸入轉為相應的命令,執行進一步的操作。
- View:向用戶呈現展示的信息,與M建立觀察者模式,根據M的改變自動重新渲染。
首先需要說的是,不要以瀏覽器的角度理解這個流程,因為那個時代瀏覽器還未出現。一個完整的MVC的工作流程是這樣的:
- 首先C接受用戶的刺激。
- (流程①)C將這種刺激轉化為某種命令去調用M的接口,對M執行更新操作。
- (流程②)M發送狀態改變的通知給V(由觀察者模式完成)。
- (流程③)V調用M的接口獲取最新數據,重新渲染V(由觀察者模式完成)。
從調用流程我們發現經典MVC有以下幾個特征:
- C與V共同組成一個表現層,即一個UI組件,兩者是無法獨立存在的,所以沒有實質上的分離,這點與如今的MVC變種有很大區別。
- C與V沒有直接的調用關系,各自處理自己的事務。
- 引入觀察者模式實現數據綁定,C沒有直接更新V,而是去更新M,然后通過觀察者模式對V進行更新。由于一個M可以對應多個UI組件,當某個特定的C更新M時,會引起相關的多個V同時更新,這對于開發復雜的用戶界面非常便利。
- 成功將“表現層(C+V)”從“業務邏輯層(M)”剝離出來。
2.2 經典MVC的缺陷
2.2.1 觀察者模式的缺陷
觀察者模式在給開發者帶來便利的同時,也帶來了一個問題,那就是:很難通過跟蹤代碼來獲悉程序的流程走向,這直接導致了程序復雜度的提高,所以過多的使用觀察者模式會使程序變的不易理解。
2.2.2 特殊表現層邏輯的尷尬位置
隨時用戶對圖形界面的要求越來越高,GUI變得越來越復雜,表現層的邏輯已經不僅僅是將M的數據直接顯示到屏幕上那么簡單。我們需要對M的數據進行進一步的加工處理后才能呈現給用戶。經典MVC的時代,圖形用戶界面是非常簡單的,所以MVC能滿足大部分場景的需求,就算有那么一小部分特殊的表現層邏輯(M數據的加工處理),也被放到M里進行處理了,雖然污染了M的純度,但是影響并不大。但是對于當代的富客戶端應用來說,這種“特殊表現層邏輯”是非常龐大的,如果都塞進M里,這顯然是不能接受的。
2.2.3 smalltalk的對策
基于smalltalk-80 MVC的開發者也意識到了MVC的短板,他們采用的策略是對V進行拓展,將V拓展為一個全新的對象,它既包含V的全部內容(包括取代V,與M建立觀察者模式),又含有對M數據進行加工處理的邏輯代碼,他們把這種全新的對象叫作:Presentation Model。而這一切的改變都是為了更徹底的將“表現層”與“業務邏輯層”分離。
三、總結
經典MVC總起來說有兩個關鍵點:分離表現層、通過觀察者模式進行數據同步。雖然MVC已經不能滿足當代富客戶端應用的需求,但是它的兩個關鍵點卻被傳承了下來,影響了一系列的MVC變種,比如MVP、MVVM等,而這些MVC變種也正是為了滿足富客戶端的需求進化而來,下篇文章介紹MVP與MVVM。
參考文獻
<a >wikipedia Model-view-controller</a>
<a >Martin Fowler GUI Architectures</a>
<a >Model View Controller History</a>