国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

用標(biāo)記區(qū)別對(duì)象類型會(huì)導(dǎo)致誤貼標(biāo)簽

2019-11-18 15:22:08
字體:
供稿:網(wǎng)友

當(dāng)使用字段中非凡的標(biāo)記來區(qū)別對(duì)象類型時(shí),會(huì)產(chǎn)生標(biāo)記對(duì)相關(guān)數(shù)據(jù)誤貼標(biāo)簽的錯(cuò)誤 ? 被稱為 Impostor Type 錯(cuò)誤模式。在診斷 java 代碼的這一部分中,Eric Allen 對(duì)這個(gè)錯(cuò)誤的癥狀和起因進(jìn)行了分析,具體說明了預(yù)防錯(cuò)誤產(chǎn)生的方法,并討論了一種吸引人的混合實(shí)現(xiàn)方法,這種方法不使用 impostor type,但最后,還是有很多相同的缺點(diǎn)產(chǎn)生。請(qǐng)?jiān)谟懻撜搲c作者和其他讀者分享您對(duì)本文的看法。
程序中除了最無關(guān)緊要的部分外都要對(duì)某些數(shù)據(jù)類型進(jìn)行操作。靜態(tài)類型系統(tǒng)提供了一種方法,它能夠確保程序不會(huì)對(duì)給定類型的數(shù)據(jù)進(jìn)行不當(dāng)?shù)牟僮鳌ava 語(yǔ)言的優(yōu)點(diǎn)之一是嚴(yán)格的區(qū)分類型,所以在程序運(yùn)行前已消除了類型錯(cuò)誤。作為開發(fā)人員,我們可以使用這個(gè)類型系統(tǒng)提供更健壯且沒有錯(cuò)誤的代碼。然而,我們卻經(jīng)常沒有讓類型系統(tǒng)發(fā)揮出最大的潛力。

Impostor Type 錯(cuò)誤模式
很多程序可以更多地使用靜態(tài)類型系統(tǒng),但它們沒有這樣做,而是依靠包含區(qū)別數(shù)據(jù)類型標(biāo)記的非凡字段。

代碼快速跟蹤

清單 1. 用 impostor type 實(shí)現(xiàn)幾何外形
一個(gè)基本示例,演示了引入這類錯(cuò)誤是如何的輕而易舉。
清單 2. 構(gòu)造新的 form
引入了錯(cuò)誤。
清單 3. 用實(shí)際類型實(shí)現(xiàn) form
這種新奇的方法可以在運(yùn)行時(shí)報(bào)錯(cuò)。
清單 4. 一種混合的實(shí)現(xiàn)方式
不使用 impostor type,但易受性一樣。
依靠這些非凡字段區(qū)別數(shù)據(jù)類型,這樣的程序放棄了類型系統(tǒng)專門提供給它們的保護(hù)措施。當(dāng)這些標(biāo)記中的一個(gè)對(duì)它的數(shù)據(jù)誤貼了標(biāo)簽,就會(huì)產(chǎn)生我稱之為 Impostor Type 的錯(cuò)誤。

癥狀
impostor type 錯(cuò)誤的一種常見癥狀是很多概念上不同類型的數(shù)據(jù)都被同樣(并且錯(cuò)誤)的方式處理。另一常見癥狀是數(shù)據(jù)與任何指定的類型都不匹配。

首要規(guī)則是,只要當(dāng)概念上的數(shù)據(jù)類型和它被程序處理的方法不匹配,就可以懷疑是否發(fā)生了這個(gè)模式的錯(cuò)誤。

為說明引入這種模式的錯(cuò)誤是多么的輕而易舉,讓我們來考慮一個(gè)簡(jiǎn)單的示例。假設(shè)我們需要處理各種各樣的歐幾里得幾何學(xué)外形,如圓形、正方形等等。這些幾何外形沒有坐標(biāo),但含有一個(gè) scale 變量,所以可以計(jì)算它們的面積。

清單 1. 用 imposter type 實(shí)現(xiàn)各種幾何外形

public class Form {

String shape;

double scale;

public Form(String _shape, double _scale) {

this.shape = _shape;

this.scale = _scale;

}

public double getArea() {

if (shape.equals("square")) {

return scale * scale;

}

else if (shape.equals("circle")) {

return Math.PI * scale * scale;

}

else { // shape.equals("triangle"), an equilateral triangle

return scale * (scale * Math.sqrt(3) / 4);

}

}

}

盡管您會(huì)發(fā)現(xiàn)人們經(jīng)常這么做,但用這種方法實(shí)現(xiàn)幾何外形還是存在嚴(yán)重缺點(diǎn)。

