基於AngularJS的企業軟件前端架構[轉載]

這篇是我參加QCon北京2014的演講內容:html

提綱:

企業應用在軟件行業中佔有很大的比重,而這類軟件多數如今也都採用B/S的模式開發,在這個突飛猛進的時代,它們的前端開發技術找到了什麼改進點呢?前端

B/S企業軟件前端開發模式大致上與桌面軟件相似,都是偏重量級的,在前端可能會有較多的業務邏輯,這些業務邏輯如何被合理模塊化,與界面分離,以便測試,成爲這個領域的一個重要挑戰。另外一方面,因爲企業應用的界面相對規整,偏重的是數據存取,沒有太多花哨的東西,因此常見的界面控件也是可枚舉的,如何讓開發界面的工做能更快完成,甚至由不擅長編寫代碼的業務設計人員來作,與界面原型的工做合二爲一,能提升很多開發效率。node

在AngularJS等MV*框架出現以後,給這個領域帶來一些契機,架構師們可以有機會去從新規劃前端的架構,甚至是開發流程,從而讓整個軟件的生產更爲高效。git

本文將探討它給這個領域帶來的變化。 github

正文:

企業應用前端的特色

企業應用系統是一種很常見的軟件系統,這類系統的特色是面向某個行業,功能較複雜,對界面的要求通常是整齊,不追求花哨。這類系統一般有C/S和B/S兩個流派,其中的B/S方式由於部署和集成的便利,使用得較爲廣泛。npm

一樣是在瀏覽器中作東西,寫企業應用和網站的差異也很明顯。企業應用的業務邏輯較重,前端有必定的厚重性,可是對效果並不追求不少,主要是各種控件的使用,表單的存取值等等。gulp

企業應用產品的一些特色以下:後端

  • 獨佔模式。

通常用戶使用互聯網產品,都是片斷時間使用,好比購物或者閱讀,作完以後就刷新或者關閉瀏覽器了,而企業應用每每是工做的所有,從早上上班開始打開,到下班才關掉,一天絕大部分工做都在上面完成,好比一個呼叫中心的操做員。設計模式

  • 重業務,輕視覺

企業應用對視覺的追求是比較低的,通常不會要求花哨效果,以業務操做的流暢性爲第一目標。瀏覽器

  • 界面規整,模式單一

企業應用的界面佈局相對有模式可循,能夠用不多的場景來窮舉,界面橫平豎直,比較規整,使用到的控件元素也是可窮舉的,基本沒有什麼特效。

  • 鍵盤操做

因爲企業應用的用戶都相對比較專業,在上崗以前須要通過統一培訓,並且每一個用戶使用的頻度較高,不少時候他們會用盡可能快捷的方式來作操做,好比鍵盤,這一點在互聯網產品中比較少見。因此,有時候你們爲了追求好看,把系統原生的select用div來替換,在這種狀況下反而增長了用戶的麻煩。

  • 邏輯複雜

我以前所在的行業中,業務邏輯很複雜,前端可能會須要寫不少複雜的邏輯,JS代碼大部分是在處理邏輯,而不是界面交互。

  • 加載速度的側重不一樣

互聯網產品每每很重視首屏優化,可是其策略可能與企業應用不一樣。好比說,3個200k的模塊,在網站型產品中可能優化成一個100k加三個150k的模塊,但在企業應用中,極可能優化成一個400k加三個50k的模塊。爲何會這樣呢?由於內容型的網站講究的優化策略是分攤,若是首次加載太慢,會很影響用戶的信心,但企業應用用戶的容忍度是較高的,他並不在意剛打開的時候慢一些,由於打開了以後就要用一天,對於以後每步操做的模塊加載速度卻是要求很高。另外,對於內存泄露的處理,也要求得比較高一些。整個這些策略,實際上是來源於C/S系統的影響。

  • 瀏覽器版本相對寬鬆

