亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

Chinaunix

標(biāo)題: 診斷 Java 代碼: 設(shè)計(jì)“可測試的”應(yīng)用程序 [打印本頁]

作者: cinc    時(shí)間: 2002-10-08 10:05
標(biāo)題: 診斷 Java 代碼: 設(shè)計(jì)“可測試的”應(yīng)用程序
http://www-900.ibm.com/developerWorks/cn/java/j-diag/part15/index.shtml

心存測試概念進(jìn)行代碼設(shè)計(jì)時(shí)的七條基本原則
Eric E. Allen (eallen@cs.rice.edu)
博士研究生候選人,Rice 大學(xué)
2001 年 9 月

在診斷 Java 代碼的這一部分中,Eric Allen 暫停了對具體錯(cuò)誤模式的討論,轉(zhuǎn)而選擇討論關(guān)于設(shè)計(jì)易于、甚至我們樂于測試的軟件的問題。他概述了七條設(shè)計(jì)原則,這些原則能大幅提高您編寫測試代碼的效率并因此提高結(jié)果代碼庫的健壯性。請?jiān)谟懻撜搲c作者和其它讀者共享您關(guān)于本文的心得。
謹(jǐn)以本文獻(xiàn)給周二攻擊的受害者,向?yàn)?zāi)難挑戰(zhàn)的英雄們和美國人民的鋼鐵意志。
當(dāng)設(shè)計(jì)大型程序的時(shí)候,您必須時(shí)刻留心不同設(shè)計(jì)選項(xiàng)對諸如性能和可擴(kuò)展性這樣的特征的影響。隨著軟件產(chǎn)品的日漸復(fù)雜及其無所不在的部署,軟件的“可測試性”也成了更重要的考慮事項(xiàng)。

徹底測試代碼的重要性是顯然的。花在編寫測試和測試代碼上的時(shí)間和精力給您帶來的回報(bào)是維護(hù)成本的大幅降低。

然而,除非您很小心,否則您花在測試代碼上的精力可能會首先達(dá)到花在編寫代碼上的精力的幾倍!我曾看到程序員們齊心協(xié)力地對他們的全部代碼進(jìn)行單元測試,結(jié)果花在上面的時(shí)間使大多數(shù)人都以沮喪而告終。

幸運(yùn)的是,沒有必要這樣。在您設(shè)計(jì)軟件的時(shí)候應(yīng)用一些基本原則,編寫易于測試、甚至使測試成為樂趣的代碼是可能的。

跟其它編碼原則一樣,這些原則也不是不容置疑或不可改變的教條。有時(shí)候打破這些規(guī)則也是必要的。因此,理解每條原則背后的動機(jī)和判斷何時(shí)這些動機(jī)不適用(或應(yīng)讓位給更關(guān)心的問題)的能力是很重要的。

原則 1. 到 GUI 視圖的外面去
盡可能把代碼移到 GUI 視圖的外面。然后各種 GUI 動作就能成了模型上的簡單方法調(diào)用。為什么您需要這樣做呢?

對 GUI 測試者來說,通過方法調(diào)用測試功能比間接地測試功能容易的多。
另一個(gè)好處是它使修改程序功能而不影響視圖變的更容易。
當(dāng)然,視圖中也可能存在錯(cuò)誤。在理想情況下,對程序的測試將同時(shí)檢查模型和視圖。(想更多了解測試視圖,請參閱我關(guān)于 Liar View 錯(cuò)誤模式的文章或 Jeffries 等人的 Extreme Programming Installed。這兩個(gè)鏈接都在參考資料部分。)

原則 2. 使用類型進(jìn)行錯(cuò)誤檢查
類型是您的朋友 — 盡可能多地用類型系統(tǒng)自動檢查錯(cuò)誤。

類型能在程序運(yùn)行之前自動捕捉程序中的錯(cuò)誤。沒有靜態(tài)類型檢查的話,類型錯(cuò)誤將作為破壞者逗留在您的程序中,直到恰當(dāng)?shù)膱?zhí)行路徑碰巧把它揭露出來為止。

最大限度地發(fā)揮使用類型的長處是棘手的。通常,一組數(shù)據(jù)結(jié)構(gòu)可以在一個(gè)抽象級別上一起使用,或者被分出,成為一個(gè)單一的、更高抽象級別的一個(gè)新的相關(guān)數(shù)據(jù)類型。

