從三層架構(gòu)到MVC-MVP
當(dāng)然這種架構(gòu)模式本身的一些問題也會在接下來的內(nèi)容就加以介紹,另外就是如果大家有什么不同觀點(diǎn)的話,歡迎拍磚(只要不打臉就行,呵呵)。
一. MVC是誰提出的
模型-視圖-控制器(MVC)是Xerox PARC在八十年代為編程語言Smalltalk-80發(fā)明的一種軟件設(shè)計模式,至今已被廣泛使用。最近幾年被推薦為Sun公司J2EE平臺的設(shè)計模式,并且受到越來越多的使用 ColdFusion 和 PHP 的開發(fā)者的歡迎。模型-視圖-控制器模式是一個有用的工具箱,它有很多好處,但也有一些缺點(diǎn)。
二. MVC是否適合進(jìn)行大項目的開發(fā)
MVC框架肯定是適合于做大項目開發(fā)的,但并不是說有了MVC框架我們就可以開發(fā)大項目,聽起來有些繞,其實(shí)道理很簡單,原因就是人(開發(fā)者)。如果你是一個對MVC框架的設(shè)計理念有深入研究的人,那么你在使用MVC框架進(jìn)行產(chǎn)品和項目開發(fā)的時候就會隨時隨地都要考慮一些問題:
1.低耦合性(強(qiáng)調(diào)視圖層和業(yè)務(wù)層分離)
2.可測試性(這個非常重要)
3.高重用性和可適用性
4.有利于軟件工程化管理等等。
這里我很欣賞老趙的治學(xué)態(tài)度,因為在他的文章和代碼中隨時隨地都在進(jìn)行著思考,特別是其對可測試性,單元測試(這里不是什么TDD)的思考,讓我看起來有心靈相通的感覺。因為這些問題都是在做中型甚至大型項目中要認(rèn)真思考的,決不是說微軟給的例子就是我們的唯一準(zhǔn)則,必定里面有對也有錯,我相信在MVC面前,國內(nèi)甚至微軟內(nèi)部的牛人都不是很多。
說了這些,大家可以意識到了,如果在沒有理解下面這張圖以及對MVC的“所謂優(yōu)點(diǎn)是從何處得到的”有認(rèn)識,而一上來就去拿MVC去開發(fā)大型項目的話,我想不僅不能發(fā)揮asp.net MVC框架的估勢,相反會時時受制于里面的約束,配置和功能特性,最后感覺還不如直接用asp.net webform開發(fā)來的直接,不是嗎?真要是到了這一境地,我想不僅無法使用MVC進(jìn)行大型目開發(fā),就連中小企業(yè)應(yīng)用都應(yīng)付不來。
三. 能不能使用MVC架構(gòu)進(jìn)行Webform的開發(fā)
有人嘗試使用ASP.NET MVC 框架來進(jìn)行webform方式的開發(fā),我個人是不欣賞這種做法的,這就好比在使用LINQ的項目中又同時使用SQL語句一樣“怪異”,這在代碼的整體風(fēng)格上會讓人產(chǎn)生迷惑,不是嗎?當(dāng)然老趙也在他的視頻課程中提到在webform頁面中使用一些MVC功能(比如:ModelBinder等),但我想老趙的本意決不是讓這種混合方式的開發(fā)大行其道,必定這是“非主流”,所以孰輕孰重還是要大家自己把握的。
四. 傳統(tǒng)的三(N)層架構(gòu)與MVC,以及MVC與MVP關(guān)系
本文所說的三層架構(gòu)指:表現(xiàn)層(顯示層), 業(yè)務(wù)邏輯層, 數(shù)據(jù)訪問層(持久化)。如果大家非要“生搬硬套”的把它與MVC扯上關(guān)系的話,那我就只能在這里"強(qiáng)扭這個瓜"了,即:
三層架構(gòu)中"表現(xiàn)層"的aspx頁面對應(yīng)MVC中的View(繼承的類不一樣)
三層架構(gòu)中"表現(xiàn)層"的aspx.cs頁面(類)對應(yīng)MVC中的Controller,理解這一點(diǎn)并不難,大家想一想我們以前寫過的Redirect,當(dāng)然它本身就是跳轉(zhuǎn)了一些鏈接頁面,而MVC中的Controller要做的更爽,它控制并顯示輸出了一個視圖。即然所起到的作用都是對業(yè)務(wù)流程和顯示信息的控制,只不過是實(shí)現(xiàn)手段不同而已。
三層架構(gòu)中業(yè)務(wù)邏輯層和數(shù)據(jù)訪問層對應(yīng)MVC中的Model(必定View和Controller已找到“婆家”,剩下的Model只能是業(yè)務(wù)業(yè)務(wù)層和數(shù)據(jù)訪問層的了,呵呵)。但其實(shí)微軟的一些MVC示例項目中對這個問題理解的并不是這樣簡單,這一點(diǎn)在我之前的關(guān)于兩個MVC示例的思考(MVCStore和Oxite) 已闡述過,就不多說了。
其實(shí)明白了這個關(guān)系,就可以嘗試把以前的三層結(jié)構(gòu)遷移到MVC框架下,當(dāng)然在這個過程中肯定會遇到這樣或那樣的問題,但原則就是把將MVC的優(yōu)勢發(fā)揮到極致,要不然還不如不做。說到這里,其實(shí)早在N年前就有人提出使用FrontController(前端控制器)來實(shí)現(xiàn)對HTTP頁面請求的路由跳轉(zhuǎn)(包括數(shù)據(jù)的展現(xiàn)),說白了就是使用HttpHandler來進(jìn)行頁面請求的處理和數(shù)據(jù)綁定,而不是完全“指望”普通的頁面訪問重定向等。這樣做的目的,就我而言與Routing中的Controller和Action的出發(fā)點(diǎn)標(biāo)是一致的,只不過Routing實(shí)現(xiàn)的更優(yōu)雅同時也更底層一些。
說完了三層架構(gòu),再看看MVC與MVP,其實(shí)在這之前我們有必要看一下這張圖:
看完了上面的圖,大家就會發(fā)現(xiàn)MVP與MVC最大的一個區(qū)別就是“Model與View層之間倒底該不該通信(甚至雙向通信,如圖)。我想這也是目前做這兩方面研究的專家所互相爭論的戰(zhàn)場。必定各有各的好處和因好處要付出的代價。起碼在MVP模式下的Presenter要擁有“絕對權(quán)力”。如果沒有它,MODEL與View就是兩個孤島,盡管各有各的地盤(完全解耦),但不會給企業(yè)帶來什么有用的價值。所以我這里有一個比喻來形容MVP中的:
Presenter ----就是一個控制欲極強(qiáng)的女人,甚至就連“用什么姿勢”,它都要管一管。
當(dāng)然日里萬機(jī)操心多了就會讓自己要做的事越來越多,最終它面臨的就是該層代碼日益龐雜,且書寫起來不太方便,必定就連事件綁定這類雞毛算皮的事都要?dú)w它管,累不累呀。最終我們看到MVP中的View就真的代碼輕閑了不少(國企職工嘛),難怪說View只要從相應(yīng)的IVIEW接口下實(shí)現(xiàn)相應(yīng)的屬性和一些簡單方法就完事了,而最終調(diào)用IVIEW接口下的那個視圖實(shí)例則完全交給了Presenter,這讓我想到了MVC中可以支持“自定義模版引擎(最終由MVC框架來控制使用系統(tǒng)還是自定義的模版引擎)”以及平時大家常掛在嘴邊的換膚功能,想到這里多少還真有那么點(diǎn)意思了(精神層面上)。
當(dāng)然在微軟內(nèi)部對MVP的理解也有所不同,如下圖中所說的Supervising Controller模式和上面大家看到的PassiveView.
Supervising Controller模式其實(shí)很接近于MVC的那張圖了,只是又提供了Presenter與View之間的“雙向通信”。這種做法也是有很多不同意見的,起碼對那些支持“單向依賴”的開發(fā)者而言是“嗤之以鼻”的。
說到這里,表達(dá)一下我的觀點(diǎn),我是偏向于PassiveView的,雖然這種模式有些霸道,但必定是讓Model和View之間真正解耦,為開發(fā)者提供了最大的“控制成就感”,可以說想怎么控制視圖就怎么控制,但因此所造成的問題就是代碼書寫量和實(shí)現(xiàn)復(fù)雜性等問題了。
五. Controller和Model中該有哪些東東
因為VIEW中的邏輯比較簡單,所以對系統(tǒng)復(fù)雜性的考慮基本上要重點(diǎn)放在Model中,而Controller是對業(yè)務(wù)流程的控制,其應(yīng)該保持“代碼清爽”。說是這么說,但實(shí)際進(jìn)行項目開發(fā)時這兩者之間的界線能這么清楚嗎,答案是“盡量保(堅)持”。必定這是MVC的“特色”嘛。
另外這里向大家推薦一個不錯的方法"Robustness",有了它您就可以很容易的找出那些系統(tǒng)方法要放在MODEL中,哪些該歸入控制邏輯中了,該方法我在兩年前的一篇文章中提到過,大家感興趣的話可以看看這個鏈接, 采用[ICONIX] 方法實(shí)踐BLOG設(shè)計之四 [健壯性分析] .其核心內(nèi)容如下:
實(shí)體對象(entity object):
通常是來自域模型中的對象(也就是現(xiàn)實(shí)世界),它常對應(yīng)于數(shù)據(jù)庫表和文件,這些數(shù)據(jù)表和文件中存儲了執(zhí)行用例所需的數(shù)據(jù)。有些實(shí)體對象是“臨時”對象(如搜索結(jié)果),當(dāng)用例結(jié)束后將消失。
邊界對象(boundary object):
參與者使用它來同系統(tǒng)交互,這通常包含窗口,屏幕,對話框和菜單。如果有GUI原型,將會知道許多主要的邊界對象是什么。
控制對象(control object):
將邊界對象和實(shí)體對象關(guān)聯(lián)起來(通常被稱為控制器,因為它們通常不是真正的對象),它包含了大部分應(yīng)用邏輯,它們在用戶和存儲的數(shù)據(jù)之間架起一座橋梁??刂茖ο笾邪?jīng)常修改的業(yè)務(wù)規(guī)則和策略。這樣修改只需要在這些對象中進(jìn)行,而不會涉及到用戶界面和數(shù)據(jù)庫模式??刂破髋紶?(20%的時間內(nèi))也會是設(shè)計中的“真正對象”,但大部分時間內(nèi),控制器只是一個占位符,用于避免您遺漏用例要求的任何功能和系統(tǒng)行為。
上面的三個對象分別對應(yīng)Model, View, Controller.
正如文中所說,該方法還提供了如下好處:
1.它幫助您確保用例文本的正確性,且沒有指定不合理或不可能的行為 (基于要使用的一組對象),從而提供了健康性檢查。
2.幫助確保用例考慮了所有必需的分支流程,從而提供了完整性和正確性檢查。
3.讓您能夠(持續(xù))發(fā)現(xiàn)對象,因為在域建模期間可能會遺漏一些對象, 而這些對象在繪制時序圖時不易被發(fā)現(xiàn),并且很可能正是它導(dǎo)致無法繪制時序圖。
4.縮小分析和設(shè)計的鴻溝,從而最終完成初步設(shè)計(關(guān)于初步設(shè)計復(fù)核會在下一篇中介紹)。
六.MVC與MVP是否可以同時出現(xiàn)在一個SLN甚至一個項目中
這一點(diǎn)我想誰說了都不算數(shù),只有用戶需求才是王道,用戶使用在當(dāng)前項目中實(shí)現(xiàn)某些特定功能,而該功能恰恰是MVC或MVP的用武之地,那就一個字:“用”。
最后還要再說明一點(diǎn):
業(yè)務(wù)邏輯是系統(tǒng)架構(gòu)中體現(xiàn)核心價值的部分。它的關(guān)注點(diǎn)主要集中在業(yè)務(wù)規(guī)則的制定、業(yè)務(wù)流程的實(shí)現(xiàn)等與業(yè)務(wù)需求有關(guān)的系統(tǒng)設(shè)計,所以說一個系統(tǒng)來說,業(yè)務(wù)邏輯是無處不在的。View上的是顯示邏輯,Controller上是流程控制邏輯),Model上簡直就是“邏輯大本營”了。
使用 MVC 框架時我們要將“經(jīng)常變化”的業(yè)務(wù)規(guī)則(位于Controller)和相對穩(wěn)定的業(yè)務(wù)邏輯(位于Model)分離開,同時在Model層采用接口方式實(shí)現(xiàn),以此來應(yīng)對將來不斷變化的業(yè)務(wù)需求。
【編輯推薦】