不少時候提到企業應用,你們的想法就是低端,IE6,但其實這個的緣由是客戶只購買軟件,運維通常本身作,每一年不會有不少持續的投入來改進,因此致使不少老系統不能持續升級。軟件廠商其實反倒能夠用更激進的策略去升級瀏覽器,用戶對這個的接受度仍是比較高的,使用系統的羣體也是比互聯網用戶小不少的,拋棄老舊瀏覽器的事情也確實能夠幹,好比我就見過幾年前某電信營業系統預裝的都是Firefox。

企業應用常見的前端框架

在開發B/S企業應用前端的人羣中,有很大一部分羣體選擇了服務端的組件化方式,好比JSF之類,它的弊端是與異構服務端的第三方系統集成比較麻煩。也有很多人使用Bindows和ExtJS這樣的框架,最近的KendoUI也是個不錯的選擇。

每種類型選一個有表明性的來講說:

  • HTC 在瀏覽器端擴展標籤

早期有些團隊採用的方式,通常會跟XMLHTTP等結合使用,易於使用,界面代碼整潔,但已被主流瀏覽器拋棄。

  • JSF等 在服務端生成界面

之後端爲主的架構師最推崇的方式,受Struts的MVC模型影響很深,弱化了前端,使得前端蛻化爲後端的一種附屬。

  • GWT 編譯階段生成界面

寫其餘語言來生成HTML和JS,通常會依賴於一種前端UI庫。這種方式也比較受後端架構師喜歡,由於他們以爲寫JS很頭疼,寧肯寫Java。

  • ExtJS 用JS封裝界面組件,乾脆就不要HTML了

這是另一種極端,從Bindows開始,使用純邏輯代碼來描述界面,走着跟Java Swing同樣的道路,也有很多人喜歡。但這種方式在沒有好用的界面設計器的狀況下很是痛苦。

  • Flex等 脫離HTML體系,另闢蹊徑

這條路實際上是對Java Applet的一種延續,好處是能夠不受HTML體系的制約,獨立發展,因此其實這些體系在企業應用領域的成熟度遠超HTML體系。

曾經的企業B/S應用幾件寶

有一段時間,咱們幾乎只有IE6,因此那個時候的前端開發人員很快樂,沒有兼容的壓力。那時候,咱們如何構建前端應用呢?

參見http://weibo.com/1858846672/B1fL3vuYN?mod=weibotime

  • HTC

這是最好用的聲明控件的方式。

  • XMLHTTP

儘管尚未AJAX的概念,但咱們已經能夠用它作先後端分離的傳輸機制了。

  • VML

在IE裏面畫矢量圖,不使用插件,有其餘選擇嗎?

  • XSLT

把XML數據轉換成HTML,跟如今的前端模板像嗎?

  • popup

建立右鍵菜單最好的方式。

用這些技術構建的一個典型企業應用

單頁應用和前端分層

當時這些系統的構建方式也能夠算單頁應用,咱們用iframe來集成菜單,每一個菜單有本身獨立的功能,整個主界面是始終不會刷新的。

時光飛逝,這些年,前端有了什麼本質的改變,產生了翻天覆地的變化嗎?

有時候咱們回顧一下,卻發現多數都是在增長完善一些細節,真正有顛覆性的有好比以RequireJS和SeaJS爲表明的模塊定義和加載庫,npm這樣的包管理器,grunt,gulp,百度fis這樣的集成開發模式。爲何它們算是本質改進呢?

由於這些標誌着前端開發從粗放的模式,逐漸變化到精確控制的形態。好比咱們不再能無論代碼的依賴關係,也不能一打開界面就不分青紅皁白把全部可能要用到的代碼都馬上加載過來,那個時代已通過去了,從任何角度講,現代的前端開發都在精細化,從代碼的可控,到界面體驗的精細優化,到整個團隊甚至公司甚至互聯網上的組件共享,以及前端團隊協做流程的改進,這已是一個很成規模的產業了。

咱們把眼光放到2013年,在這一年裏最火的前端技術莫過於NodeJS和AngularJS,前者給咱們帶來的是一種開發方式的改變,後者是一種典型的前端分層方案。Angular是前端MV*框架的一個流派,用過的人都會以爲很爽。它爽在什麼地方呢?由於它幫咱們作的事情太多了,一個雙向綁定,無所不包,凡是存取值相關的操做,基本都不用本身寫代碼。在企業應用前端功能裏,表單的存取值和校驗佔據了很大的比例,這些事都不用幹了,那簡直太好了。

