《開源框架那些事兒22》:UI框架設計實戰

UI是User Interface的縮寫,通常被認爲是MVC中View的部分,作用是提供跟人機交互的可視化操作界面。MVC中Model提供內容給UI進行渲染,用戶通過UI框架產生響應,一般而言會由控制層調用業務邏輯進行處理,並把處理結果以Model方式返回View,再次渲染。UI框架的大致過程就是如此,按實現方式可以分爲RIA和瘦客戶端方式,目前基於B/S的瘦客戶端方式比較流行。
UI框架套路上很簡單,但是想要做好可就不容易了。目前基於MVC的框架燦若繁星,不客氣的說是個軟件公司就有自己的技術框架,技術厲害的公司可能還有幾套。筆者也經歷過多家互聯網公司,也用過不少框架,界面開發始終是短板所在。

 

一、新UI框架的需求由來


1. 場景A

UI框架對View層沒有封裝或者支持有限。View層的代碼全部需要開發人員手動完成,框架沒有提供代碼封裝或者相關代碼生成工具,導致項目開發流程中,出現大量Ctrl+C、Crtl+V,進而影響界面代碼質量。
筆者曾和IT業界比較有名的外包公司合作過項目,一個JSP頁面四、五千行代碼,Java業務邏輯、html佈局和css樣式糅合在一起,不要說修改了,就是看明白頁面也是異常艱難。跟開發人員溝通瞭解到,團隊採用界面實現方式是jsp,框架提供的樣式不滿足客戶需求,迫使團隊自行開發很多框架層面的功能。經常一個需求變動,導致開發人員修改十幾處地方,頁面的混亂就可想而知了。

2. 場景B
技術框架分層嚴格,界面完全組件化。View層和Model層完全分離,開發人員編寫頁面需要額外學習組件,訪問後臺成本巨大,很多業務需求需要通過框架升級方式才能解決,時間浪費嚴重。
這是從一個極端走到另一個極端,以嚴格的框架徹底限制死開發人員。筆者參與過的銀行項目,就是採用這種方式:開發人員寫的頁面全是組件模板,無法靈活定義一些功能,導致全部業務需求完全通過組件體現,而且開發人員本身無法修改組件,組件存在Bug或者無法實現某些業務場景,那開發人員還要在組件團隊、項目領導之間扯皮,搞得所有人身心俱疲。

3. 場景C
框架性能問題。框架設計人員追求華麗的頁面效果,完美的層次封裝就容易導致這種後果,特別是在頁面複雜或者頁面嵌套多時,很容易發生這種問題。
開發人員最怕遇到這種問題,這意味着項目要傷筋動骨。還以銀行項目做例子:原先框架版本是3.0,業務領導認爲界面太土,不美觀,經過框架團隊一年多的努力,框架4.0對界面做了大幅度的美化處理,提供了複雜的封裝,結果造成嚴重的性能問題。因爲銀行項目頁面複雜,有些表單要展示幾百個字段,用框架4.0開發後要10多秒,根本無法被接受。最後這一系列的代價由開發人員買單,用html原生語法重新開發這個複雜頁面。

4. 場景D
升級維護問題。有些框架設計時,設計人員迫於團隊或者領導壓力,框架集合太多業務邏輯,導致後期團隊面臨兩難選擇:不升級,Bug無法解決;升級界面產生各種問題,需要花費大量精力去糾正。
這種場景也不少見,特別是框架包含多個項目的業務需求時,衝突由爲明顯,筆者經歷過一個項目:每次升級,代碼需要對比幾百處,浪費2-3天的時間,就這樣還不能保證完全正確;最可怕的是,每次升級都要如此。

歸納一下,對UI框架有如下需求:
1.提升開發效率,減少重複代碼。對於開發人員而言,開發時,界面寫得代碼越短越好;維護時,修改的地方越少越好。
2.清楚的UI層次,框架可以分離業務邏輯、佈局和樣式,讓頁面結構清晰明瞭,讓開發人員集中更多精力在業務邏輯,而不是頁面佈局、js、css等技術細節。
3.豐富的組件支持,項目團隊大部分業務場景應該可以被框架組件涵蓋,而無需重新開發。
4.靈活的擴展能力,項目團隊可以根據框架規範自行擴展展示組件,實現個性化需求。
5.優異的性能,UI界面展示時的響應時間應該和原生態語言接近。框架能處理JS、CSS加載及合併的問題。
6.框架升級不影響業務代碼。

只有滿足上述要求的UI框架,對開發人員和項目團隊纔是真正有幫助的UI框架。

 