最顯著的缺點(diǎn)之一是這個(gè)方法不能真正的擴(kuò)展。假如要為我們的 form 引入一個(gè)新的幾何外形(比如,“五邊形”),我們必須進(jìn)入并修改 getArea() 方法的源代碼。不過可擴(kuò)展性是個(gè)獨(dú)立的考慮因素;在本文中,我們把重點(diǎn)放在實(shí)現(xiàn)幾何外形所造成的錯(cuò)誤的易受性上。我會(huì)在以后的文章中回到關(guān)于可擴(kuò)展性的問題上來。

假如我們?cè)诔绦蚱渌糠謽?gòu)造了一個(gè)新的 Form 對(duì)象,如下所示,請(qǐng)考慮將會(huì)發(fā)生什么情況:

清單 2. 構(gòu)造一個(gè)新的 form

Form f = new Form("sqaure", 2);

當(dāng)然,“square”被拼錯(cuò)了,但是編譯器認(rèn)為,這是完全合法的代碼。

現(xiàn)在考慮一下,當(dāng)我們?cè)噲D對(duì)新的 Form 對(duì)象調(diào)用,比如說 getArea() 方法時(shí)發(fā)生什么情況。因?yàn)?Form 對(duì)象中的幾何外形與 if-then-else 代碼塊中的任一測(cè)試的幾何外形都不匹配,它的面積將在 else 分句中被計(jì)算,似乎它是個(gè)三角形似的!

這里將不會(huì)報(bào)錯(cuò)。事實(shí)上,在很多情況下,返回值看起來都好象是完全合理的數(shù)字。即使我們插入些冗余代碼,檢查 else 分句中的隱含條件是否包含(比如說,斷言),也要到代碼執(zhí)行時(shí)才能發(fā)現(xiàn)錯(cuò)誤。

很多其它相似的錯(cuò)誤也可能在上述代碼中產(chǎn)生。if-then-else 代碼塊可能會(huì)偶然遺漏一句分句,導(dǎo)致類型與那句分句相對(duì)應(yīng)的所有 Form 都被錯(cuò)誤地處理了。此外,因?yàn)?impostor type 在字段中只是一個(gè) String,所以它可能會(huì)被意外或惡意地修改。

無論用哪一種方法,這樣的修改會(huì)帶來各種各樣的損害。

治療和預(yù)防措施
正如您可能設(shè)想過的那樣,我建議用類型系統(tǒng)在靜態(tài)檢查期間將它們清除,從而避免這種類型的錯(cuò)誤。請(qǐng)考慮這種新奇的實(shí)現(xiàn)方法:

清單 3. 用實(shí)際類型實(shí)現(xiàn) form

public abstract class Form {

double scale;

public Form(double _scale) {

this.scale = _scale;

}

public abstract double getArea();

}

class Square extends Form {

public Square(double _scale) {

super(_scale);

}

public double getArea() {

return scale * scale;

}

}

class Circle extends Form {

public Circle(double _scale) {

super(_scale);

}

public double getArea() {

return Math.PI * scale * scale;

}

}

class Triangle extends Form {

public Triangle(double _scale) {

super(_scale);

}

public double getArea() {

return scale * (scale * Math.sqrt(3) / 4);

}

}

現(xiàn)在考慮一下,在創(chuàng)建一個(gè)新 Form 時(shí),假如誤輸入了“Sqaure”,會(huì)發(fā)生什么情況。編譯器將會(huì)報(bào)錯(cuò),告訴我們類 Sqaure 找不到。代碼將連運(yùn)行的機(jī)會(huì)也沒有。

同樣地,編譯器將不會(huì)答應(yīng)我們忘記為我們的任意子類定義 getArea() 方法。當(dāng)然,任何對(duì)象要改變 Form 的類型是不可能的。

最后說明
在離開這個(gè)主題之前,我還想討論另一種可能的實(shí)現(xiàn),一種我曾經(jīng)討論過的兩種實(shí)現(xiàn)方法的混合。

在這種情況下,不使用 impostor type,但代碼包含很多相同的易受性,似乎它們以前就有。實(shí)際上,這種實(shí)現(xiàn)方法比對(duì)每個(gè)類型單獨(dú)實(shí)現(xiàn) getArea() 方法更差。

清單 4. 一種混合的實(shí)現(xiàn)方式

public abstract class Form {

double scale;

public Form(double _scale) {

this.scale = _scale;

}

public double getArea() {

if (this instanceof Square) {

return scale * scale;

}

else if (this instanceof Circle) {

return Math.PI * scale * scale;

}

else { // this instanceof Triangle

return scale * (scale * Math.sqrt(3) / 4);

}

}

}