若是就由於這個用Angular,那還有些早。有一些第三方代碼被稱爲庫,另一些稱爲框架,Angular是框架而不是庫。框架的含義是,有更強的約束性,並不是做爲輔助功能來提供的。

先看一下企業應用的一般形態吧,會有一個可配置的菜單,而後多半會採用MDI的形式,能打開多個業務功能,用選項卡的形式展現起來,能夠隨時切換操做。每一個人天天經常使用的功能是能夠窮舉的,他進入系統以後,通常要用到下班才關掉。因此這種系統很是適合作成單頁應用,開始的時候加載一個整體框架,每點擊一個菜單,就加載這個菜單對應的功能模塊,放在一個新的選項卡或者別的什麼地方展現出來。

在早期作這種系統的時候,通常都會用iframe來集成菜單,這種方式很方便,可是每一個菜單頁都要載入共同的框架文件,初始化一個環境,數據之間也不能精確共用。

因此如今咱們作企業信息系統,再也不適合用iframe來集成菜單,全部菜單的業務代碼,會在同一個頁面的做用域中共存。這在某些方面是便利,好比數據的共享,一個選擇全國城市的下拉框,在多個功能中都存在,意味着這些城市的數據咱們能夠只加載一次。但從另一個角度來講,也是一種挑戰,由於數據之間產生干擾的可能性大大增長了。

咱們回顧一下在傳統的客戶端開發中是怎麼作的,早在經典的《設計模式》一書中,就提到了MVC模式,這是一種典型的分層模式。長期以來,在Web開發人員心中的MVC,指的都是Struts框架的那張圖,但咱們單頁應用中的MVC,其實更接近最原始的《設計模式》書中概念。因此咱們要在前端分層,而不只僅把整個前端都推到視圖層。

作單頁應用,前端不分層是很難辦的,當規模擴大的時候,很難處理其中一些隱患。分層更重要的好處是可以從全盤考慮一些東西,好比說數據的共享。跨模塊的數據共享是一個比較複雜的話題,搞得很差就會致使不一致的狀況,若是考慮到在分層的狀況下,把各類數據來源都統一維護,就好辦多了。

因此,以AngularJS爲表明的前端MV*框架最重要的工做就是作了這些對於分層的指導和約束性工做,在此基礎上,咱們能夠進一步優化單頁應用這類產品。

前端的自定義標籤體系

構建一個大型企業應用,最重要的是創建整套組件體系。通常針對某行業的軟件,長期下來都會有不少固定的模式,能夠提煉成組件和規則,從前端來看,體現爲控件庫和前端邏輯。控件庫這個是老生常談,在不少框架裏都有這個概念,但各自對應的機制是不一樣的。

從寫一個界面的角度來說,最爲便利的方式是基於標籤的聲明式代碼,好比咱們常見的HTML,還有微軟的XAML,Flex中的MXML等,都很直接,設想一下在沒有可視化IDE的狀況用相似Java Swing和微軟WinForm這樣的方式編寫界面,毫無疑問寫XML的方式更易被接受。因此,咱們能夠得出初步的結論,界面的部分應該寫標籤。

很遺憾,HTML自帶的標籤是不足的,它有基本表單輸入控件,可是缺少DataGrid,Tree之類更富有表現性的控件。因此絕大多數界面庫,都採用某種使用JavaScript的方式來編寫這類控件,好比:

<div id="tabs">
  <ul>
    <li><a href="#tabs-1">Nunc tincidunt</a></li>
    <li><a href="#tabs-2">Proin dolor</a></li>
    <li><a href="#tabs-3">Aenean lacinia</a></li>
  </ul>
  <div id="tabs-1">
  </div>
  <div id="tabs-2">
  </div>
  <div id="tabs-3">
  </div>
</div>
$(function() {
    $( "#tabs" ).tabs();
});