事實(shí)上,編程語言自身的歷史可以看成是可以編程的抽象級別的逐漸提高。匯編語言提供了比特到整數(shù)和浮點(diǎn)數(shù)的抽象。接下來是記錄和函數(shù)抽象,然后又是諸如對象、類、線程以及異常這樣的抽象。

在每一抽象級別上,達(dá)到與更高級別抽象一致的功能是可能的,但那實(shí)質(zhì)上僅僅是耗費(fèi)更多精力,冒更多的錯(cuò)誤風(fēng)險(xiǎn)。

在面向?qū)ο笳Z言(其它現(xiàn)代語言也一樣)中,一個(gè)程序員在設(shè)計(jì)抽象上有很大的靈活性。在哪個(gè)抽象級別上設(shè)計(jì)程序就成了基于折衷的決定,比如由抽象級別提供的更多的健壯性和由于不能在更低抽象級別上工作而帶來的表達(dá)性(有時(shí)是性能)的損失。

通常,高級別抽象帶來的健壯性和簡單性的價(jià)值很少被其它考慮事項(xiàng)超過。(要了解對這個(gè)問題的更多討論,請參閱我關(guān)于 Impostor Type 錯(cuò)誤模式的文章,在參考資料部分有它的鏈接。)

原則 3. 使用調(diào)節(jié)器避免“故障線路”(fault line)
我用“故障線路”來指獨(dú)立組件之間的接口,獨(dú)立組件之間和組件與其相應(yīng)子組件之間相比,很少有交互。這種故障線路的一個(gè)典型示例是 GUI 視圖和它的模型之間的接口。其它示例包括在編譯器中處理的不同階段之間的接口或操作系統(tǒng)的內(nèi)核和用戶界面之間的接口。

找出程序的故障線路,然后用具有轉(zhuǎn)發(fā)功能的調(diào)節(jié)器快速訪問聚合組件。

沿著故障線路隔離測試每個(gè)組件通常更容易。但如果每個(gè)組件暴露的對象有很多,或者組件中您想測試的一些對象只有通過多個(gè)嵌套引用才能訪問,那么測試就會變的很乏味。

不用隔離測試,而是擁有您在它上面調(diào)用您想測試的各種方法的單個(gè)調(diào)節(jié)器對象通常是有幫助的。這個(gè)對象然后能把這些方法調(diào)用轉(zhuǎn)發(fā)到適當(dāng)?shù)牡胤健?br />
沿著相同線路,設(shè)計(jì)和自己的測試代碼串聯(lián)在一起的程序組件接口是有益的。這將使您把注意力集中在使這些接口盡可能簡單上。

原則 4. 方法:小型簽名和缺省參數(shù)
使用小型方法說明和重載帶缺省方法參數(shù)的方法將使您在測試中調(diào)用這些方法變的愉快的多。否則,在測試這些方法時(shí)您將不得不構(gòu)造額外參數(shù)。如果參數(shù)很大,那么將很快導(dǎo)致代碼膨脹。更糟的是,它會誘使您編寫比在其它情況下更少的測試。

原則 5. 訪問器不應(yīng)修改內(nèi)存狀態(tài)
請?jiān)谀臏y試中使用不修改內(nèi)存狀態(tài)的訪問器來檢查對象狀態(tài)。

在某些方面,測試和實(shí)驗(yàn)室試驗(yàn)相似。它們都想證明特定假設(shè)有效。如果特定檢查動作改變了該領(lǐng)域的狀態(tài),那么要這樣做會變得困難的多。

與量子力學(xué)領(lǐng)域不同,計(jì)算機(jī)進(jìn)程的狀態(tài)可以不修改就被檢查。使用這種原則對您有好處。

原則 6. 用接口說明外部程序組件
用接口說明外部程序組件使得我們可以容易地在測試案例中模擬這些組件。

這條原則能節(jié)省大量時(shí)間,特別是當(dāng)外部組件的實(shí)現(xiàn)還未完成時(shí)。通常,大多數(shù)基本組件都不能準(zhǔn)時(shí)可用。如果這些組件不在適當(dāng)位置您就不能測試您自己的代碼的話,那么您就在朝災(zāi)難走去。您的客戶不會關(guān)心您只有兩個(gè)小時(shí)來集成遲到了兩周的組件。他們知道的全部就是整套產(chǎn)品被延期了和這是違約的。

