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

首頁 > 學院 > 開發設計 > 正文

診斷和糾正Java程序中反復出現的錯誤類型

2019-11-18 11:01:55
字體:
來源:轉載
供稿:網友

  診斷和糾正 java 程序中反復出現的錯誤類型
Eric E. Allen
軟件工程師,Cycorp, Inc.
2001 年 2 月

歡迎光臨診斷 Java 代碼,一個隔周更新的新專欄,著重討論和您日常編程工作有關的 Java 解決方案。本文為第一篇,介紹了錯誤模式的概念,一個非常有用的概念,它將提高您檢測和修正代碼中錯誤的能力。您會了解到一種最普遍的錯誤模式,這將為您開始識別和避免更高級的錯誤模式奠定基礎。
錯誤模式和它們為什么有用
正如好的編程技能涉及很多設計模式(您可以在不同的程序上下文中組合和應用這些模式)的知識一樣,好的調試技能也涉及對 錯誤模式的一定了解。錯誤模式就是已發出的錯誤和程序中潛在的錯誤之間的重復出現的相互關系。這種概念對編程來說并不新鮮。醫生們在診斷疾病時依靠相似類型的相互關系。他們在實習期間通過和資格較老的醫生共同工作來學習這些。他們的教育就是集中在做這種診斷上的。相反,我們軟件工程師的教育是集中在過程設計和算法分析上的。這些技能固然重要,但是人們對調試過程的教育卻很少關注。相反,我們得自己去“拾起”這種技能。隨著極端編程的出現和它對單元測試的注重,這種做法已經開始改變了。但是頻繁的單元測試只是解決了問題的一部分。一旦發現錯誤,就必須診斷和糾正它們。幸運的是,很多錯誤都遵循我們可以識別的幾種錯誤模式的其中一種。一旦您可以識別出這些錯誤模式,您就可以診斷出錯誤的原因并且更快地糾正它了。

錯誤模式與反模式有關,反模式是一次又一次被證實是失敗的公共軟件設計的模式。雖然反模式是設計模式,錯誤模式卻是與編程錯誤相關的錯誤的程序行為的模式。這與設計根本沒有關系,而是與編程和調試過程有關。

通過示例學習
為了說明錯誤模式后面的思想,讓我們來考慮一種基本錯誤模式,編程新手(經常還有更高級的程序員)經常會碰到這種錯誤模式。在后面的文章中,我們會談到更高級的錯誤模式。對每一種模式,我會討論將有助于把該模式的錯誤的發生控制到最少的編程原則(并非暗示所有的錯誤都是不遵循編程原則的結果;不管我們遵循多少原則,我們都會犯錯誤)。

為了分類起見,我會使用下面的形式(從醫學上借用一些術語)來概括錯誤模式描述:

模式名稱
癥狀
起因
治療方法和預防措施
Rogue Tile 模式
也許它是編程新手中最普遍的錯誤模式,起因是復制和粘貼一段代碼到程序的其它部分。有時,復制的一小部分因為功能上需求的略微不同而作了改動。不可避免地,錯誤在一個副本中被修正了,而在另一個副本中沒有被修正,這樣在錯誤癥狀復發時就會讓您很頭疼。盡管大多數程序員很快就熟悉了這種錯誤模式,但他們中很少人采取適當的措施來將這種錯誤的出現控制到最少。您很輕易就會偷懶不去思考而簡單地復制您認為已經可以運行的代碼。但是工作效率由于修正代碼而喪失,這是因為不加選擇的復制?粘貼操作很快降低了復制代碼帶來的任何工作效率。

我稱此為 Rogue Tile 模式是因為,一段代碼的各個副本可以被看成是分布在程序中的“tile”。由于不同副本中的代碼出現了差異,副本就變成了“rogue tile”。

癥狀
這種錯誤的模式的最普遍癥狀是,在您認為已經修正了問題以后,程序還繼續表現出錯誤的行為。

起因
為了理解這種情況發生的原因,我們來看看下面的二元樹類層次結構:

public abstract class Tree {

}

public class Leaf extends Tree {

public Object value;
...
}

public class Branch extends Tree {

public Object value;
public Tree left;
public Tree right;
...
}

對于這些類要注重的第一件事就是,兩種具體類都包含 Object 類型的 value 字段。假如您決定稍后讓樹包含,比如說,Interger,您也許會忘記更新其中的一個字段聲明。假如程序的其它部分需要這些字段是 Interger 的話,程序就很可能不會編譯。您或許記得您改變了其中一個類的 value 字段的類型,卻忽略了一個事實,就是您沒有在其它類中作相應的改變。

一些預防措施
當然,這個示例所示的錯誤是編程新手可以很快學會通過分解出公共代碼來避免的。在本例中,字段聲明應該移到 Tree 類中。它的兩個子類就會繼續這個字段,而且對字段聲明的任何改變都只需要在一個地方出現。

繼續看這個示例,我們可能還會編寫在一個 Tree 中相加和相乘所有節點的方法。為了簡單起見,我將以遞歸的方式來編寫這些方法。

// in class Tree:

public abstract int add();
public abstract int multiply();

// in class Branch:

public int add() {
return this.value.intValue() + left.add() + right.add();
}

public int multiply() {
return this.value.intValue() * left.multiply() + right.multiply();
}

// in class Leaf:

public int add() { return this.value.intValue(); }
public int multiply() { return this.value.intValue(); }

請注重我在 multiply 方法中為 Branch 類引入的錯誤:我沒有用第三項去乘,而是加了它。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 渭源县| 柳州市| 嘉善县| 偏关县| 武城县| 开江县| 临泽县| 武乡县| 衡阳县| 彭山县| 郴州市| 玉林市| 平塘县| 浦北县| 罗源县| 招远市| 苍南县| 堆龙德庆县| 英超| 长沙县| 衡东县| 探索| 灯塔市| 保靖县| 泰州市| 岐山县| 秀山| 怀化市| 工布江达县| 舞阳县| 闽侯县| 余姚市| 津南区| 怀来县| 慈利县| 邢台市| 宣城市| 壤塘县| 千阳县| 玉山县| 民乐县|