前言
從ASP.NET MVC1.0發表至今,也已度過了近六個年頭,改版到最新的MVC 6,無論用的是Java、PHP、ASP.NET,各種開發工具在Web應用程式上,MVC是一個公認較好的設計方式,問題是很多公司過去的系統是利用ASP.NET 2.0以Web Form形式開發,開發人員也多半是以Web Form技術為主,轉變成為MVC方式,可能嗎?又或是有這個必要嗎?值得做這個投資嗎?以下這篇文章為各位介紹為什麼微軟會推這個ASP.NET MVC,以及和過去相比,這個開發技術究竟有什麼優點和缺點,至於是否該將系統開發方式改成ASP.NET MVC,就留給讀者去做判斷了!
MVC是一種設計模式(Design Pattern),不是一種語言工具
MVC一詞可以追朔到1970年代,使用Smalltalk開發的GUI應用程式系統,系統在架構時將和使用者互動的部份切割成為View,企業資料放在模組Model,透過Controller控制器,讓使用者在畫面上做資料的修正時,和後端系統中要使用的資料完全分開,在View上面不做狀態的紀錄(Stateless)。這樣的設計非常適合以HTTP的請求(Request)及回應(Response)為基礎的Web應用程式的架構。這裡先對MVC(Model, View, Control)做進一步的解釋。
Models(模組): 使用者需要使用到的資料,在系統中會用的到資料,像是在一個庫存系統中,訂購單,產品資料(產品編號、名稱、單價),客戶資料(客戶編號、客戶名稱、地址、電話)這些都歸類在模組中。
Views(檢視): 使用者和系統互動的介面,像是使用者在畫面上要看到的客戶列表、產品列表、訂單資訊、新增畫面、修改畫面等。
Controllers(控制器): 接收使用者的訊息,傳遞資訊到個模組檢視,連結這些檢視和模組之間的操作。
如果我們以一場音樂會來做比擬,使用者(Users)就是要入場的觀眾,主辦單位就是這個控制器(Controllers),必須準備好所有的事項,安排整個從售票到舞台佈置、燈光、音響、找到演出者、安排所有曲目的演奏順序,而檢視(Views)就是直接和這些要入場觀眾接觸的介面,像是售票窗口、舞台的場景,模組(Models)則是負責各項工作的燈光、舞台佈置、演出人員、售票人員。MVC的設計模式,是將這些角色們做適當分工,各司其職,而由控制器整合所有的工作,在使用者面前讓演出圓滿成功。
在ASP.NET MVC的程式架構中 控制器是繼承自System.Web.Mvc.Controller的類別,控制器中的方法(Method),會關聯到一個URL,在系統透過HTTP方式接收到一個來自URL的請求(Request), (例如在網址列上鍵入某個URL,這個控制器中某個方法對應到這個URL),這個方法會去整合後端的模組,將資料呈現在檢視上面,如下圖
當然,並非每一種軟體架構都適合以MVC的設計模式開發,在此就將幾種常見到的設計模式做個說明比較。
Smart UI
大多數的程式設計師都用過Smart UI的設計模式寫程式,只要寫過視窗應用程式或ASP.NET Web Form程式,多半都使用過這種設計模式。 這類的設計模式,通常是將使用者會用到的元件拖拉到畫面上,在元件的事件中撰寫程式,大部分使用者和程式的互動可以歸類為滑鼠的事件以及鍵盤事件,在觸發的事件中完成程式的撰寫。這樣的設計模式,因為沒有將商業邏輯、資料存取元件做適當的抽離,程式設計師最常做的事就是複製與貼上(Copy Paste)。面對類似的功能,將程式碼整塊複製,貼在要做的新功能,再逐行修改,Smart UI的開發模式,最大的問題就是維護與擴充功能。當系統必須做修改時,不能避免的就是進到程式碼裡,一行一行的看,當程式擴大到一個程度時,上萬行程式碼,已經是超過一般人所能改得動的。
這類的程式碼往往是MVC設計模式的負面教材,MVC的設計模式用盡一切方法,就是要避免Smart UI這種的寫法,但是Smart UI也不是全然都不好,小型的系統可以快速完成,如果需求不是那麼龐大,維護工作也可以順利進行。另外Smart UI模式建構雛形是最快的方法,可以在短時間讓使用者看到系統呈現的概念,這點是MVC設計模型不容易做到的。
Model View
Smart UI的設計模式,最大的問題在於一些商業邏輯以及資料存取的部分不能抽離出來而造成再維護上的困難,Model View將這些抽離放在模組中,這是很大的改進,讓原來的設計方式較容易維護,但是也產生了兩個問題,首先是檢視和模組的關係太過於緊密,要分開測試不大容易,另外是操作上,模組會有太多的程式,商業邏輯、操作方式、企業規則、資料存取全部都集中在模組裡。
傳統的3層式架構
三層式架構又將原有的Model View設計模式向前進了一大步,因為將資料存取層抽離出來,讓單元測試比較容易達成,但是因為三層式架構是以檢視直接和使用者做互動關係,利用事件驅動方式驅動程式,要寫出自動測試程式,變得相對複雜。另外在實務上常看到一些大型系統,以ASP.NET Web Form使用三層式架構,在一些設計規範沒有嚴格遵守下,在前端介面直接對資料庫做存取,或將商業邏輯寫在展現層-檢視(View)中,程式設計師就只能和這數千隻程式搏鬥。當使用者提出新需求要求修改原有功能時,只能直接下去看程式,一支一支的修正需求,系統的測試往往是模擬使用者輸入資料,測試資料是否正確顯示,測試介面操作是否人性化。而這些所有的測試, 都只能做整合測試(Integrated Test),各功能沒有適當的抽離下,單元測試(Unit Test)的是不可能做到的。另外原本該寫在商業邏輯層的程式或是資料存取層的程式,在各地方都出現,也造成系統難以維護。
ASP.NET Web Form vs ASP.NET MVC
再來討論ASP.NET Web Form和ASP.NET MVC的轉變。究竟以ASP.NET Web Form開發出了什麼問題, 讓Visual Studio團隊想導入這個MVC架構, 成為新的規格?
1.ViewState的包袱:
在ASP.NE Web Form中,為了維護狀態(State),像是「使用者送出資料後,畫面上的文字方塊,還能夠保持原本的資料」這在熟悉操作ASP.NET的程式設計師耳裡聽起來是件理所當然的事情,但是隨著對ASP.NET了解愈深入, 就愈清楚。事實上,ASP.NET透過PostBack機制,及一個名為_ViewState的Hidden標籤,將資料記錄起來,這個機制好處是使用者不用再費很多心力去處理這些資料問題。缺點是,無論您願意或不願意,這個機制永遠存在,當畫面上資料愈來愈多,或是更複雜時,這個ViewState反而是造成系統效能低落的最大兇手。
2.頁面的生命週期複雜化:
ASP.NET Web Form創造了各種的控制項,利用控制項的事件處理(Event Handle)方式,將程式碼放在事件處理程序中,而成功的模擬出了Windows應用程式的事件處理方式。實際上這些在ASP.NET中的事件,卻又混雜了許多頁面上的事件。例如:當在ASP.NET中
控制項上的Click事件處理程序上寫了一段程式碼,當使用者按下這個按鈕,整個頁面先做了Submit,畫面重新產生時,會發生Page.Load、Button.Click、Page.PreRender 以及其他的Page相關事件。但是如果有加上了主版頁面(Master Page),或是將按鈕放在使用者自定控制項中,頁面的生命週期將變得複雜到難以控制。寫過一陣子ASP.NET的程式設計師應該都面臨過類似的問題,到底Master的Load先執行,還是Content中的Load先執行?畢竟在真實世界中的Web應用程式,不會在畫面上只放一顆按鈕。 3.介面和程式邏輯的混用
在ASP.NET Web Form中設計了Code Behind機制,讓使用者可以將HTML語法和程式邏輯分開,這個設計獲得很多的掌聲,問題是,ASP.NET在很多控制項的設計,卻又鼓勵使用者在HTML頁面中編寫程式碼,像是一些資料庫相關的控制項,系統交錯著介面和程式邏輯,不僅在美工人員與程式撰寫人員的工作重複,很多美工做出來的html到了程式人員手上,要重新以ASP.NET的控制項再做一次,程式夾雜著HTML語法,在維護上也變得較為複雜。
4.HTML控制的薄弱
ASP.NET是一個在Web應用程式開發工具,所有的機制都是靠著HTML、CSS、JavaScript做前端介面的控制。為了讓使用者可以很快的利用工具完成系統,ASP.NET創造了很多伺服器端控制項,讓使用者得以像在Windows開發系統,拖拉這些控制項設計程式畫面。這些控制項將程式設計師的程式碼轉換成為HTML語言、CSS、JavaScript。但是,這個轉換過程,使用者可以修改的空間相當有限,常常要施展一些「怪招」(非正式的方法)才能得到預期的HTML語法,這樣也限制住在ASP.NET使用HTML、CSS、JavaScript的功能。
5.不容易以物件思考開發系統
ASP.NET Web Form是以事件驅動為出發,HTTP和HTML都被隱藏在Web Form中,開發者看到的一開始就是Web Form的Page.Load,在開發系統時,要陳述真實的Web行為時,卻又要被迫以PostBack機制來完成。在分析系統時無法以物件的方式抽離出這些使用者行為,必須綁定在這些事件上,讓分析的工作陷入兩難,是要模擬Web上面的真實事件(使用者送出登入資訊,點選購買,選擇商品)?還是ASP.NET Web Form上面所發生的事件?(Page的Load事件,Button的Click事件,Page的PreRender事件)
6.不容易測試
應該沒有任何一個程式設計師會將一個完全沒有測試過的程式交出去,最起碼都會把每個按鈕按一按,看東西會不會跑出來再說(雖然東西有跑出來不代表程式就是正確的)。而這些程式碼要怎麼測?在ASP.NET Web Form經常是只有一個選擇,整合測試(Integrated Test)。系統所有功能無法很清楚的分隔,功能必須執行出結果,才能得到正確與否,也因此單元測試(Unit Test)難以實現,也就無法成功建立出程式品質的控制。
可能面臨的問題
將ASP.NET Web Form改以ASP.NET MVC開發就能夠解決以上的問題? 是的,但是相同的轉換過程中也會有幾個問題必須去解決:
1.人員能力的提升
ASP.NET MVC程式的寫法會從URL Routing開始,這對習慣ASP.NET Web Form的使用者是陌生的,但是這是Web HTTP的原始模式,過去習慣在ASP.NET Web Form產生的程式碼下寫程式的程式設計師,必須對Web的行為再進一步的認識,雖說學習是程式設計師的宿命,在長久以來習慣於Web Form的操作模式,新的開發模式會是一種新的挑戰。
2.系統分析的方式轉變
ASP.NET Web Form上開發系統,很常常會出現一種以結構化程式設計的思維在撰寫程式,將功能切割,細分每一個功能,個別去設計。在ASP.NET MVC的開發介面中,Model已經被抽離出來,但是物件思考還是要靠物件系統分析的方式達成,否則系統很容易流於,以ASP.NET MVC設計模式寫出很像Web Form的系統。
3.圖形化的控制項不見了
在ASP.NET Web Form有許多相當好用的控制項,是利用ViewState,以及PostBack機制模擬Windows應用程式設計出來的,這類的控制項將HTML、 CSS、JavaScript的語法包裝在控制項的設計中,程式設計師只要從工具箱拖拉到畫面,修改屬性,事件中再寫上幾行程式碼,就可以做出一些很困難的工作(像是月曆控制項),但是這些控制項,包裝了太多東西,在不了解內容的狀況下,很容易寫出實際上效能極差的系統,例如在一個表格中放了數十個AJAX的Update Panel,用來做排班的功能,系統重新產生資料,很可能在PostBack要花非常久的時間,而幾乎完全無法改善這段程式的效能,原因是這些內容都已經包裝在控制項中,完全沒有調整的空間,只有讓這些功能都回到最基本的HTML、CSS、JavaScript才能真正把不必要的動作去掉、讓程式回到最精簡的狀況。
4.沒有GridView、SQL DataSource這類的資料庫感知元件
過去仰賴GrieView、FormView、Repeater、SQLDataSource這類控制項可以快速開發出具有相當實用功能的應用程式。在ASP.NET MVC的開發中,程式設計師必須利用HTML基本的設計來實現,一開始會有種「打掉重練」的感覺,甚至會有種挫折感,過去只要一個拖拉完成的事情,要重新熟悉這個工具,自己建構出新的開發模式。
5.必須更清楚知道HTML、CSS、JavaScript
在去除這些既有Web Form提供的元件之後,瀏覽器上前端的操作,靠的就只有最基本的HTML、CSS、JavaScript,以往將JavaScript當成用Google查詢可以下載放到自己的程式的方法,必須修正一些觀念,對JavaScript的撰寫必須下功夫去理解。同時對CSS的認識就必須更清楚,這對長時間以Web Form上面控制項屬性做設定來寫程式的程式設計師,無疑是相當大的挑戰。
結論
任何一種設計模式沒有絕對好或絕對不好的,系統開發適合用的設計模式,會因系統的特性而異,縱使系統較適合某種設計模式,開發團隊的人員技術、成本以及時間都是必須考量的因素,也因此考量系統開發更換一種新技術,肯定是一件艱難的決策。但是只要是在開發系統的領域中,無論是專案經理、系統架構師、系統分析師、程式設計師(或是集這些工作於一身的人),了解ASP.NET MVC,是您今天必修的一門技術。 |