原則 7. 優(yōu)先編寫測試代碼
優(yōu)先編寫測試代碼。這是標(biāo)準(zhǔn)的 XP 方法,但卻總有一種忽視它的誘惑。

每次我屈服于這種誘惑時(shí),我都感到后悔。假設(shè)您正努力生產(chǎn)正確的代碼,那么您 好象能從推遲編寫測試代碼中節(jié)省的時(shí)間其實(shí)只是一個(gè)幻想。

注意:這不是說您應(yīng)該一次性編寫全部測試代碼后,再一次性全部實(shí)現(xiàn)。編寫一些測試代碼,實(shí)現(xiàn)它們,再編寫一些測試代碼,再實(shí)現(xiàn)它們等等是個(gè)更好的辦法。設(shè)計(jì)以這種方式得以進(jìn)展;在實(shí)現(xiàn)階段捕捉錯(cuò)誤并在下一組測試中改正它。以這種方式編寫測試也更少會使人畏縮。

代碼比您需要的還多?
只需一點(diǎn)點(diǎn)努力,就可能容易地對任何程序進(jìn)行徹底的測試。當(dāng)然,不可避免存在這些原則不適用的情況;于是,看起來好像不可能對功能進(jìn)行測試。

當(dāng)出現(xiàn)這些情況時(shí),我盡力退一步地看這個(gè)問題,“我怎樣才可能測試這種代碼?”相反地,我問自己,“我怎樣才能以可測試方式編寫這些代碼呢?”這種想法上的改變的結(jié)果經(jīng)常是增加了大量 僅僅服務(wù)于簡化測試的功能。

什么?別擔(dān)心;出現(xiàn)這種情況完全正常。

就象很多現(xiàn)有的設(shè)計(jì)模式,它們只是為了增加程序的可擴(kuò)展性就往程序中添加很多類(例如 visitor、decorator 等等),開發(fā)簡化測試的新模式是可以接受的。實(shí)際上,面向?qū)ο笳Z言的很多特征都是為了簡化擴(kuò)展而包含進(jìn)去的;為什么語言的未來版本(或全新的語言)不應(yīng)包含簡化測試的特征。

對 Java 語言來說,這已經(jīng)開始。人們計(jì)劃在未來版本中包含很多更強(qiáng)大的類型系統(tǒng)、斷言(assertion)等等。就象面向?qū)ο蟮恼Z言已經(jīng)增加了我們重用和擴(kuò)展現(xiàn)有代碼的程度,將來,面向測試的設(shè)計(jì)和特征將幫助我們增強(qiáng)新老代碼的健壯性。

參考資料

參加本文的討論論壇。


DePaul 大學(xué)的軟件工程系在檢測 Java 空指針異常的自動化法則方面做了一些工作。


JUnit 主頁提供討論程序測試方法的很多有趣文章的鏈接,并提供 JUnit 的最新版本。


如果您正用 VisualAge for Java 開發(fā)代碼,請看看這篇文章 VisualAge for Java 3.5 中的調(diào)試和單元測試。


查閱 iContract ,一個(gè)方便您往 Java 代碼中添加斷言的工具。


Roy Miller 和 Chris Collins 提供的文章“XP distilled”(developerWorks,2001 年 3 月),說明了極端編程方法如何為您的 Java 工程帶來更大的成功。


查閱 ExtremeProgramming.org 上的官方的 XP 編程規(guī)則。


想了解如何測試視圖的一些觀點(diǎn),看看 Eric Allen 關(guān)于 Liar View 錯(cuò)誤模式的文章(developerWorks,2001 年 4 月)。


想更多了解測試視圖的觀點(diǎn),Jeffries、Anderson 和 Hendrickson 的 Extreme Programming Installed(Addison-Wesley,2001 年)會很有用。


想了解為什么使用更高級別的抽象是更有益的(即使它只是在逐步走向前臺),請參閱 Eric Allen 關(guān)于 Impostor Type 錯(cuò)誤模式的文章(developerWorks,2001 年 7 月)。