class Square extends Form {

public Square(double _scale) {

super(_scale);

}

}

class Circle extends Form {

public Circle(double _scale) {

super(_scale);

}

}

class Triangle extends Form {

public Triangle(double _scale) {

super(_scale);

}

}

盡管編譯器仍然會(huì)捕捉類型的拼寫錯(cuò)誤,且對(duì)象類型是無法改變的,我們又一次使用了 if-then-else 代碼塊調(diào)度適當(dāng)?shù)念愋汀_@樣,我們又要面臨 if-then-else 代碼塊中 instanceof 檢查與我們所操作的那組類型不匹配的情況。

還必須提出,像第一種實(shí)現(xiàn)方法那樣,這個(gè)實(shí)現(xiàn)方法的擴(kuò)展性不如第二種。

總結(jié)
那么,簡(jiǎn)而言之,這就是我們最近的錯(cuò)誤模式:

模式:Impostor Type

癥狀:一種程序,它用同樣的方式處理概念上不同類型的數(shù)據(jù),或者無法識(shí)別某種類型的數(shù)據(jù)。

起因:程序針對(duì)各種類型的數(shù)據(jù)使用帶標(biāo)記的字段,而不是獨(dú)立的類。

治療和預(yù)防措施:盡可能將概念上不同的數(shù)據(jù)類型分成幾個(gè)獨(dú)立的類。
重點(diǎn)在于,這種語(yǔ)言為您提供了避免這類錯(cuò)誤的最好資源 ? 只是要記得使用它們。

參考資料

請(qǐng)參與本文的討論論壇。

JUnit 主頁(yè)提供了很多有趣文章的鏈接,這些文章討論了程序測(cè)試的方法,還有最新的 JUnit 版本。

假如您喜歡 JUnit,請(qǐng)查看整套 xUnit 測(cè)試工具,有多種不同語(yǔ)言版本。

我必須提一下工具中的 xUnit 套件是設(shè)計(jì)用來和極端編程一起使用的,這是一種新型的功能強(qiáng)大并快速開發(fā)干凈、健壯軟件的方法。

“框架體系結(jié)構(gòu)的 UML 概要文件”(PDF 幻燈片放映)突出顯示具體的 JUnit 個(gè)案研究。

盡管與這個(gè)討論沒有直接的聯(lián)系,我還是推薦您參閱 Martin Fowler 的文章,其中討論了 UML 的角色和極端編程中的設(shè)計(jì)。

采用 “Java 調(diào)試”教程(developerWorks,2001 年 2 月),從而獲得一般調(diào)試技術(shù)的幫助。

不熟悉 Java 開發(fā)或希望重溫 Java 編程技術(shù)嗎?請(qǐng)采用這篇全面的教程,“ Java 語(yǔ)言的基礎(chǔ)知識(shí)”。

請(qǐng)閱讀 Eric 的所有診斷 Java 代碼的文章,許多篇著重討論錯(cuò)誤模式。

請(qǐng)?jiān)?developerWorks Java 技術(shù)專區(qū)中查閱更多 Java 參考資料。

關(guān)于作者
Eric Allen 畢業(yè)于 Cornell 大學(xué),曾獲得計(jì)算機(jī)系和數(shù)學(xué)系的學(xué)士學(xué)位。他還是 Rice 大學(xué) Java 編程語(yǔ)言小組的博士研究生。它的研究涉及到開發(fā)用于 Java 語(yǔ)言的語(yǔ)義模型和靜態(tài)分析工具,兩者都是源代碼和字節(jié)碼級(jí)別的。目前,他正在為 NextGen 編程語(yǔ)言實(shí)現(xiàn)一種從源代碼到字節(jié)碼的編譯器,這也是 Java 語(yǔ)言的泛型運(yùn)行時(shí)類型的一種擴(kuò)展。請(qǐng)通過 eallen@cs.rice.edu 與他聯(lián)系。

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 灯塔市| 大理市| 津市市| 辽源市| 盱眙县| 政和县| 崇阳县| 金门县| 涿州市| 隆林| 金乡县| 康定县| 延安市| 岫岩| 乌鲁木齐县| 赞皇县| 宁河县| 伊宁市| 达州市| 张家界市| 大悟县| 依兰县| 湖北省| 宜兰县| 自贡市| 高阳县| 东港市| 宜黄县| 天柱县| 新和县| 岑巩县| 祁连县| 霍林郭勒市| 苏州市| 会东县| 巴东县| 右玉县| 安乡县| 山阳县| 寿宁县| 竹山县|