若是這樣,這些複雜控件就都要經過JavaScript來建立和渲染了,這與咱們剛纔提到的原則是違背的。那咱們尋找的是什麼呢,是一種能擴展已有HTML體系的東西。在早期,IE瀏覽器中有HTC,能夠經過引入命名空間來聲明組件,如今的標準瀏覽器中又引入了Web Components,在Polymer這個框架中能夠看到更多的細節。說到底,這類方式要作些什麼事情呢?

  • 隔離組件的實現,讓使用變得簡單
  • 支持自行擴展新的組件
  • 做一些做用域上的隔離,好比Web Components裏面,style標籤上能夠加做用域,表示這個樣式只生效於組件內部

從另一個角度講,爲何咱們非要這麼作不可?最大好處來自哪裏?對於大型項目而言,管理成本和變動成本都是須要認真考慮的。若是一個組件,須要在DOM中聲明一個節點, 而後再用一個js去獲取DOM,把DOM渲染出來,再填充數據的話,這個過程的管理成本是很大的,由於HTML和JS這兩個部分丟了一個都會有問題,不管在何時,維護一個文件老是比維護多個文件要強的,咱們看HTC那種方式,爲何它的使用成本很低,由於它能夠把控件自身的DOM、邏輯、樣式所有寫在本身內部,整個一個文件被人引用就能夠了。在如今這個階段不存在這麼好用的技術了,只能退而求其次。

因此,在這個點上,Angular帶來的好處是可擴展的標籤體系,這也就是標籤的語義化。Angular的主打功能之一是指令,使用這種方式,能夠很容易擴展標籤或者屬性。好比,業務開發人員能夠直接寫:

<panel>
     <tree data="{{data}}"></tree>
</panel>

這樣多麼直觀,並且能夠跟原有的HTML代碼一塊兒編寫,不形成任何負擔。語義化的標籤是快速編寫界面的不二法門。

業務邏輯

有了語義化標籤以後,若是咱們只寫界面不寫邏輯,那也夠了,但現實每每沒有這麼美好,咱們還要來考慮一下業務邏輯怎麼辦。

企業應用通常都是面向某行業的,在這個行業內部,會有一些約定俗成的業務模型和流程,這些東西如何複用,一直是一個難題。以往的作法,會把這些東西都放在服務端,用相似Java這樣的語言來實現業務元素、業務規則和業務流程的管理。

這種作法所帶來的一個缺點就是對界面層的忽視,由於他只把界面層看成展現,對其中可能出現的大量JavaScript邏輯感到無所適從。不少從事這一領域的架構師不認同界面層的厚度,他們認爲這一層只應當是很薄的,純展現相關的,但在這個時代,已經不存在真正輕量級的界面了。

前面提到,咱們在前端做分層,把展示層跟業務邏輯層徹底隔離,帶來的好處就是邏輯層不存在對DOM的操做,只有純粹的邏輯和遠程調用,這麼一來,這一層的東西均可以很容易作測試。對於一個大型產品來講,持續集成是頗有必要的,自動化測試是持續集成中不可缺乏的一環。若是不作分層,這個測試可能就比較難作,如今咱們能把容易的先作掉,並且純邏輯的代碼,還能夠用更快的方式來測試。

以前咱們作前端的單元測試,都須要把代碼加載到瀏覽器來執行,或者自行封裝一些「無頭瀏覽器」,也就是不打開實際的展現,模擬這個測試過程。這個過程相對來講仍是有些慢,由於它還有加載的這個網絡傳輸的過程,若是咱們能在服務端作這個事情呢?

咱們看到,最近很火的NodeJS,它從不少方面給了前端工程師一個機會,去更多地把控整個開發流程,在咱們這個場景下,若是能把針對前端邏輯的單元測試都放在node裏作,那效率就會更高。

二次開發平臺

咱們來看看,有了這麼一套分層機制,又有了界面標籤庫以後,該作些什麼呢?

作企業軟件的公司,有很多會作二次開發平臺,這個平臺的目標是整合一些已有的行業組件,讓業務開發人員甚至是不懂技術的業務人員經過簡單的拖拉、配置的形式,組合生成新的業務功能。