在 developerWorks Java 技術(shù)專區(qū)上查找更多的 Java 參考資料。


關(guān)于作者
Eric Allen 從 Cornell 大學(xué)獲得計(jì)算機(jī)科學(xué)及數(shù)學(xué)的學(xué)士學(xué)位,并且是 Rice 大學(xué) Java 編程語言小組的博士候選人。在回 Rice 完成學(xué)位前,Eric 是 Cycorp,Inc. 的 Java 開發(fā)者帶頭人。他還在 Javaworld 主持“Java 初學(xué)者”討論論壇。他的研究包括在源程序和字節(jié)碼級別上 Java 語言的語義模型和靜態(tài)分析工具開發(fā)。Eric 還幫助開發(fā) Rice 的 NextGen 編程語言編譯器,NextGen 是一個(gè)支持泛運(yùn)行時(shí)類型的 Java 擴(kuò)展?赏ㄟ^ eallen@cs.rice.edu 與 Eric 聯(lián)系。
  


作者: cinc    時(shí)間: 2002-10-08 10:36
標(biāo)題: 診斷 Java 代碼: 設(shè)計(jì)“可測試的”應(yīng)用程序
如何生產(chǎn)出高質(zhì)量的軟件,很大程度上取決于代碼的質(zhì)量。
XP提出:高質(zhì)量的代碼,應(yīng)該是可測試的代碼。所以他提倡 test first design。

XP 推薦的test first design 的開發(fā)過程:
比如說你要寫一個(gè)類,按以下步驟來:

1.寫這個(gè)類的框架,寫的代碼只要能夠進(jìn)行測試就可以了。
2.寫測試代碼,完成測試框架,編譯源程序和測試程序,看到測試運(yùn)行失敗。
3.寫程序,然后運(yùn)行測試,直到所有測試通過。
4.以后修改代碼后,運(yùn)行測試,如果所有測試通過,修改代碼成功。



舉例說明:如果你寫一個(gè)更新數(shù)據(jù)庫的方法 updateThread:

Thread 是論壇里的一篇文章 屬性有 title(標(biāo)題), content(內(nèi)容), notify(是否通知作者)

1.寫這個(gè)類的框架:
class Thread { //Thread Bean
    ...  // 一堆的 get,set 方法
}
class ThreadDAO {
    /**
     * update Thread from DB
     */
    public void updateThread( Thread thread )
            throws SQLException, ThreadNotFoundException{
        // 里面不寫任何代碼,等到寫完測試后再在此寫代碼
        // 現(xiàn)在寫的 ThreadDAO 的代碼只是為了編譯通過。
    }
}

2.寫測試代碼,使用 JUnit 作為測試框架
  我寫了三個(gè)測試函數(shù):
  測試 NULL Object 的情況:testUpdateThreadNULLObject()
  測試 Thread Not Found  :testUpdateThreadNotFound()
  測試 正常的 更新       :testUpdateThreadNormal()
  