二、TinyUI的解決方案

 
Tiny團隊對UI框架也有自己的想法,也提出一種UI框架解決方案。TinyUI採用如下設計原則,項目團隊在技術選型時需要考慮清楚。

TinyUI的原則
1.保證界面開發的靈活性,尊重開發人員的開發權利。
Tiny團隊遵守“二八”原則,認爲再完美的UI框架也只能解決80%實際開發過程中遇到的界面問題,剩下的20%需要開發人員的經驗和智慧才能解決。那種提倡一攬子解決全部界面開發問題的UI框架,只會讓設計者陷入過多技術細節,導致過度設計。因此,TinyUI提供最大程度的靈活:只要遵守必要的框架規範,開發人員可以自由擴展組件,來滿足日益變化的業務需求。
2.技術問題與業務邏輯分離。
TinyUI採用開源協議,作爲開源軟件來提供UI框架,代碼本身不包含任何業務邏輯。避免框架設計者開發業務組件,業務團隊使用的模式。技術問題由設計者解決,而業務邏輯由業務團隊根據自身業務靈活定製、擴展。
3.性能至上,效率優先。
TinyUI在設計初期就考慮組件性能問題,目標是接近原生態頁面;其次,UI框架完全開源,開發人員只要熟悉模板語言,就可以輕鬆上手,避免因爲學習曲線過高影響開發效率。
在上述原則的指定下,TinyUI具有如下特性:

特性
1.TinyUI是基於JQueryUI,相較於Dojo來說,JQueryUI更容易上手,使用也更簡單;相對於ExtUI來說,它更輕量,速度響應也更好;同時它也是可胖可瘦,即可以實現比較大的控件,也可以用少量代碼就使得界面更加靈動。
2.佈局與界面分離。TinyUI引入模板引擎,頁面採用模板+組件的方式進行渲染,可以大幅簡化頁面。
3.採用了多重佈局方式,每一級目錄當中都可以編寫一個佈局。項目經理可以根據業務需求按不同層級定義不同的佈局。
4.採用了pagelet方式,可以把頁面區塊獨立提供或者被別的頁面進行引用。
5.提供了UI組件模式,用戶可以方便的編寫UI組件,併發布到應用當中,同時提供了資源加載機制,如果UI組件包含有JS或CSS文件,不用特別指定,也不用進行首頁合併,可直接被使用。
6.提供了BigPipe機制,可以大大提供模板的處理速度及提升用戶界面的使用體驗。
7.通過組件方式開發界面,封裝了組件的實現細節,可以平滑切換到其它實現。
8.與各種開源組件或代碼段集成更容易,利用一個已經實現的開源組件封裝成UI組件,只要幾分鐘。接口的擴展可以循序漸進,隨用隨包裝。
9.資源自發現。框架會自行加載新增加的組件,所有的css/js文件都會自動進行添加。

TinyUI實際上並不是一個具體的UI展現組件,它只是一個UI構建體系。它可以適應於各種Html+CSS+JS的體系架構中,提供以UI方式開發界面的技術方案。

組件規範
TinyUI認爲界面所有公用的內容都可以由UI組件包(UIComponents)概括。UI組件包包括一個或者多個組件(UIComponent),UI組件包中包含了其所需的css/js/gif/htm等等各種資源。同時有一個UI組件包描述文件(*.ui.xml),描述對UI組件包的結構、內容、以及對其它UI組件包的依賴關係。
開發時,UI組件包以獨立的maven工程爲單位,最後以Jar包爲單位進行發佈。
舉例:我們要複用JQuery,實際上非常簡單。在Maven工程結構中,在resources目錄中,放置所有的JQuery資源進來,然後編寫一個ui組件包描述文件。UI組件包就算開發完畢了。

TinyUI框架的組件管理器會根據包描述文件自動加載、引入相關資源,而這些都無需程序人員干預。

頁面規範
TinyUI推薦採用模板語言,如:tinyTemplate,FreeMaker等作爲展現層,這樣可以充分發揮組件包的優勢。Tiny內部實現複用了tinyTemplate模板語言,但是實際上並沒有限制,你完全可以用其它模板語言做同樣的事情。

具體頁面開發時,組件開發人員採用宏定義具體的函數接口,普通開發人員直接調用宏接口就可以了。
 
舉例:


 這樣寫頁面多簡單,採用Tiny框架的前臺開發,基本上幫助你解決了上述難題,但是對你的工作沒有任何限制。


小貼士
Dojo簡介:
Dojo是一個用javascript語言實現的開源DHTML工具包。利用它的低級API和可兼容的代碼,能夠寫出輕便的、單一風格(複雜)的JavaScript代碼,它能提升你的web應用程序可用性、交互能力以及功能上的提高。

