• <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>
    • 軟件測試技術
    • 軟件測試博客
    • 軟件測試視頻
    • 開源軟件測試技術
    • 軟件測試論壇
    • 軟件測試沙龍
    • 軟件測試資料下載
    • 軟件測試雜志
    • 軟件測試人才招聘
      暫時沒有公告

    字號: | 推薦給好友 上一篇 | 下一篇

    敏捷思維(14)—代碼驗證

    發布: 2008-2-02 17:17 | 作者: 林星 | 來源: 不詳 | 查看: 19次 | 進入軟件測試論壇討論

    領測軟件測試網 要保證架構的穩定和成功,利用代碼對架構進行驗證是一種實用的手段。代碼驗證的核心是測試,特別是單元測試。而測試的基本操作思路是測試優先,它是敏捷方法中非常重要的一項實踐,是重構和穩定核模式的重要保障。
    面向對象體系中的代碼驗證
    代碼驗證是保證優秀的架構設計的一種方法,同時也是避免出現象牙塔式架構設計的一種措施。我們在上一篇穩定化中提到說架構設計最終將會體現為代碼的形式,因此使用形式化的代碼來對架構進行驗證是最有效的。
    由于是代碼驗證,因此就離不開編寫代碼,而代碼總是和具體的語言、編譯環境息息相關的。在這里我們主要討論面向對象語言,代碼示例采用的Java語言。利用面向對象語言來進行架構設計有很多的好處:
    首先,面向對象語言是一種更優秀的結構化語言,比起非面向對象語言,它能夠更好的實現封裝、降低耦合、并允許設計師在抽象層次上進行思考。這些因素為優秀的架構設計提供了條件。
    其次,面向對象語言可以允許設計師只關注在框架代碼上,而不用關心具體的實現代碼。當然,這并不是說非面向對象的語言就做不到這一點,只是面向對象語言的表現更優秀一些。
    最后,面向對象語言可以進行很好的重用。這就意味著,設計師可以利用原有的知識、原有的軟件體系,來解決新的問題。
    此外,利用Java語言,還可以獲得更多的好處。Java語言是一種面向接口的語言。我們知道,Java語言本身不支持多重集成,所有的Java類都是從Object類繼承下來的。這樣,一個繼承體系一旦確定就很難再更改。為了能夠達到多重繼承的靈活性,Java引入了接口機制,使用接口和使用抽象類并沒有什么不同的地方,一個具體類可以實現多個接口,而客戶端可以通過申明接口類型來使用,如下面這樣:
    List employees=new Vctor();
    如果需要將Vctor換成LinkedList,那么除了上面的創建代碼,其它的代碼不需要再做更多的修改。而Vctor這個具體類除了實現List這個接口以外,還實現了Cloneable、Collection、 RandomAccess、Serializable。這說明除了List接口之外,我們還可以通過以上所列的接口來訪問Vector類。因此接口繼承能夠成為類繼承的補充手段,發揮十分靈活的作用。同時又避免了多重繼承的復雜性。但是接口中只能夠定義空方法,這是接口的一個缺陷。因此在實際編程中,接口和抽象類通常是一起使用的。我們在Java的java.util包中看到Collection接口以及實現Collection接口的AbstractCollection抽象類就是這方面的例子。你可以從AbstractCollection抽象類(或其某個子類)中繼承,這樣你就可以使用到AbstractCollection中的缺省代碼實現,由于AbstractCollection實現了Collection接口,你的類也實現Collection接口;如果你不需要利用AbstractCollection中的代碼,你完全可以自己寫一個類,來實現Collection接口(這個例子中不太可能發生這種情況,因為工具類的重用性已經實現設計的非常好了)。Java中有很多類似的例子。Java語言設計并不是我們討論的重點,更加深入的討論可以參看專門的書籍,這里我們就不作太多的介紹了。
    以上花了一些篇幅來討論面向對象設計和面向接口設計的一些簡單的預備知識。這些知識將成為代碼驗證的基礎。
    接口和架構
    這里的接口指的并不是Java中的Interface的概念,它是廣義的接口,在Java語言中具體表現為類的公有方法或接口的方法。在COM體系或J2EE體系中還有類似但不完全相同的表現。對于一個系統的架構來說,最主要的其實就是定義這些接口。通過這些接口來將系統的類聯系在一起,通過接口來為用戶提供服務,通過接口來連接外部系統(例如數據庫、遺留系統等)。因此,我們為了對架構進行驗證的要求,就轉化為對接口的驗證要求。
    對接口進行驗證的基本思路是保證接口的可測試性。要保證接口具有可測試性,首先要做的是對類和類的職責進行分析。這里有幾條原則,可以提高接口的可測試性。
    1、 封裝原則
    接口的實現細節應該封裝在類的內部,對于類的用戶來說,他只需要知道類發布出的公有方法,而不需要知道實現細節。這樣,就可以根據類的共有方法編寫相應的測試代碼,只要滿足這些測試代碼,類的設計就是成功的。對于架構來說,類的可測試性是基礎,但是光保證這一條還不夠。
    2、 最小職責原則
    一個類(接口)要實現多少功能一直是一個不斷爭論的問題。但是一個類實現的功能應該盡可能的緊湊,一個類中只處理緊密相關的一些功能,一個方法更應該只做一件事情。這樣的話,類的測試代碼相應也會比較集中,保證了類的可測試性;貞浽诜謱幽J街形覀冇懻摰哪莻例子,實現類為不同的用戶提供了不同的接口,這也是最小原則的一個體現。
    3、 最小接口原則
    對于發布給用戶使用的方法,需要慎之再慎。一般來說,發布的方法應該盡可能的少。由于公布的方法可能被客戶頻繁的使用,如果設計上存在問題,或是需要對設計進行改進,都會對現有的方法造成影響。因此需要將這些影響減到最小。另一方面,一些比較輕型的共有方法應該組合為單個的方法。這樣可以降低用戶和系統的耦合程度,具體的做法可以通過外觀模式,也可以使用業務委托模式。關于這方面的討論,可以參考分層模式。較少的接口可以減輕了測試的工作量,讓測試工作更加集中。
    4、 最小耦合原則
    最小耦合原則說的是你設計的類和其它類的交互應該盡可能的少。如果發現一個類和大量的類存在耦合關系,可以引入新的類來削弱這種耦合度。在設計模式中,中介模式和外觀模式都是此類的應用。對于測試,尤其是單元測試來說,最理想的情況是測試的類是一個單純的類,和其它的類沒有任何的關系。但是現實中這種類是極少的,因此我們能夠做的是盡可能的降低測試類和其它的類的耦合度。這樣,測試代碼相對比較簡單,類在修改的時候,對測試代碼的影響也比較小。
    5、 分層原則
    分層原則是封裝原則的提升。一個系統,往往有各種各樣的職責,例如有負責和數據庫打交道的代碼,也有和用戶打交道的代碼。把這些代碼根據功能劃分為不同的層次,就可以對軟件架構的不同部分實現大的封裝。而要將類的可測試性的保證發展為對架構的可測試性的保證。就需要對系統使用分層原則,并在層的級別上編寫測試代碼。關于分層的詳細討論,請參見分層模式。
    如果你設計的架構無法滿足上述的原則,那么可以通過重構來對架構加以改進。關于重構方面的話題,可以參考Martin Fowler的重構一書和Joshua Kerievsky的重構到模式一書。
    如果我們深入追究的話,到底一個可驗證的架構有什么樣的意義呢?這就是下一節中提到的測試驅動和自動化測試的概念。
    測試驅動
    測試驅動的概念可能大家并不陌生。在RUP中的同樣概念是測試優先設計(test-first design),而在XP中則表現為測試優先編程(test-first programming)。其實我們在日常的工作中已經不知不覺的在進行測試驅動的部分工作了,但是將測試驅動提高如此的高度則要歸功于敏捷方法。測試驅動的基本思想是在對設計(或編碼)之前先考慮好(或寫好)測試代碼,這樣,測試工作就不僅僅是測試,而成為設計(或代碼)的規范了。Martin Fowler則稱之為"specification by example"
    在敏捷測試領域。一種做法是將需求完全表述為測試代碼的形式。這樣,軟件設計師的需求工作就不再是如何編寫需求來捕獲用戶的需要,而是如何編寫測試來捕獲用戶的需要了。這樣做有一個很明顯的好處。軟件設計中的最致命的代碼是在測試工作中發現代碼不能夠滿足需求,發生這種情況有很多的原因,但是其結果是非?膳碌,它將導致大量的返工。而將需求整理為測試代碼的形式,最后的代碼只要能夠經過測試,就一定能夠滿足需求。當然,這種肯定是有前提的,就是測試代碼要能夠完整、精確的描述需求。做到這一點可不容易。我們可以想象一下,在對用戶進行需求分析的時候,基本上是沒有什么代碼的,甚至連設計圖都沒有。這時候,要寫出測試代碼,這是很難做到的。這要求設計師在編寫測試代碼的時候,系統的整體架構已經成竹在胸。因此這項技術雖然擁有美好的前景,但是目前還遠遠沒有成熟。
    雖然我們沒有辦法完全使用以上的技術,但是借用其中的思想是完全有可能的。
    首先,測試代碼取代需求的思想之所以好,是因為測試代碼是沒有歧義的,能夠非常精確的描述需求(因為代碼級別是最細的級別),并緊密結合架構。因此,從需求分析階段,我們就應該盡可能的保持需求文檔的可測試性。其中一個可能的方式是使用CRC技術。CRC技術能夠幫助設計人員分析需求中存在的關鍵類,并找出類的職責和類之間的關系。在RUP中也有類似的技術。業務實體代表了領域中的一些實體類,定義業務實體的職責和關系,也能夠有助于提高設計的可測試性。無論是哪一種方法,其思路都是運用分析技術,找出業務領域中的關鍵因素,并加以細化。
    其次,測試驅動認為,測試已經不僅僅是測試了,更重要的是,測試已經成為一種契約。用于指導設計和測試。在這方面,Bertrand Meyer很早就提出了Design by Contract的概念。從軟件設計的最小的單元來看,這種契約實際上是定義了類的制造者和類的消費者之間的接口。
    最后,軟件開發團隊中的所有相關人員如果都能夠清楚架構測試代碼,那么對于架構的設計、實現、改進來說都是有幫助的。這里有一個關于測試人員的職責的問題。一般來說,我們認為測試人員的主要職責是找出錯誤,問題在于,測試人員大量的時間都花費在了找出一些開發人員不應該犯的錯誤上面。對于現代化的軟件來說,測試無疑是非常重要的一塊,但是如果測試人員的日常工作被大量原本可以避免的錯誤所充斥的話,那么軟件的質量和成本兩個方面則會有所欠缺。一個優秀的測試人員,應該把精力集中在軟件的可用性上,包括是否滿足需求,是否符合規范、設計是否有缺陷、性能是不是足夠好。除了發現缺陷(注意,我們這里用的是缺陷,而不是錯誤),測試人員還應該找出缺陷的原因,并給出改正意見。
    因此,比較好的做法是要求開發人員對軟件進行代碼級別的測試。因此,給出架構的測試代碼,并要求實現代碼通過測試是提高軟件質量的有效手段。在了解了測試驅動的思路之后,我們來回答上一節結束時候的問題?沈炞C架構的最大的好處是通過自動化測試,能夠建立一個不斷改進的架構。在重構模式中,我們了解了重構對架構的意義,而保證架構的可測試性,并為其建立起測試網(下一節中討論),則是架構能夠得以順利重構的基本保證。我們知道,重構的基本含義是在不影響代碼或架構外部行為的前提條件下對內部結構進行調整。但是,一旦對代碼進行了調整,要想保證其外部行為的不變性就很難了。因此,利用測試驅動的思路實現自動化測試,自動化測試是架構外部行為的等價物,不論架構如何演化,只要測試能夠通過,說明架構的外部行為就沒有發生變化。
    針對接口的測試
    和前文一樣,這里接口的概念仍然是廣義上的接口。我們希望架構在重構的時候能夠保持外部行為的穩定。但要做到這一點可不容易。發布的接口要保證穩定,設計師需要有豐富的設計經驗和領域經驗。前文提到的最小接口原則,其中的一個含義就是如此,發布的接口越多,今后帶來的麻煩就越多。因此,我們在設計架構,設計類的時候,應該從設計它們的接口入手,而不是一上手就思考具體的實現。這是面向對象思想和面向過程思想的一大差別。
    這里,我們需要回顧在穩定化這一模式中提到的從變化中尋找不變因素的方法。穩定化模式中介紹的方法同樣適用于本模式。只有接口穩定了,測試腳本才能夠穩定,測試自動化才可以順利進行。將變化的因素封裝起來,是保持測試腳本穩定的主要思路。變化的因素和需要封裝的程度根據環境的不同而不同。對一個項目來說,數據庫一般是固定的,那么數據訪問的代碼只要能夠集中在固定的位置就已經能夠滿足變化的需要了。但是對于一個產品來說,需要將數據訪問封裝為數據訪問層(或是OR映射層),針對不同的數據庫設計能夠動態替換的Connection。
    測試網
    本章的最后一個概念是測試網的概念。如果嚴格的按照測試優先的思路進行軟件開發的話。軟件完成的同時還會產生一張由大量的測試腳本組成的測試網。為什么說是測試網呢?測試腳本將軟件包裹起來,軟件任何一個地方的異動,測試網都會立刻反映出來。這就像是蜘蛛網一樣,能夠對需求、設計的變更進行快速、有效的管理。
    測試網的腳本主要是由單元測試構成的。因此開發人員的工作除了編寫程序之外,還需要編織和修補這張網。編織的含義是在編寫代碼之前先編寫測試代碼,修補的含義是在由于軟件變更而導致接口變更的時候,需要同步對測試腳本進行修改。額外的工作看起來似乎是加大了開發人員的工作量。但在我們的日常實踐中,我們發現事實正好相反,一開始開發人員雖然會因為構建測試網而導致開發速度下降,但是到了開發過程的中期,測試網為軟件變動節約的成本很快就能夠抵消初始的投入。而且,隨著對測試優先方法的熟悉和認同,構建測試網的成本將會不斷的下降,而起優勢將會越來越明顯:
    能夠很容易的檢測出出錯的代碼,為開發人員掃除了后顧之憂,使其能夠不斷的開發新功能,此外,它還是代碼日創建的基礎。
    為測試人員節省大量的時間,使得測試人員能夠將精力集中在更有效益的地方。
    此外,構成測試網還有一個額外的成本,如果開發團隊不熟悉面向對象語言,那么由于接口不穩定導致的測試網的變動會增大其構建成本。
    總結
    從以上的討論可以看出,架構和代碼是分不開的,架構脫離了代碼就不能夠稱得上是一個好的架構。這是架構的目標所決定的,架構的最終目標就是成為可執行的代碼,而架構則為代碼提供了結構性的指導。因此,用代碼來驗證架構是一種有效的做法。而要實現這個做法并不是一件容易的事情,我們需要考慮代碼級別的架構相關知識(我們討論的知識雖然局限在面向對象語言,但是在其它的語言中同樣可以找到類似的思想),并利用它們為架構設計服務。

    (待續)
    作者簡介:
    林星,辰訊軟件工作室項目管理組資深項目經理,有多年項目實施經驗。辰訊軟件工作室致力于先進軟件思想、軟件技術的應用,主要的研究方向在于軟件過程思想、Linux集群技術、OO技術和軟件工廠模式。您可以通過電子郵件 iamlinx@21cn.com 和他聯系。

    文章來源于領測軟件測試網 http://www.kjueaiud.com/

    TAG: 敏捷思維


    關于領測軟件測試網 | 領測軟件測試網合作伙伴 | 廣告服務 | 投稿指南 | 聯系我們 | 網站地圖 | 友情鏈接
    版權所有(C) 2003-2010 TestAge(領測軟件測試網)|領測國際科技(北京)有限公司|軟件測試工程師培訓網 All Rights Reserved
    北京市海淀區中關村南大街9號北京理工科技大廈1402室 京ICP備2023014753號-2
    技術支持和業務聯系:info@testage.com.cn 電話:010-51297073

    軟件測試 | 領測國際ISTQBISTQB官網TMMiTMMi認證國際軟件測試工程師認證領測軟件測試網

    老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月

  • <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>