public class ThreadDAOTest extends TestCase {

...

public void testUpdateThreadNULLObject() {
    try{
        final ThreadDAO dao = new ThreadDAO()&#59;
        final Thread pt = null&#59;
        dao.updateThread(pt)&#59;
        fail ("Except NULL Object&quot&#59;
    }catch( final SQLException sqlException ){
        fail("Unexpected excetpion: " + sqlException )&#59;
    }catch( final ThreadNotFoundException threadNotFoundException ){
        fail("Unexpected excetpion: " + threadNotFoundException )&#59;
    }catch ( final IllegalArgumentException IllegalArgumentException ){
        //pass
    }
}


public void testUpdateThreadNotFound() throws Exception {
    try{
        final ThreadDAO dao = new ThreadDAO()&#59;
        final Thread pt = dao.findByUID( 1 )&#59;
        pt.setID( 100 )&#59;
        dao.updateThread(pt)&#59;
        fail("Expect ThreadNotFoundException&quot&#59;
    }catch( final SQLException sqlException ){
        fail("Unexpected excetpion: " + sqlException )&#59;
    }catch( final ThreadNotFoundException threadNotFoundException ){
        //Pass
    }
        
}

public void testUpdateThreadNormal() throws Exception {
    ThreadDAO dao = new ThreadDAO()&#59;
    Thread pt = dao.findByUID(1)&#59;
    // store old values
    String oldTitle = pt.getTitle()&#59;
    String oldContent = pt.getContent()&#59;
    boolean oldNotify = pt.getNotify()&#59;
    // change values
    pt.setTitle ( oldTitle + "AddedTitle.&quot&#59;
    pt.setContent ( oldContent+ "AddedContent.&quot&#59;
    pt.setNotify(!oldNotify)&#59;
    // update
    dao.updateThread(pt)&#59;
   
    // query again
    pt = dao.findByUID(1)&#59;
   
    assertEquals("Update Thread Title", oldTitle + "AddedTitle.", pt.getTitle())&#59;
    assertEquals("Update Thread Content", oldContent + "AddedContent.", pt.getContent())&#59;
    assertEquals("Update thread Notify", !oldNotify, pt.getNotify())&#59;
   
    // back to original value
    // change values
    pt.setTitle( oldTitle )&#59;
    pt.setContent( oldContent )&#59;
    pt.setNotify( oldNotify )&#59;
    // update
    dao.updateThread(pt)&#59;
}
    編譯,運(yùn)行測試,一定失敗,呵呵,這就是現(xiàn)在我們的目標(biāo),測試框架已經(jīng)完成

3. 開始寫 ThreadDAO.updateThread() 方法

    /**
     * Update title , content, notify of a thread
     */
    public void updateThread( final Thread thread )
            throws SQLException, ThreadNotFoundException{
        Validation.validateNotNull( thread )&#59;
        final Thread newThread = thread&#59;
        findByUID( newThread.getID() )&#59;
        Connection conn = getConnection()&#59;
        PreparedStatement stat
            = conn.prepareStatement( "update " + ... )&#59;
        stat.setString( 1, newThread.getTitle() )&#59;
        stat.setString( 2, newThread.getContent() )&#59;
        stat.setString( 3, notifyString )&#59;
        stat.execute()&#59;

        stat.close()&#59;
        conn.close()&#59;
    }

    然后運(yùn)行測試,如果測試失敗,繼續(xù)修改代碼,直到測試成功。

4. 如果以后對代碼做修改,比如方法內(nèi)部的優(yōu)化。。。只要重新運(yùn)行測試,
   就可以很有信心的說,我的代碼沒有問題。


這有幾個(gè)好處
  寫程序是可以知道什么時(shí)候?qū)懘a結(jié)束了,以運(yùn)行測試是否成功為標(biāo)準(zhǔn)
  對自己的代碼很有信心,特別是對將來的改動,不用害怕。
  好的代碼是可測試的代碼,寫測試的過程,會發(fā)現(xiàn)原來設(shè)計(jì)中不足的地方,可加以修改
  測試可以作為代碼的文檔,要知道代碼作了些什么,看測試代碼就可以了。

測試工具:
  JUnit(單元測試框架類庫)
  Ant(Java 項(xiàng)目管理軟件)

作者: designlee    時(shí)間: 2002-10-08 15:49
標(biāo)題: 診斷 Java 代碼: 設(shè)計(jì)“可測試的”應(yīng)用程序
好長,偶頭暈了,先收起來!
作者: eclipse    時(shí)間: 2002-10-08 15:55
標(biāo)題: 診斷 Java 代碼: 設(shè)計(jì)“可測試的”應(yīng)用程序
看完了,可惜功力不夠,感覺理解只是字面上的,again~~
作者: cinc    時(shí)間: 2002-10-08 16:24
標(biāo)題: 診斷 Java 代碼: 設(shè)計(jì)“可測試的”應(yīng)用程序
最上面那篇文章我也沒仔細(xì)看,太多理論了,看不是很懂。

不過 XP 中提到的很多實(shí)踐(象 test first design, make it simple, refactoring)
卻是很實(shí)際很實(shí)際的東西。都是使用后立馬見效的。可以說也是前人的經(jīng)驗(yàn)積累,學(xué)習(xí)他
們對自己的編程水平的提高很有幫助。

我也是在真正做過一次之后才真正有些了解,到理解和熟練還有好長一段路要走哦。

大家一起努力實(shí)踐。呵呵。
:)





歡迎光臨 Chinaunix (http://72891.cn/) Powered by Discuz! X3.2