ExtUI簡介:
它是一種主要用於創建前端用戶界面,是一個基本與後臺技術無關的前端ajax框架。組件豐富,功能強大,可惜現在收費了。


三、TinyUI的設計思路

 

常見問題
1.UI中JS的引入與順序,JS合併的問題 。
2.UI中css的引入與順序,CSS合併的問題 。
3.重複代碼的問題。同樣的內容在許多地方都有,如果要改動就要改動許多個地方,修改時萬一遺留了,將來就是一個坑。
4.整體佈局調整困難的問題。
5.開發效率的問題,項目經理總是期望界面開發越快越好。
6.執行效率的問題,前臺響應要求速度更快。
7.國際化問題。

     ......
 
 下面,筆者依次講解TinyUI是如何處理上述問題:

 

Js和Css的引入與順序以及合併的問題

1.JS和CSS的引入問題。
傳統界面開發,程序員需要在頁面配置引入js和css的路徑,既麻煩又容易出錯。TinyUI採用組件封裝了JS和CSS,這份工作統一交給組件設計者處理,程序員開發頁面時根本不用關心需要引入哪些JS和CSS,只要知道要用哪些宏接口就行了。
2.JS和CSS的順序問題。
這個問題也是傳統界面開發之間的難點,JS和CSS之間的順序搞錯,通常會導致頁面出現亂七八糟的問題,定位問題也是異常複雜。TinyUI將順序問題交給組件管理器處理,它會依次檢查組件的依賴關係,如果有UI組件的依賴關係配置錯誤,組件管理器會記錄異常日誌,這些不正常組件不會被加載到正常組件列表。組件間的依賴關係理順後,組件內部包含的JS和CSS的關係也就理順了。TinyUI按如下順序加載JS和CSS:
a.  父組件的資源比子組件優先加載。比如組件A依賴組件B,那麼框架先加載組件B資源,再加載組件A資源。
b. 同一組件的資源,順序靠前的優先加載。組件的js和css路徑都可以配置多個,同一組件框架按配置順序依次加載資源。
3.JS和CSS的合併問題。
在傳統界面開發,性能調優往往涉及到js和css的合併,頁面的IO少了,性能自然能提高,但是對程序員來說這就很困難,改動js和css意味着很多相關頁面都要修改。TinyUI從框架層面支持js和css的合併,程序員無需手工調整,框架提供了UiEngineTinyProcessor這個適配器處理上述合併問題。


UiEngineTinyProcessor合併JS
 a. 適配器通過組件管理器獲得全部正常的UI組件,並依次遍歷每個組件
 b. 調用組件的getComponentJsArray方法,獲得該組件引用的全部js路徑,並依次遍歷每個路徑
 c. 根據路徑通過VFS獲得js的內容,合併到outputStream
 d. 合併完每個組件的引入JS內容,最後合併該組件需要調用JS代碼


UiEngineTinyProcessor合併CSS
 a. 適配器通過組件管理器獲得全部正常的UI組件,並依次遍歷每個組件
 b. 調用組件的getComponentCssArray方法,獲得該組件引用的全部css路徑,並依次遍歷每個路徑
 c. 根據路徑通過VFS獲得css的內容,合併到outputStream
 d. 合併完每個組件的引入css內容,最後合併該組件需要調用CSS代碼
 
重複代碼的問題

仔細分析頁面重複代碼的由來,主要可以分爲以下幾塊:
1.無用的資源引入。寫過頁面的人都知道,程序員最喜歡把一段段的js、css到處粘,而不分析是否有用,導致大量不必要的資源引入,降低頁面性能。TinyUI通過組件管理器管理資源,最終輸出到頁面的引用,絕對跟組件包的資源一致,只要組件設計者設計組件包時保證沒有引入無用的資源。
2.重複的業務邏輯。TinyUI採用模板語言渲染頁面,通過宏定義解決重複業務邏輯。因爲宏是可以嵌套宏的,所以理論上再複雜的頁面都可以通過宏搞定,宏如果使用得當,可以大幅度減少頁面代碼。
3.相同的功能片段。 有些業務場景需要引入統一功能片段,界面相同,TinyUI可以採用模板命令include完美處理這種場景。
 
整體佈局調整困難的問題

傳統界面開發,頁面佈局與邏輯代碼是混在一起的,特別是複雜頁面,調整起來自然困難。TinyUI的設計時一開始就將佈局與頁面邏輯徹底分成兩個文件,當然你要用TinyUI推薦的模板組織。

