摘要:圖對(duì)可復(fù)用代碼挑戰(zhàn)最大的五項(xiàng)問(wèn)題五大開(kāi)發(fā)問(wèn)題如下。瀏覽器的缺陷修復(fù)。瀏覽器缺失的功能。復(fù)雜的地方是,當(dāng)前瀏覽器會(huì)在未來(lái)的瀏覽器版本中被修復(fù)。假設(shè)瀏覽器引起常見(jiàn)的網(wǎng)站問(wèn)題為解決瀏覽器使用特殊技巧,將來(lái)瀏覽器發(fā)布新版本修復(fù)了,就會(huì)出現(xiàn)問(wèn)題。
任意一段重要的代碼都需要關(guān)注無(wú)數(shù)的開(kāi)發(fā)問(wèn)題。但是,其中對(duì)可復(fù)用JavaScript代碼挑戰(zhàn)最大的五項(xiàng)問(wèn)題如圖14.2所示。
圖14.2 對(duì)可復(fù)用JavaScript代碼挑戰(zhàn)最大的五項(xiàng)問(wèn)題
五大開(kāi)發(fā)問(wèn)題如下。
瀏覽器缺陷。
瀏覽器的缺陷修復(fù)。
外部代碼。
瀏覽器回歸。
瀏覽器缺失的功能。
我們需要權(quán)衡解決這些問(wèn)題所花費(fèi)的時(shí)間與得到的收益。這些是不得不回答的問(wèn)題。你分析潛在受眾、開(kāi)發(fā)資源、開(kāi)發(fā)排期等,這些都是決定性因素。
當(dāng)試圖開(kāi)發(fā)可復(fù)用的JavaScript代碼,我們需要考慮所有的因素,還需要考慮目前最流行的瀏覽器,因?yàn)檫@些瀏覽器是我們的目標(biāo)受眾最可能使用的瀏覽器。其他不那么流行的瀏覽器,我們至少保證代碼可以優(yōu)雅降級(jí)。例如,如果一個(gè)瀏覽器不支持某API,我們應(yīng)該小心我們的代碼不會(huì)拋出任何異常,這樣剩下的代碼仍然可以順利執(zhí)行。
在接下來(lái)的小節(jié)中,我們將講解這些問(wèn)題,以便更好地理解我們面對(duì)的挑戰(zhàn)以及如何應(yīng)對(duì)。
1 瀏覽器的bug和差異當(dāng)我們開(kāi)發(fā)可復(fù)用性JavaScript代碼時(shí),需要考慮解決的問(wèn)題之一是處理我們確定需要兼容的多種瀏覽器bug以及API的差異。盡管瀏覽器越來(lái)越標(biāo)準(zhǔn)化,但是代碼還是必須得完全符合瀏覽器提供的特性。
實(shí)現(xiàn)這一目標(biāo)的方法很直接:我們需要完整的測(cè)試工具,足以覆蓋代碼常用的和不常用的用例。充分測(cè)試之后,在知道開(kāi)發(fā)的代碼將在支持的瀏覽器中工作后,我們會(huì)感到安全。假設(shè)瀏覽器沒(méi)有后續(xù)變化,不會(huì)打破向后兼容性,我有一個(gè)模糊的預(yù)感,代碼甚至?xí)谖磥?lái)版本的瀏覽器中工作。在14.3節(jié)中,我們會(huì)觀察特定的策略來(lái)處理瀏覽器bug和差異。
復(fù)雜的地方是,當(dāng)前瀏覽器bug會(huì)在未來(lái)的瀏覽器版本中被修復(fù)。
2 瀏覽器的bug修復(fù)瀏覽器永遠(yuǎn)存在特定的錯(cuò)誤是很愚蠢的——大部分瀏覽器bug最終都會(huì)修復(fù),把希望寄托在瀏覽器bug上是很危險(xiǎn)的開(kāi)發(fā)策略。最佳方式是使用14.3節(jié)中的技術(shù),使用不會(huì)過(guò)時(shí)的變通方案。
在編寫一個(gè)可重用的JavaScript代碼時(shí),我們希望它可以持續(xù)運(yùn)行很長(zhǎng)時(shí)間。編寫任何方面的網(wǎng)站(CSS、HTML等),瀏覽器發(fā)布新版本后,我們不希望再回去修復(fù)代碼。
假設(shè)瀏覽器bug引起常見(jiàn)的網(wǎng)站問(wèn)題:為解決瀏覽器bug使用特殊技巧,將來(lái)瀏覽器發(fā)布新版本修復(fù)了bug,就會(huì)出現(xiàn)問(wèn)題。
處理瀏覽器漏洞的問(wèn)題是雙重的:
當(dāng)bug最終被修復(fù),我們的代碼容易損壞。
我們無(wú)法為了避免網(wǎng)站損壞而說(shuō)服瀏覽器廠商不修復(fù)bug。
最近恰好發(fā)生了第2種情況的有趣的事例,關(guān)于scrollTop的bug(https://dev.opera.com/article...)。
當(dāng)處理HTML DOM時(shí),可以使用scrollTop和scrollLeft屬性,修改當(dāng)前元素的滾動(dòng)位置。但是當(dāng)我們對(duì)根元素使用這些屬性時(shí),根據(jù)規(guī)范,將會(huì)返回滾動(dòng)的位置,IE11與Firefox瀏覽器嚴(yán)格遵循了這則規(guī)范。而Safari、Chrome和Opera并沒(méi)有遵守。如果試圖修改根元素的滾動(dòng)位置時(shí),不會(huì)發(fā)生任何事情。為了實(shí)現(xiàn)相同的效果,我們只能在body元素上使用scrollTop和scrollLeft屬性。
當(dāng)面對(duì)瀏覽器的不一致性時(shí),Web開(kāi)發(fā)者們常常檢測(cè)當(dāng)前瀏覽器的名字(通過(guò)用戶代理字符串,后續(xù)會(huì)詳細(xì)介紹),然后在IE11和Firefox上對(duì)HTML元素使用scrollTop和scrollLeft屬性,而在Safari、Chrome和Opera上則對(duì)body元素使用scrollTop和scrollLeft屬性。規(guī)避這類問(wèn)題將會(huì)造成災(zāi)難性后果。因?yàn)樵S多網(wǎng)頁(yè)明確編碼指定在Safari、Chrome或Opera上使用body元素,這些瀏覽器無(wú)法真正修復(fù)這個(gè)bug,因?yàn)橐坏┬迯?fù),許多網(wǎng)頁(yè)都無(wú)法運(yùn)行。
這引出了另一個(gè)關(guān)于bug的觀念:在確定某一功能是否是潛在的錯(cuò)誤時(shí),使用規(guī)范進(jìn)行驗(yàn)證!
瀏覽器的bug不同于未指明的API。參考瀏覽器規(guī)范非常重要,因?yàn)橐?guī)范提供了確切的標(biāo)準(zhǔn),瀏覽器使用這些標(biāo)準(zhǔn)進(jìn)行開(kāi)發(fā)和完善代碼。相比之下,一個(gè)未指明的API的實(shí)現(xiàn)可能會(huì)在任何時(shí)候發(fā)生改變(特別是試圖成為標(biāo)準(zhǔn)化的實(shí)現(xiàn))。在未指明的API不一致的情況下,你應(yīng)該對(duì)預(yù)期輸出進(jìn)行測(cè)試。警惕這些API未來(lái)可能發(fā)生的變化。
另外,bug修復(fù)和API的變化是有區(qū)別的。bug修復(fù)是很容易預(yù)見(jiàn)的——瀏覽器最終將修復(fù)bug,即使要花很長(zhǎng)的時(shí)間,API變化更難發(fā)現(xiàn)。標(biāo)準(zhǔn)API不太可能改變,盡管不是完全聞所未聞,變化更有可能出現(xiàn)未指明的API中。
幸運(yùn)的是,大多數(shù)Web應(yīng)用程序出問(wèn)題的情況很少發(fā)生。萬(wàn)一出現(xiàn)問(wèn)題,有效地提前預(yù)知是無(wú)效的辦法(除非我們逐一測(cè)試相關(guān)的API——但是這樣一個(gè)過(guò)程的開(kāi)銷是可怕的)。這種API的變化應(yīng)該做回歸處理。
下一個(gè)需要關(guān)心的問(wèn)題是,沒(méi)有人是一座孤島,我們的代碼也不是,讓我們研究代碼的影響范圍。
3 外部代碼和標(biāo)記任何可重用代碼必須與圍繞它的代碼共存。我們希望代碼運(yùn)行在自己編寫的網(wǎng)站或是他人開(kāi)發(fā)的網(wǎng)站上,我們都需要確保代碼可以與其他代碼共存。
這是一把雙刃劍:我們的代碼不僅必須能夠經(jīng)受住可能寫得很遭的外部代碼,還必須得克服環(huán)境對(duì)代碼的不利影響。
我們需要警惕的程度很大程度上取決于所使用的代碼對(duì)環(huán)境的關(guān)注。例如,如果我們僅為單個(gè)或有限個(gè)網(wǎng)站編寫可重用的代碼,在某種程度上可以控制,可以少一些擔(dān)心,因?yàn)槲覀冎来a的運(yùn)行對(duì)外部代碼的影響程序,而且一旦有問(wèn)題,我們可以自行修復(fù)。
{注意 }這個(gè)問(wèn)題的重要程度足以用一本書來(lái)闡述。如果你想更深入地探究,我們強(qiáng)烈推薦Ben Vinegar 和 Anton Kovalyov 編寫的《第三方JavaScript》一書(Manning, 2013, https:// www.manning.com/books/third-party-javascript)。
如果開(kāi)發(fā)代碼將廣泛用于未知環(huán)境(不可控的)中,則我們需要雙重確認(rèn)代碼的健壯性。接下來(lái)討論一些實(shí)現(xiàn)代碼健壯性的策略。
代碼封裝為了避免我們的代碼影響頁(yè)面上的其他代碼,最佳實(shí)踐是使用封裝。通常來(lái)說(shuō),封裝指代碼(如同)存放在容器里。從廣義上來(lái)說(shuō),是一種限制訪問(wèn)其他對(duì)象組件的語(yǔ)言機(jī)制。Aunt Mathilda也許會(huì)總結(jié)為“各人自掃門前雪,莫管他人瓦上霜”。
在頁(yè)面上引入我們的代碼時(shí),盡可能少地影響全局代碼,將會(huì)使Aunt Mathilda非常開(kāi)心。事實(shí)上,盡可能少地使用全局變量,甚至最好僅限一個(gè),是很容易的。
第12章中的jQuery,它是最流行的客戶端JavaScript庫(kù),也是最好的范例。jQuery引入一個(gè)名為jQuery的全局變量(一個(gè)函數(shù)),別名為$,它甚至允許其他網(wǎng)頁(yè)為$設(shè)置別名避免沖突。
jQuery中幾乎所有的操作都通過(guò)jQuery函數(shù)完成。其他函數(shù)(工具函數(shù))被定義為jQuery的屬性(第3章介紹如何將函數(shù)定義為另一個(gè)函數(shù)的屬性),使用jQuery作為命名空間。我們可以使用相同的策略。假設(shè)我們需要定義一組函數(shù),我們將其定義在命名空間ninja下。
與jQuery類似,我們可以定義名為ninja()的全局函數(shù)以操作傳入的變量。例如:
var ninja = function(){ /* implementation code goes here */ }
使用我們?cè)O(shè)定好的命名空間定義工具函數(shù):
ninja.hitsuke = function(){ /* code to distract guards with fire here */ }
如果我們不需要ninja作為函數(shù),僅作為一個(gè)命名空間即可,我們可以使用如下定義方式:
var ninja = {};
創(chuàng)建空對(duì)象,隨后在該對(duì)象上定義屬性或方法即可。為了保證代碼的封裝,需要避免其他操作,如修改已經(jīng)存在的變量、函數(shù)原型甚至DOM元素。修改我們自己代碼之外的任何內(nèi)容,都可能引起潛在的沖突和混淆。另外,盡管我們小心翼翼地嚴(yán)格遵守最佳實(shí)踐封裝代碼,但我們?nèi)匀粺o(wú)法保證代碼的行為。
模范代碼有一個(gè)老笑話Grace Hopper在Cretaceous時(shí)期為接替人員清除蛀蟲時(shí)說(shuō):“你最不惡心的代碼就是你自己寫的代碼。”看起來(lái)很諷刺,但是當(dāng)我們的代碼與不可控的代碼同時(shí)運(yùn)行時(shí),為了安全起見(jiàn),我們需要假設(shè)最糟的情況。
盡管一些代碼編寫工整,但也有可能潛在地做一些出乎意料的事,例如修改函數(shù)屬性、對(duì)象屬性和DOM元素的方法。這些都可能設(shè)有陷阱。
在這種情況下,我們的代碼只能做一些無(wú)傷大雅的事,例如使用JavaScript數(shù)組,一般情況下JavaScript數(shù)組只能是JavaScript數(shù)組。但是,如果一些頁(yè)面上修改了數(shù)組的行為,我們的代碼將無(wú)法運(yùn)行,當(dāng)然不是我們自身的原因。
遺憾的是,處理這種問(wèn)題沒(méi)有固定的原則標(biāo)準(zhǔn),但是我們可以采取一些措施。我們將在后續(xù)小節(jié)中介紹保護(hù)性方法。
應(yīng)對(duì)ID濫用大部分瀏覽器具有一些反特性(我們不能稱之為bug,因?yàn)檫@些特性是有意而為之),這些特性會(huì)使得代碼不可預(yù)期地落入陷阱從而運(yùn)行失敗。這些特性使得原始元素與添加在元素上的id或name屬性產(chǎn)生關(guān)聯(lián)。但是當(dāng)id或name屬性與元素上已經(jīng)存在的部分屬性產(chǎn)生沖突時(shí),就會(huì)發(fā)生一些意料之外的情況。
查看以下HTML代碼片段,觀察id屬性的濫用:
現(xiàn)在,在瀏覽器中可以這樣調(diào)用:
var what = document.getElementById("form").action;
我們期望返回合理的form的action屬性。大部分情況下是可以返回的。但是當(dāng)檢查值的時(shí)候你會(huì)發(fā)現(xiàn),返回的卻是input#action元素。為什么?讓我們?cè)囋嚻渌兀?/p>
document.getElementById("form").submit();
這條語(yǔ)句本應(yīng)引起form提交,但是卻返回script錯(cuò)誤:
Uncaught TypeError: Property "submit" of object #is not a function
發(fā)生了什么呢?
瀏覽器將
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/109397.html
目錄 一、禪道 一、測(cè)試工具背景 二、測(cè)試管理工具 三、測(cè)試工具介紹 四、禪道介紹 五、禪道操作 7. 創(chuàng)建發(fā)布 8. 測(cè)試團(tuán)隊(duì) 二、缺陷報(bào)告 三、測(cè)試報(bào)告 一、概要 二、測(cè)試過(guò)程 三、缺陷分析 四、測(cè)試總結(jié) 四、接口測(cè)試以及用例編寫 五、Fiddler 好文推薦 一、禪道 一、測(cè)試工具背景 當(dāng)測(cè)試環(huán)境搭建完成后,測(cè)試人員將在自己搭建的環(huán)境上執(zhí)行測(cè)試用例,開(kāi)展測(cè)試工作。測(cè)試人員在執(zhí)行測(cè)試用例的過(guò)...
摘要:軟件測(cè)試是為了降低存在缺陷的可能性,即便是沒(méi)有找到缺陷,也不能證明軟件是完美的。軟件測(cè)試中存在原則的缺陷發(fā)現(xiàn)在的模塊中。軟件測(cè)試不僅是找出缺陷,同時(shí)也需要確認(rèn)軟件是否滿足需求。 4.1軟件缺陷定義 軟件缺陷就是通常說(shuō)的bug,它是指在軟件中存在的影響 *軟件未達(dá)到產(chǎn)品說(shuō)明書標(biāo)明的功能, *軟...
摘要:如果數(shù)據(jù)從舊系統(tǒng)遷移到新系統(tǒng)是當(dāng)前版本發(fā)布的主要目的,那么更要關(guān)注報(bào)表數(shù)據(jù)數(shù)據(jù)遷移缺陷如果一個(gè)舊系統(tǒng)要被新系統(tǒng)取代,舊系統(tǒng)里的數(shù)據(jù)要移到新系統(tǒng)。 對(duì)任何軟件產(chǎn)品來(lái)說(shuō),軟件上線永遠(yuǎn)是一件大事。完全確保所有功能生效以及發(fā)布高質(zhì)量軟件給用戶非常重要。 不好的、不成熟的、不穩(wěn)定的、難以使用的產(chǎn)品會(huì)引...
閱讀 636·2023-04-25 21:29
閱讀 1195·2023-04-25 21:27
閱讀 1112·2021-11-25 09:43
閱讀 1175·2021-09-29 09:43
閱讀 3693·2021-09-03 10:30
閱讀 2927·2019-08-29 15:26
閱讀 2885·2019-08-29 12:52
閱讀 1815·2019-08-29 11:10