2009年4月14日

John Resig: The DOM is a Mess (and the inspiration I got from this talk)

這個 talk 約 1 小時 12 分,推薦給對 jQuery/JavaScript 有興趣的人,對於開發 Framework/API 的人來講也有很多可以借鏡的地方。(線上觀賞影片在這裡)

John Resig 是目前很紅的 Open Source JavaScript Library – jQuery 的發明人,
他任職於 Mozilla Corporation,這場 talk 是他分享在開發 jQuery 的過程中遇到的困難以及心得感想,對我來說蠻有啟發性的,雖然 scope 差了十萬八千里,但我維護的元件性質也類似 jQuery,也會被很多 client 以各種意想不到的方式使用,也要面對 backward compatibility、graceful degradation 等等問題。

以下是我聽到的一些重點:

Graceful Degradation


這裡有個定義,在 web browser 這個領域裡面,很常見的 reference 是 YUI Graded Browser Support

這個概念講的是由於實務上的限制(時間、金錢),(JavaScript) framework 沒辦法 support 快速變化的各家 browser 的各個版本(的各個 mode),因此要有一套 support 的策略,細節包括各家、各版 browser 的市佔率,以及要 support 所必須付出的成本(這通常跟 browser 遵守 standard 的程度成正比)等等。

除了要制定一套策略,程式的寫法也要注意,以下是從影片中節錄的圖(有點糊@@)
ResigSpeech_GracefulDegradation(EventBinding)

這裡的程式寫法的順序大有學問,首先在 if statement 裡面試圖用標準的 W3C 語法來附加 EventListener,但是並非所有 browser 都有實作 W3C Spec,因此針對 IE 這個尚未實作 W3C Spec 的 browser 的 API Call 就寫在 else if 裡面。

這樣有什麼好處呢?當未來 IE 實作了 W3C Spec 之後,這個 attachEvent function 的程式一行都不用改,IE 自然可以執行到 if statement 中的標準 W3C 語法!而遇到還沒實作 W3C Spec 的 browser 也還是可以正常的執行這個 function(只是經過額外的判斷,效能稍微差了一點點)。

結論就是:愈符合標準/愈新的 API Call 應該寫在越前面,vendor-specific 的 (non-standard_ API Call 應該要往後挪,如此才可減少未來升級的 effort。

Feature Simulation


接下來一個重點是如何判斷目前執行這段 js 的 browser 是否有提供特定功能?
 
最早的時候都是透過 browser sniffing/user agent sniffing 的技術,但是這樣的寫法太沒有彈性,每次 browser 推出新版的時候,程式可能都需要修改。甚至當網站被攻擊的時候,可能 header 中的資訊會被竄改(或者 power user 自己修改),導致 js 判斷錯誤,進而產生了奇怪的畫面等等。

比較好的程式寫法如下圖所示(還是有點糊@@)
ResigSpeech_FeatureSimulation(Verify API)


前半段的程式 create 了一個 div,然後在這個 div 上加上 comment,最後 return getElementByTagName(“*”) 的長度是否為零的 boolean 值。根據這個值就可以知道目前的 browser 對於 getElementByTagName 的 implementation 是否有 bug(一切以 W3C Spec 為準),而接下來的程式就可以根據這個 boolean 值做適當的處理。


這裡的觀念類似前面講的 Graceful Degradation,重點在於不要根據 browser/user agent 的版本來假設目前 browser 對某個 API (e.g., getElementByTagName) 的 implementation 為何,實際上用程式測出來的結果才是最準的!
(這也許可以算是 unit test 的進階/變形應用?)


Reduce the number of assumptions


這其實是比較一般性的通則,在程式裡面通常都會有很多假設(assumptions),
很多時候寫程式的人不會特別去注意這些假設,但是就如同去年 MS TechEd 的心得
當假設出了問題,或許是假設不符合實際情況,或者是被駭客攻破(e.g., 設法製造一個出乎你意料之外的 input),那麼系統就會出很大的問題。因此盡量設法減少系統中的假設是一個很好的 practice,系統的假設少了,出錯的機會就少(因為可能要多寫程式去處理一些特殊狀況)

但是適量的假設是有必要的,例如你很難(大概也沒有必要)對系統中每一個變數都額外再寫程式去驗證這個變數的 type 是否正確,這基本上是 type system 的工作,因此「type system 要負責抓到如 InvalidCastException 這樣的例外狀況,並停止程式的執行,以免程式真的 run 下去之後導致更嚴重的錯誤(buffer overflow?)」就是一個典型的假設,此時通常都需要信任這個 programming language 所提供的 infrastructure 是夠嚴謹的,而不是自己寫一大堆程式到處去做 type checking。

今天不知道為什麼突然想寫寫看這樣的心得,大概是因為最近類似影片看很多,
以後有空應該會多寫一點類似的文章 :p

沒有留言:

Google Spreadsheet 裡用規則運算式

最近因為工作關係,遇到要用 Google Form 及 Google Sheet 所以研究了 Google Sheet 裡的一些 function 怎麼用 首先,分享一下如何在 Google Sheet 裡用規則運算 :D