Tiny的模板體系組織方式如下:
?支持多層文件結構
?佈局文件統一用.layout擴展名結尾
?頁面文件統一用.page擴展名結構
?只有.page文件可以被外部訪問,訪問方式有兩種.page或.pagelet
?訪問.pagelet,實際上相當於訪問同名page,模板引擎只會做頁面渲染;訪問.page,模板引擎除了頁面渲染還要進行佈局渲染
 

也許有些人看到這裏問:將一個文件內容拆分成兩塊,還要定義兩者間的聯繫,是不是太複雜了?其實一點也不復雜,用戶根本不需要定義佈局文件和頁面文件的聯繫,請參考以下規範設計你的頁面佈局結構:

查找佈局文件規則
1.匹配當前目錄同名的佈局文件。
2.匹配當前目錄默認的佈局文件。
3.若某一級目錄無法滿足匹配條件,則向該目錄上一級目錄進行匹配,直到根目錄爲止。
 
比如:aa.page所中的路徑是/a/b/c/aa.page,佈局的渲染過程如下:

查找/a/b/c/aa.layout是否存在?如果存在,則渲染,否則查找/a/b/c/default.layout,如果存在,則渲染。

查找/a/b/aa.layout是否存在?如果存在,則渲染,否則查找/a/b/default.layout,如果存在,則渲染。

查找/a/aa.layout是否存在?如果存在,則渲染,否則查找/a/default.layout,如果存在,則渲染。

查找/aa.layout是否存在?如果存在,則渲染,否則查找/default.layout,如果存在,則渲染。

通過上面的渲染機制,程序員有可能只寫了非常少的內容,但是通過分層佈局渲染,最後出來的效果也會非常豐富多彩。

開發效率的問題
採用TinyUI框架對開發效率提升,至少有如下兩點:
1.重複代碼大幅減少,工作效率自然就提升了。
2.學習曲線降低。採用組件+模板的頁面開發模式,對普通開發人員基本可以屏蔽JS和CSS,這兩者的技能要求程度就可以大大降低;額外增加的學習成本是模板語言,對程序員而言,模板語言達到使用程度,一天足矣。
 
執行效率的問題
TinyUI框架採用如下技術手段,加快頁面的訪問速度:
1.合併頁面的JS和CSS。通過減少網絡IO請求,特別是在原頁面涉及很多資源時,提速效果就會比較明顯。
2.緩衝功能。用戶可以設定哪些頁面進行緩衝,緩衝多長時間。
3.支持BigPipe方式渲染頁面。前文說過TinyUI框架支持將大頁面拆分成一個個pagelet,讓瀏覽器可以多線程同時渲染,從而提升性能。
 
普通的web頁面,一般來說是頁面生成,網絡傳輸,前面頁面渲染,這三部分的時間加起來就是操作人員從點擊鼠標到最後看到頁面的時間。

舉例來說,一個頁面有主頁面框架,共有4個部分的內容顯示。爲了便於分析,簡化一下模型,假設主頁面框架生成需要0.2S,4個部分的內容生成各自需要0.2S,網絡傳輸與瀏覽器渲染也各計成0.2秒,這樣,在傳統的方式下,需要的時間就是0.2*5+0.2*5+0.2*5=3秒。

那麼換成BigPipe方式,時間的執行分佈大概是如下圖:


 

 

所以換成BigPipe方式,時間大概就是1.4秒的樣子。節省的時間大概是50%強一點的樣子。

當然,這個時間是在各自三段時間都是0.2秒的情況,實際運行過程中,網絡傳輸的時間在局域網中的時間會更快,後臺頁面的處理,也可以採用多線程處理的方式來進行,這樣,後面頁面處理時間可以縮短到0.4S,網絡傳輸時間有0.2S也可以了。由於採用了BigPipe方式,在0.6S的時候,就可以看到最頁面框架,後面的時間就是一塊塊出來,當後面出來的時間比較快的時候,給使用的感受就是在0.6S+界面就可以出來。這個與最初的3S,用戶體驗上明顯是有天壤之別的。

國際化的問題
對於小項目而言,可能不關心這個問題。但是TinyUI好歹是技術框架,目標是大型項目,如果不能支持國際化,那也說不過去。

TinyUI提供兩種國際化方案,任君選擇:
1.國際化資源標籤。國際化資源就很容易理解了,工程添加國際化資源文件,頁面用國際化標籤進行引用即可。
2.國際化頁面。 國際化頁面是指訪問某頁面時,模板引擎會優先使用與訪問者相同的語言的頁面文件進行渲染。譬如:存在aa.page,aa.zh_CN.page,如果非zh_CN語言的人來訪問,渲染的是aa.page,zh_CN語言的人來訪問,渲染的是aa.zh_CN.page。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章