仁者見仁,智者見智。在這種問題上每個優秀的技術人員應該總是有自己獨特的見解。能得到一個能“服眾”的結論固然好,但是支持百家爭鳴更為重要。我始終認為Atlas的最大長處不在於其AJax特性,不在於其提供了復雜JS才能實現的多樣化功能。在我看來,Atlas是很了不起的,而它的了不起體現在三個地方:
1. Declarative Syntax:
應該有不少人有過在Html Element中嵌入浏覽器無法識別的屬性,而在某個地方通過自己編寫的Javascript方法讀出並加以一些功能。其實我在數年前總覺得這樣的方法是tricky solution。我不喜歡tricky的方法,特別是無條理性的tricky solution。這樣的方法的確可以work,但是可讀性一般比較差。在大多數時刻,我始終把代碼的可維護性放在第一位。後來由於在項目中需要開發一個Rich ClIEnt,給用戶以大量的操作自由度(描述不當,不過估計無法用三句兩句話說清了),於是不得不使用了這個方法。在進行了大量嘗試後,發現如果合理使用,這的確是一個非常靈活有效,並且易於維護的方法。ASP.Net強大的客戶端Element模型又可以說對這種方法合作的幾乎天衣無縫。
Atlas的Declarative Scripts可以說將上面提到的這個方法進行了極大的升華。將一個從一開始似乎十分Tricky的方法變成了另一種開發方式,將程序設計和XML結合在了一起。事實上,這給了許多項目設計一個參考。將客戶端代碼的結構化也大大地提高了可維護性。
原來,代碼還可以這麼寫。
2. Extendable Behavior, Extender, etc.
它們所作的貢獻是提供了良好的設計。能讓程序員輕松地寫出符合良好設計的代碼。
一個良好設計的代碼,其中一個非常基礎的特點就是“high cohesion”,也就是“高內聚”。高內聚的組件與外界的依賴很少,這樣大大方便了開發,調試,測試,發布和部署。
就拿開發一個Extender來說,需要的就是寫一個Class Library,並編譯成一個程序集。使用時只需簡單的引入,並像使用普通控件一般即可。在開發時需要的也僅僅是Atlas的基礎結構,少得不能再少的一個程序集。
還是一個典范,還是一個示例。
3. Powerful Foundational Framework
這裡不提Atlas提供了一個完全面向對象的編成框架,提供了一個Compat層來兼容多個浏覽器等。現在來思考一個問題:如何寫出高性能的Web應用程序?
或者換個角度想一下,一個網站的性能是從什麼方面體現出來的?這不光是要服務器端的努力,特別是現在客戶端越來越Rich,客戶端的Load也越來越多。優化PLT(Page Load Time)也是一個越來越重要的議題。這需要對於浏覽器,Html以及HTTP標准有相當完整的認識。通過分析Page Load來優化一個頁面能夠達到非常了得的效果,經過PLT優化的網頁往往能將一張頁面的打開時間縮短3-5秒甚至更多,並且往往也能減少服務器端的運算以及流量。
Atlas的基礎代碼框架的每一步都是盡量地符合優化PLT的Best Practice。所以使用Declarative Script和Atlas框架所提供的JS類往往效率會比較高。打個比方,浏覽器對於相同域名只會並行地使用兩個端口進行加載,因此將不同資源從不同域名加載是優化PLT的一個常用方式。但是由於可能JS中任何部分的代碼都可能會改變的頁面的DOM或者Render出不同的內容(例如使用document.write),因此浏覽器在下載JS文件時是會Block住其他任何的資源加載,無論其是否在同一個域名中。加上現在JS文件越寫越大,數量越來越多,因此浏覽器的加載能力就被削弱了。在Atlas中,Binding機制能比較好地處理JS加載問題,以優化頁面的PLT以及Perceived Performance。
Atlas的缺點?
其實我有時候總是會想,Atlas代碼是不是寫的太龐大了,使用起來方便嗎?比如其OO特性,使用起來似乎不是很方便,代碼量和代碼體積頗高,而且對於沒有接觸過Atlas的人不是很容易看懂。外界不少提供面向對象機制的JS框架似乎就精煉許多。我也因為某些需要為JS寫了一套面向對象機制的擴展,很簡單,使用方便,OO機制使用方式也是盡可能地向Java代碼靠攏。繼承,虛函數等必須的功能也一個不缺。
不得不說,這個似乎是Atlas的一個瑕疵。但是瑕不掩瑜,Atlas依舊是一套優秀的JS框架。它實現的Ajax,卻又遠遠超越了Ajax本身。沖著AJax or .Net來接觸Atlas的程序員往往總是能從它身上得到驚喜。
學習Atlas……
我經常在我身邊的開發人員中推薦.Net,雖然無償,但是沖得就是對這一技術的喜愛。我是技術人員。當然對於Atlas也向別人進行過介紹,也看到不少人學習Atlas的情況。
似乎Atlas進入了.NET相同的情況,大家紛紛在使用,感覺很爽,而去了解它是如何做的人卻很少。知道在什麼情況下如何使用的人也很少。而且能夠靈活使用的人,往往也對其機理有了相當認識。可能的確只有從一個特定的層次以及角度去看它,才能對它有更好的掌握能力。“使用論”和“深入論”的爭鋒似乎依舊存在。忽然想起Jeffrey Richter說過他的CLR via C#市場反響不好,現在越來越少的人希望從CLR層面去了解.Net Framework……
其實我也是“使用論”的支持者,但是我僅僅支持良好的使用方式。這都不是一朝一夕能夠煉成,也不是僅僅靠了解一門技術就能做到的。要成為一個優秀的技術人員,所需的技術覆蓋之廣,其實遠超過普通技術人員的想象。
經典評論:
1.
Atlas先天不足,在我的文章:http://dflying.cnblogs.com/archive/2006/05/01/390401.Html 中headchen朋友有這樣一條評論,絕對入木三分,這才是真正高手的看法:
(以下引用headchen朋友的評論)
1. Javascript試基於原型prototype的繼承機制,通過構造函數和原型對象來模擬類。這一點在Atlas中當然不會發生改變。只不過他在暗地裡全都處理了,處理得方法是:派生類拷貝了基類原型對象得所有方法到自己得原型對象中。這樣當一個派生類繼承於一個基類時,自動繼承類通過原型對象實現得實例方法(當然派生類的原型對象中若存在同名方法,則不拷貝)。
2. Atlas通過registerBaseMethod來聲明得虛方法僅僅時構造函數得內部方法(有一些文檔中稱為privilege方法,意思時能夠訪問構造函數得局部變量,Atlas正是通過這個來模擬私有變量的)。而Atlas中大量的get_ set_正是此類方法。
3.在Javascript中實現一個類的實例方法有兩種途徑:1 把方法定義在原型對象中,這個在使用時自動通過訪問原型鏈來訪問實例的方法。這種方式的好處是節省內存,效率比較高(這裡說的效率是實例化對象時的效率),因為多個實例的方法都存在一個原型對象中。2 定義為原型對象的內部方法(上面已經說過來),這種方式,在初試化實例對象時,實際上是給每個對象實例都定義了一個相應的方法。所以初試化實例對象時需要更多的內存和時間。但這種實現方式有他存在的必要性,那就是利用函數的closure特性來實現特有的需求,比如:生成事件委托,回調函數,實現局部變量等等。但如果對象實例很多時,存在很大的效率問題,所以把他稱為privilege方法也時有道理的,那就是他的存在的理由就是為來利用closure。
微軟在Atlas種大量使用privilege方式來實現實例方法,而有意無意的淡化來Javascript固有的prototype的實現方法,從語法上來看更接近C#的語法,另外Atlas種存在大量的get_ set_ 類方法也只能通過這種方式來實現,我們也看到絕大多數類實例的方法,即使不是必須,也大多采用類這種實現方式,而不是prototype的方式。對於這種動向,本人時持有反對意見的。很明顯的看出:Atlas有.Net情結。想在Javascript環境實現一個穩固嚴密的架構,但確犧牲了 Javascript原有的靈活性,並且犧牲了大量的內存和效率。
所以我們可以利用Atlas提供的一些擴展,比如對於String Array Function等的擴展,特別時命名控件,事件委托等等。但不必完全拘役於它或者完全模仿他。
Atlas對Function,Array,String的擴展是通過prototype來擴展的,這也是Javascript中的唯一的選擇,也是 Atlas的基礎性的建設。我說的Atlas內部函數的傾向是指架構中類(class)以及繼承等的實現。可以看出,在Atlas中除了對 Function,Array,String,Date的擴展和對Event的實現外,其他類的實現均是通過內部函數的方式,而不是prototype的方式,前面我說過,內部函數的方式有存在的必要性,但除非必要(比如你要實現一個供setTimeout使用的回調函數等),在Javascript中對類實例的方法的標准實現是通過prototype的,這是ECMAScript的規范。當然不是說通過內部函數的方式實現不可以,就是存在內存和效率問題,如果一個類的實例可以預見到不是很多,則無所謂了。如果比較多的話,問題就來了。
我認為,在Atlas的客戶端腳本中存在的某些傾向有一定的問題:
1. 為了語法的完整大量采用內部函數來實現類方法,前面已經說的夠多的了。
2. 過份強調了嚴密性而放棄了靈活性和效率。典型的就是對對象屬性的實現方式。大量采用了get_ set_ 這樣的內部函數。就其好處,當然首先保證了私有變量安全,另外可以對屬性的值進行校驗,便於擴展,還有就是可以觸發事件或者其他的聯動計算來保證數據的完整性。另外在解析XML腳本時保證來對屬性訪問的合法性。PME的概念在.net中可以說時很普遍,也是C#,VB.net等語言固有的特性,但這些並不是Javascript固有的特性,可以說Javascript語言從設計到發展到標准化(ECMAScript)都不是這個方向,從將來的趨勢來看也沒有這種趨勢。因為客戶端腳本的目標和一個編譯性語言時不同的,他的特點時簡潔、靈活、強大,他存在於宿主環境中,他最主要的目標是操作宿主對象,所以對自身的面向對象的特性方面要弱一些,而且並不嚴密,存在很多不足。若非要那他來建立一個“堅固”的客戶端腳本環境,我不會看好這個方向,或許微軟把 JScript.Net強制放在IE環境下會比在JScript中磕磕絆絆地模擬好一些,但這是不可能的。要我來說的話,那些大量的set_ get_ 還是扔了吧,盡管他有不少好處,但和付出的代價來說,太不劃算了。
Atlas的抱負可能太大了一些,依我看,照此路發展下去(不僅僅是客戶端腳本),很難成功。當然對於微軟來說,沒有什麼是不可能的,我們還是拭目以待吧。
2.
其實這些是選擇實現JS類的比較關鍵的地方。Atlas的目的是完整的在客戶端實現一個盡量嚴謹的OO機制,但是有些地方受限於JS本身導致的不足,而又異常復雜,實現得也不很直觀,有種高不成低不就的感覺。因此我把它視為值得一提的缺點。
在Atlas的“硬傷”之下,還是可以有針對性地進行優化,這個需要大量的琢磨、歸納和努力啊,路漫漫其修遠兮……