【自推】ke-url.js——可在瀏覽器和nodejs環境下使用的url處理工具類 原 薦

本來是想封裝一套前端的ORM,可是做到URL處理的時候,找了半天都沒有找到用得順手的npm。

最後自己動手封裝了一個:http://git.oschina.net/janpoem/ke-url.js

爲什麼非要重複造個輪子呢?

node.js的url.js和quertstring.js

雖然node.js自帶有一個url.js和querystring.js,就其源代碼的安全性而言,真的無可挑剔,非常棒。但是,部分細節的處理上,卻不盡人意。

比如,在構造querystring的時候,如果給出一個多結構的數據,他是不會生成key[field]這樣的格式的。並且在處理編碼的時候,[]也會作爲encode的內容。雖然這樣在後端decode的時候,也能正確的解析,但在調試一個URL的時候,還是很容易就造成困擾。

其次,在解析querystring的時候,key[field]這樣的結構,他會直接解析爲{'key[field]': value},這讓我說什麼好呢?

再次,url.js的parse(解析url)的方法,在解析結果上,冗餘的結果太多:

interface Url {
        href?: string;
        protocol?: string;
        auth?: string;
        hostname?: string;
        port?: string;
        host?: string;
        pathname?: string;
        search?: string;
        query?: string | any;
        slashes?: boolean;
        hash?: string;
        path?: string;
    }

hostname與port和host是冗餘的,search和query是冗餘的,pathname和path、query、hash是冗餘的。

這個數據結構可以是url.parse解析的結果,也可以傳入url.format方法去構造一條url,很多時候因爲這彼此冗餘的結果,需要做很多的判斷、取捨,也導致生成的url和預期的結果有偏差。

較爲合理的處理,是結果不應該包含冗餘的數據,而應該講url最基礎的字段(所謂基礎,其實就是開發中經常讀寫操作的部分)拆散,而需要部分字段合併的屬性,變爲一個方法來進行讀寫處理,而不是也作爲一個屬性來訪問(這樣真的會讓人很困擾)。

除此之外,url的部分字段,包含了一些冗餘的字符(可能長久以來,已經習慣了PHP的parse_url了),比如search包含了?,protocol包含了:,hash包含了#,這其實也會對這些字段的訪問、寫入,帶來某種程度的困擾(到底該不該包含那個字符呢?)。

不過扒開url.js和querystring.js,不得不說,在字符串的處理上,他完全稱得上是js裏處理字符串上的一個標杆了。url的解析,進最大的可能性,排除存在危險的字符,保留url的完整性和解析時的兼容性。所以ke-url.js,仍然直接使用url.js來進行parse和format,只是不直接將這個結果暴露給使用者,而會對這個結果進行過濾,去掉上述說的諸多問題。

php.js

不得不說,真的很佩服老外在做事情上的偏執、徹底,真的要學習。尤其是php.js這個類庫。這個Locutus,在js裏實現了一整套php自帶的函數(傳送門),而且是哪怕一絲絲細節上的區別(js和php習慣上),他都實現到了,我真的佩服得不得了。

既然期望解析和構建url的處理接近php的結果,其實可以直接選擇php.js這個類庫。

在編寫ke-url.js的前三天我也是這麼處理的。不過php.js使用上有幾個問題:

第一,這個類庫並不是以底層類庫爲目的設計的,當然這對於普通開發者沒有什麼太大的區別。很多方法(尤其是url處理部分),還是有些過於簡單化(不如node.js對安全性、兼容性方面考慮的周全)。而且大量的使用正則表達式,而且是非常長非常長的正則表達式,性能問題就不說了,關鍵在於調試的難度。當一條url解析發生問題時,你幾乎沒辦法簡單的對解析的部分進行拆解調試(這也是瀑布式代碼流最不好的地方)結果你只知道錯了,而url解析只返回了一個空的數據對象,這時候會很尷尬。

第二,實際上,在有了node.js的url.js和querystring.js以後,再回看php.js(url部分),就顯得十分冗餘了,node.js自帶的類庫,完全可以覆蓋後者,只是在一些細節上的處理不盡人意而已。

所以經過3天折騰,還是決定果斷放棄php.js,選擇回基於node.js的url.js,增加封裝一箇中間層算了。

mootools

這個類庫已經寂靜無聲很多年了,不過這麼多年,我一直習慣使用他More庫裏面的URI實現。乃至即使換了jQuery,仍需要將URI部分轉移出來單獨使用。當然這不代表他的URI的封裝有多高明,有多安全,只是兩個原因:

1、用了很多年,熟悉他的方法(實際上我每次用還是忍不住要吐槽他的設計,傳送門,也是腦殘的兇狠,當然這麼做是爲了確保URI每個部分的數據的穩定性,但我想說這種做法沒達到這個目的,只讓接口看着更彆扭),更多的只是習慣了;

2、他在處理多層的querystring的結果是正確的,這一點很重要。

3、他解析回來的數據結構,符合我所需要的,只展現最基礎部分的(實際上他還是很冗餘的,只是因爲他的接口並不直接暴露數據,所以你不需要知道太多細節,其實嚴格說起來,還是存在不知道到底該寫入哪個屬性上)。

Don't Make Me Think

Don't Make Me Think

這句口號,最初說的是對於用戶界面設計上的一個基本要求,但現在已經變爲人機界面的一個標準,也是整個人機界面設計不斷變革的起點。

其實我覺得,這句話同樣適用於程序設計上。

一個程序的接口,應該至少有一個明確要解決的問題,但請不要給他附加上太多的可能、同時還(同時讓他解決其他問題),這會讓一個接口在使用上存在不確定性——這種不確定性,直接造成代碼的冗餘——代碼的冗餘,就會造成測試的複雜性。

否則,使用時,需要去想,我該怎麼使用他,或他會不會返回我需要的結果,或他怎麼才能返回我需要的結果呢?

一個對象(類實例屬性)的屬性,應該是這個類所需要的數據——打散到最小組成單元的數據,複合型數據應該使用方法體現,而不應該存在彼此的冗餘。A=B+C,那麼B和C應該是屬性,A應該是一個方法,這個類不應該具有一個屬性是A。所以我們並不需要讓一個屬性變成看似方法(get prop()或 set prop()),也不需要讓一個方法看似一個屬性(scala、coffee)。

否則,我需要去思考,到底我該寫入A,還是寫入B、C呢?我現在到底在調用一個方法,還是在訪問一個屬性?

一個類的設計,應該接口先行,接口決定了類的某個行爲特徵,是程序設計中的最小組成部分。如果決定不了接口,就不要類,這樣的類一定沒有其根本要解決的問題,只會寫出一大堆模棱兩可的方法。如果決定不了一個類,可以先寫成函數、靜態類、Trait,其重用性遠比寫一個類要高。

正是因爲這句話背後的精髓,隨着編程的年齡的增長,會越發的傾向選擇強類型語言,因爲輸入輸出都是明確的,動態類型就是一個鍋,他很吸引,卻不實用。

最後

可能有些跑題,其實本文只是一個日記,並不是要【自推】,只是記錄爲啥要重複造個輪子。

程序是一個很有意思的東西,就好像寫文章。詞藻華麗,不代表具有有實際意義,具有實用價值,可能用詞枯燥。

也許代碼質量很高,可是輸出數據混亂,方法解決問題不明確,一塌糊塗,也並沒有什麼實際的意義。

唯獨,文章不存在重用,而程序,卻可以封裝、封裝、再封裝。

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