1 B/S為何難於提供好的使用者互動體驗?
這裡頭的最大問題有幾個:
(1)無狀態的HTTP協定
Windows窗體間可以透過記憶體直接交換訊息,但作為B/S架構通訊基礎協定的HTTP是無狀態的。
如果將瀏覽器看成是客人,Web Server看成是旅館,在HTTP協定的管理之下,會出現這種情況:不管某客人來訪多少次,Web Server都將其視為第一次的訪客。這樣一來,客人每次都得帶齊身分證件供旅館工作人員「驗明正身」。
HTTP協定的無狀態,導致Web Server的“六親不認”,這固然能增加Web Server的吞吐量,卻給應用系統的開發帶來了麻煩。因為應用系統中往往有許多業務處理流程,天生就是資訊流轉的,即原始資料從一端進去,從另一端出來時應該已經過某些處理,怎可想像整個業務流程中的資訊會流失?於是,在HTTP各請求間共享資訊就成了件麻煩事,這就是HTTP請求的「狀態保持」問題。每個B/S系統都必須解決這個問題。微軟想了一些“歪招”,例如充分利用HTML網頁的中隱藏域,再在Web Server上做些手腳,於是ASP.NET擁有了一套在各個HTTP請求之間維持狀態的技術:Session,Cookie ,ViewState,Profile,Application。
然而問題並沒有完全解決。例如,C/S系統中常見的收集使用者輸入資訊的對話框,主窗體與對話框之間有著資訊的交換(又分為兩種:模式的和非模式的,前者對話框不關掉,主窗體不能被啟動),在B/S架構之下,由於瀏覽器的每個請求是獨立的,要在兩個獨立的瀏覽器視窗間實現類似於模式對話框這種直接的信息交換,我還真不知道該怎麼幹。
AJAX使用以下這種的方法來“摸擬”出模式窗體:將主窗體與對話框“合二為一”,對話框在HTML中就是一個div元素,平時是隱藏的,需要時再顯示它。微軟的AJAX Control Toolkit中甚至為此功能設計了一個控制項。諸如此類的小伎倆,在B/S開發中不勝枚舉。
可以看到,許多在C/S輕而易舉就可實現的功能,在B/S中要實現則大費周章。
(2) 特殊的運作環境-瀏覽器
B/S系統的前端運作環境是瀏覽器,這就帶來了諸多的限制,不能做許多事,例如直接存取硬體(例如印表機),也無法充分利用硬體的資源。例如,現在的新電腦都是雙核心的,你能直接用JavaScript加HTML寫出一個多執行緒程式來充分利用這兩顆「奔騰的芯」?
而C/S系統則直接運行在OS(作業系統)之上,可以呼叫OS提供的所有功能,這種限制就不存在了。
(3)尷尬的Web客戶端程式語言-JavaScript
傳統的C/S程序,可以使用為數眾多的各種開發語言,尤其是像C++,Java,C#之類主流物件導向語言,功能強大,使用方便,各種開發工具齊備,已非常成熟。
與此相反,B/S前端所使用最多的程式語言JavaScript,不僅不讓人喜歡,甚至讓許多程式設計師“恨之入骨”,將“用JavaScript程式設計”看成是件苦差事。
讓我們來看看JavaScript的兩大硬傷。
首先,缺乏清晰而統一的程式設計模型。
JavaScript雖然名字中有一個Java,並採用了類似的語法,但與真正的Java並無關。唉,她本身是一隻醜小鴨,總想著攀上天鵝這門親,卻沒想到別人不買單。
JavaScript用到了許多對象,但說它是物件導向的吧,又實在難以令人信服(物件導向程式設計的基本單元是類別),例如它沒有類似C#等主流物件導向語言的關鍵字class,到處是一個個的函數,這使得所有的程式碼難於以類別的方式清晰界定;同時,它又不是結構化的(結構化程式設計的基本單元是函數),因為瀏覽器在解析HTML文件時,是採用流式解讀方式,從而導致一些JavaScript程式碼被放在函數之外,在解析HTML文件時直接執行,而另一部分放到函數中的程式碼,則多採用事件驅動的方式運行,這就帶來了複雜的程式執行流程,遠不如純結構化程式設計中統一採用函數呼叫的程式設計方式簡潔。
這樣看來,JavaScript兼具面向對象,結構化,非結構化三種程式設計方式的特點,但卻弄得不倫不類,沒有一個清晰而統一的程式設計模型,難於寫出結構清晰易於維護的程式碼,反而帶來了許多混亂。
其次,JavaScript的另一個硬傷是它的瀏覽器運作環境。
由於歷史的原因,不同的瀏覽器,甚至同一瀏覽器的不同版本,其編程模型都有或多或少的差別,因而不得不寫代碼檢測瀏覽器類型,比如需要為IE寫一套代碼,又為FireFox寫另一套。這實在是一件麻煩事。
上述這些問題,幾乎是B/S架構系統「與生俱來」的「缺陷」。先天不足後天補,人們想出了許多招數來解決這些問題。 AJAX是眾人看好的希望之星。
2 希望之星-AJAX
這些天來,我有系統地了解了一下微軟的AJAX框架。發現這框架的複雜度遠遠超過我原先的估計,微軟設計AJAX框架的工程師們,將各項Web開發技術的潛力發掘得很深,在很大程度上彌補了前面提出的問題。
(1)對JavaScript語言的擴充:
微軟透過提供封裝好的AJAX Library,增強了JavaScript的物件導向特性,可以方便實現繼承,定義接口,序列化對象,引發事件,反射類型等功能,雖然比真正的物件導向語言(如Java/C#)還有差距,但能將「醜陋」的JavaScript打扮得可以見人,也算是功力不凡。
(2)大幅提升瀏覽器端程式碼的功能
在AJAX Library支援之下,配合增強功能的JavaScript,在瀏覽器本身的支援之下,可以在瀏覽器中寫JavaScript腳本,方便地向伺服器發出非同步請求,實作頁面局部刷新,並且可以直接呼叫Web Service。
(3)引入基於組件的開發(CBD)方式
基於組件的開發(CBD)早已是面向對象系統的主流開發方式,雖然現在SOA(基於服務的架構)炒作得熱鬧非凡,但要達到CBD那樣的成熟程度,還需要時間。
對JavaScript而言,別說SOA,能實現CBD都很困難。
為了實現CBD,微軟給JavaScript“大補特補”,增強了許多特性,基於Microsoft AJAX Library,程式設計師可以開發三種類型的可重複使用元件:None_Visual Component(不可視的元件,相當於物件導向系統中的一些提供公用功能的類別)、Behavior(行為,擴充現有Web控制項的功能)、Control(擁有視覺化介面元素的Web控制項)。
尤其是AJAX Control ToolKit中提供的數十個控件,基本上實現了B/S對C/S使用者介面大部分特性的摸擬,就是這個新程式設計模型應用的典範。
微軟對JavaScript程式設計模型的增強,讓軟體工程師終於可以用CBD的開發方式開發Web客戶端程式碼。我認為,這是一個進步。
(4)增強的伺服器端能力
為了增強瀏覽器端程式碼的能力,必須透過伺服器端予以配合。 AJAX本身就基於Browser與Web Server相互支援的程式設計模型(Web Server提供資料服務,Browser提供XMLHttpRequest物件可向Web Server發出非同步請求,當資料回來時,程式設計師可以用JavaScript編寫程式碼實現對網頁的動態局部更新)。
透過AJAX Extension,微軟增強了伺服器端ASP.NET框架的功能。並將常用的功能外化為簡單的Web控件,例如AJAX的核心控制項ScriptManager,用於定義頁面可更新區域的UpdatePanel,還有用於增強現有ASP.NET控制項的位於AJAX Control Toolkit中的數十個Extender控件(即附加到現有控制項上的控件,其目的是為現有控件擴充新的功能)。
擁有了這些控件,開發Web前端程式就類似在VB中設計窗體了。現在不只是可以繪出類似Windows窗體的介面,而且透過利用AJAX的非同步請求與頁面的局部刷新技術,在Web伺服器的配合之下,可以在使用者體驗上逼進Windows窗體。
不管多少人如何看不起VB,但VB所帶來的視覺化程式設計普及浪潮,的確影響深遠,微軟推動JavaScript程式設計走向這一步,也是大勢所趨。為了提高Web 開發的效率,必須走這一步。
然而,需要指出的是,不管後天如何“進補”,畢竟“先天不足”,B/S架構要在用戶體驗這一點上超過C/S,還是非常困難。
3 未來:B/S與C/S,誰主沉浮
由於管理與部署的簡便性,B/S架構成為當今許多資訊系統的首選,然而,用戶是追求好的使用體驗的,大體總結起來,有以下要求:
(1)漂亮的介面。這點B/S有優勢。
(2)方便的輸入。例如許多用戶都希望能不用滑鼠就可以錄入數據,或是透過簡單的點擊實現數據的自動填充,在B/S架構下實現起來比較麻煩,AJAX可以在一定程度上解決這個問題。
(3)閃電般的速度。對C/S而言,要實現反應速度快,有許多的法子可想,可B/S就不容易了。由於受到瀏覽器的限制,客戶端強大的硬體資源幾乎是閒置的。另外,網路速度是B/S架構的瓶頸,除非頻寬能有快速的成長,否則,WWW就是World Wide Wait。
C/S雖然擁有好的使用者體驗,但它的問題在於開發跨越整個互聯網的分散式系統困難,而且由於需要安裝客戶端,系統更新與組件版本管理就成了一個大問題,此外,不像B /S架構只需考慮伺服器端的問題,在C/S架構由於多用戶同時存取伺服器,各元件間的呼叫與依賴關係複雜,在處理多執行緒存取共用資源,事務處理等方面必須同時考慮客戶端與伺服器端,吞吐量受到大的限制。因此,C/S多建構於區域網路內,供企業內部使用。
目前基本上是B/S與C/S共存,隨著諸如AJAX之類B/S技術的廣泛應用,B/S不斷攻城掠地,佔有上風,但不可能將C/S徹底地「打垮」。
比較有趣的是:像微軟這樣的大公司,是如何看待B/S與C/S發展前途的?
我等一般開發者,沒有機會直接與微軟高層對話,但可以從其公司的產品發展路線看出一些端倪:
微軟似乎不認為B/S代表未來的技術發展方向,相反,它的許多行動,都朝著拋棄瀏覽器的方向在走。
首先,微軟簡化了C/S的開發與部署問題,推出了Smart Client技術,讓C/S客戶端程式的更新可以無需人工幹預,自動進行。
其次,微軟努力彌補B/S與C/S兩者間的鴻溝,在設計ASP.NET時,毅然拋棄已取得不錯業績的ASP,直接採用類似VB的「視覺化控制+事件驅動」 程式設計方式,甚至將Web 頁面也稱為「Form」——Web Form。
第三,微軟可能認為AJAX是一種過渡性質的技術。
微軟在AJAX上遲遲不見動作,直到看到由於Google等公司成功應用AJAX技術提升Web用戶體驗而導致AJAX的迅速竄紅時,才行動起來,給ASP.NET加上AJAX擴展,整個過程中顯然行動並不積極,投入的資源也不多,這與當年微軟與網景公司展開瀏覽器大戰時完全不一樣。但從其在VS2008中將AJAX Extension內建為標準配置,並直接整合JavaScript的調試功能到IDE中,說明微軟還是面對現實的,它承認AJAX擁有重要的地位與較大的發展潛力。
其實,我分析微軟的野心是“一統天下”,拋棄瀏覽器,徹底統一B/S與C/S。
這點在.NET 3.0/3.5看得很清楚。
首先,微軟用WCF統一了DCOM,.NET Remoting等主要用於C/S的技術,整合了原先位於COM+中的許多企業化開發特性,連同主要用於B/S架構的Web Service技術,統一地抽象並封裝為可重複使用的WCF Service。很明顯,微軟要將資訊系統開發模式由CBD轉為SOA(也就是未來的系統是組裝Service,而非組裝Component)。
其次,微軟拋棄了非常成熟的Window桌面程式設計模型(Win32 API+訊息/事件驅動)引進了一個全新的WPF程式框架,其中一個重大的革新是符合XML規範的XAML(應用程式標記語言)的出現。 XAML用XML格式純文字檔來描述應用程式介面。
我們可以輕鬆地將XAML與XHTML進行類比。瀏覽器解析XHTML程式碼,產生視覺化的網頁介面,而XAML則由.NET Framework 虛擬機負責解析,在Vista中,由於Vista直接整合.NET Framework 3.0,就可以將Vista看成是一個超級瀏覽器,由它負責讀入XAML生成用戶介面,並實現其所有應用程式功能。
如此一來,一種新的程式設計模型浮出水面,不管是B/S或C/S的系統,其方式都是統一的:讀入XAML程式碼à解析à呈現à接收用戶輸入à處理資料à顯示結果。
在這個程式設計模型中,瀏覽器成了旁觀者,不再是客戶端應用的核心。
新程式設計模型的運行平台是全功能的OS,而非功能受限的瀏覽器。這個差異是巨大的,一個運行於OS之上的瀏覽器,其功能怎麼能和OS自身相比!
現在可以透過以物件導向方式組織起來的作業系統API(應用程式介面)方便地呼叫作業系統的各種功能,充分利用客戶端的硬體資源(例如可以輕鬆地在.NET Framework之上開發多執行緒程序,「壓榨」雙核心CPU的工作能力)。使用者介面都用XAML來描述,這就統一了B/S與C/S的介面層技術。
WPF最適合的運作環境是Vista作業系統,它的一個功能子集,現在稱為Silverlight,被實作為一個瀏覽器插件,從而讓WPF程式也能跑在傳統的瀏覽器中。由於Silverlight和Vista本身都可以解析XAML,所以,現在可以用XAML只寫一套介面程式碼,就同時適用於B/S與C/S,並獲得相同的使用者體驗。
由於B/S和AJAX存在著一些先天不足,如果將經過AJAX增強功能的B/S系統比喻為一個舞者,那麼,這其實是一位帶著鐐銬跳舞的舞者,而微軟公司的想法是,與其不斷想法減輕這一鐐銬的重量,為何不乾脆直接拋棄這一鐐銬呢?
微軟推出WPF與WCF,就是這樣的一個嘗試。
應該來說,微軟公司的這套發展策略是建立在對現有B/S與C/S各自的優缺點分析的基礎之上而製訂的,有它的科學性,也考慮到了自身的商業利益。但這項策略最終實現還有許多困難,因為即使強大如微軟,也無法一統江湖。微軟的對手與微軟一樣聰明,技術進步也同樣迅速。
可以斷言,由於資訊系統應用的延續性,在相當長的一段時間內(也許有三五年,也可能有五到十年),B/S與C/S將同時並存,由於B/S許多突出的優良特性,在與C/S的競爭中將佔上風,這個局面不會有太大的改變。對於AJAX,作為B/S系統的一個重量級武器,雖然很有效,但存在不少缺陷,我對於它的未來發展,抱有謹慎的樂觀態度,不過,作為一名Web 開發者,應該去了解並應用這項技術。
未來的格局到底如何,某種技術到底有沒有前途,都不是由個人說了算的。我想,B/S與C/S之爭最終的格局,將是多面向因素共同博弈的結果。對個人而言,必須與時俱進,及時調整自己的行動和策略,這是當代軟體開發者的宿命。