從界面的角度看,拖拽生成很容易,不少界面原型工具均可以作,但要如何整合數據和業務?由於你要生成的這個功能,是實實在在要拿去用,不是有個樣子看就能夠,因此要能跟真實數據結合起來。 但這事情談何容易!

就好比說,界面上有一個選擇所屬行業的下拉框,裏面數據是配置出來的,對這個數據的查詢操做在後端,做爲一個查詢服務或者是業務對象管理起來,有些傳統的方式多是在後端做這個關聯,Angular框架能夠把這個事情推到前端來。相比Backbone這樣的框架來講,Angular因爲有雙向綁定,這個過程會變得特別省事。一個界面片斷想要和數據關聯起來,要作的事情就是各類屬性的設置,因此動態加載和動態綁定都會比較容易。

好比:

partial.html

<ul>
     <li ng-repeat="item in items">{{item.name}}</li>
</ul>

main.html

...
<div ng-include="'partial.html'" ng-controller="CtrlA"></div>
...

a.js

function CtrlA($scope) {
    $scope.items = [{name:"Tom"}, {name:"Jerry"}];
}

b.js

function CtrlB($scope) {
    $scope.items = [{name:"Donald"}, {name:"Micky"}];
}

在上面的例子裏,這個列表顯示什麼,徹底取決於ng-controller="CtrlA"這句,若是咱們把這句搞成配置的,就很容易把數據源換成另一個CtrlB,甚至說,即便在同一版本上作項目化,引入另一個包含CtrlA其餘版本的js文件,也基本無需更改其餘代碼,這就達到了二次開發的一個目的:儘量以配置而不是編碼去新增、維護新功能。

移動開發

如今的企業軟件已經不能只考慮PC的瀏覽器了,不少客戶都會有移動辦公的需求。響應式設計是一種常見的解決方案,可是在企業應用領域,想要把複雜的業務功能設計成響應式界面的代價太大了,何況界面設計自己就是開發企業軟件的這些公司的短板,因此咱們的比較簡單的辦法是對PC和移動終端單獨設計界面,這樣就有了一個問題了,這兩種界面的業務邏輯並無差異,若是咱們要維護兩套代碼,代價是很是大的,能有什麼辦法共用一些東西呢?

若是不採用分層的形式,那這個很麻煩,咱們注意到兩種系統的差別只在UI層,若是咱們用分層的模式,能夠共用UI層之外的東西。具體到Angular裏面來講,好比service,factory,甚至controller都是能夠共用的,只有directive和HTML模板隨設備產生差別就能夠了。

以前咱們不多看到有基於Angular的移動端開發框架,但如今有了,好比Ionic,使用這樣的框架,能夠直接引用已有的業務邏輯代碼,只在展現上做一些調整。這麼作有不少好處,同時也對代碼的架構水準有必定要求,須要把業務邏輯跟界面展現徹底切割開。

這樣帶來的好處也是很明顯的,獨立的業務邏輯,由於它不依賴於界面了,因此很容易控制,作單元測試,集成測試,打樁等等,總之它是純邏輯的東西,在後端能夠用什麼方式保證代碼質量,在前端的業務邏輯也同樣能夠用,業務邏輯能夠所以而清晰穩定。

對於企業應用而言,這麼作能夠極大程度地複用以往的業務邏輯,只在負責最終展現的代碼部分做差別化。

工程化

上面這些技術性的問題都解決了,剩下的都是規模帶來的邊際效應,這須要咱們從工程化角度去考慮不少問題:

  • 某個JS模塊被修改,如何得知會影響誰?
  • 某個界面片斷被調整,會影響什麼界面?
  • 如何最小化發佈?
  • 如何一鍵測試、打包、壓縮?
  • 。。。。。。

這些話題,篇幅所限,不在本文中敘述,能夠查看我另外的關於Web應用組件化的文章。

 

原文地址: 基於AngularJS的企業軟件前端架構

相關文章
相關標籤/搜索