測試驅(qū)動的面向?qū)ο筌浖_發(fā)

出版時間:2010年8月  出版社:機(jī)械工業(yè)出版社  作者:Steve Freeman,Nat Pryce  頁數(shù):253  譯者:王海鵬  
Tag標(biāo)簽:無  

前言

  隨著軟件發(fā)布周期越來越短,一個困境出現(xiàn)了:如何在更少的時間里發(fā)布更多的軟件,并持續(xù)地發(fā)布下去?我們需要新的觀點(diǎn)來解決這個困境。只有技術(shù)的轉(zhuǎn)變是不夠的。  本書展示了這樣一個新觀點(diǎn)——假如軟件不是“做”出來的,不像我們做紙飛機(jī)那樣,疊好后就飛出去,情況會怎樣呢?假如我們像對待有價值、有產(chǎn)出的農(nóng)作物那樣(培育、剪草、收割、施肥和灌溉)對待軟件,情況會怎樣呢?幾十年或幾個世紀(jì)以來,傳統(tǒng)的農(nóng)夫知道如何讓農(nóng)作物高產(chǎn)。如果我們以同樣的方式對待程序,軟件開發(fā)會有什么不同呢?  我印象最深的是,本書同時提供了這種觀點(diǎn)轉(zhuǎn)變的哲學(xué)思想和實(shí)現(xiàn)機(jī)制。本書的作者是善于寫代碼的實(shí)踐者,他們也善于教別人寫代碼。您從中可以學(xué)到如何保持高產(chǎn),以及如何重新審視您的程序?! ∵@里展示的測試驅(qū)動開發(fā)的方式不同于我所使用的方式。雖然我還不能清晰表達(dá)其中的區(qū)別,但我已從作者清楚、自信的技巧介紹中受益。方言的多樣化已經(jīng)為我進(jìn)一步優(yōu)化開發(fā)提供了思考的新源泉。本書展示了一個有條理的、一致的開發(fā)體系,其中的不同技巧相互支持?! ∥医ㄗh您閱讀本書,通過書中的例子,了解作者如何思考編程,如何實(shí)踐編程。這種體驗(yàn)將豐富您的軟件開發(fā)方式,有助于您編程,而且同樣重要的是,有助于您以不同的觀點(diǎn)來看待您的程序。

內(nèi)容概要

本書采用通俗易懂的比喻,眾所周知的編程語言,短小精悍的工作實(shí)例,深入淺出的分析處理——仿佛在和幾位世界級的編程高手一邊喝茶,一邊聊天,循序漸進(jìn)地讓讀者在不知不覺中進(jìn)入編程的最高境界。即使是剛剛?cè)腴T的初學(xué)者,也會從中找到讀書的樂趣,因?yàn)榭梢詮囊婚_始就找到開啟面向?qū)ο箝_發(fā)大門的鑰匙;隨著經(jīng)驗(yàn)的積累,編程水平的提高,再來看這本書,用不同的視角重新審視程序,又會體會到更深層的編程哲學(xué)?! ”緯蔷幊虗酆谜叩膯⒚芍改?,更是系統(tǒng)分析人員、測試人員、程序設(shè)計人員、軟件開發(fā)人員以及面向?qū)ο蟪绦蜓芯咳藛T等專業(yè)人士革新編程思想的必備手冊。

作者簡介

Steve Freeman是一名獨(dú)立咨詢師,擅長領(lǐng)域是敏捷軟件開發(fā)(http://www.m3p.co.uk)。他與Nat Pryce一同贏得了2006年敏捷聯(lián)盟的Gordon Pask獎。他是倫敦極限星期二俱樂部(London Extreme Tuesday Club)的創(chuàng)建成員,也是第一任倫敦XP日(London XP Day)的主席,還經(jīng)常在國際

書籍目錄

對本書的贊譽(yù) 譯者序 序 前言 作者簡介 致謝 第一部分 簡介  第1章 測試驅(qū)動開發(fā)的要點(diǎn)  第2章 測試驅(qū)動開發(fā)與對象  第3章 工具介紹 第二部分 測試驅(qū)動開發(fā)過程  第4章 啟動測試驅(qū)動循環(huán)  第5章 保持測試驅(qū)動循環(huán)  第6章 面向?qū)ο箫L(fēng)格  第7章 實(shí)現(xiàn)面向?qū)ο笤O(shè)計  第8章 基于第三方代碼構(gòu)建 第三部分 工作的例子  第9章 委托開發(fā)一個拍賣狙擊者  第10章 可行走的骨架  第11章 通過第一個測試  第12章 準(zhǔn)備競拍  第13章 狙擊者發(fā)出競拍出價  第14章 狙擊者贏得拍賣  第15章 邁向真正的用戶界面  第16章 狙擊多項(xiàng)物品  第17章 分解Main  第18章 填充細(xì)節(jié)  第19章 處理失敗 第四部分 可持續(xù)的測試驅(qū)動開發(fā)  第20章 聆聽測試  第21章 測試可讀性  第22章 構(gòu)造復(fù)雜的測試數(shù)據(jù)  第23章 測試診斷  第24章 測試的靈活性 第五部分 高 級 主 題  第25章 測試持久性  第26章 單元測試與線程  第27章 測試異步代碼 后記 模擬對象簡史 附錄A jMock2速查手冊 附錄B 編寫Hamcrest Matcher 參考文獻(xiàn)

章節(jié)摘錄

  這意味著在實(shí)踐中我們可以把系統(tǒng)分成兩個“世界”:值和對象。值以函數(shù)式的方式對待,對象則實(shí)現(xiàn)了系統(tǒng)有狀態(tài)的行為。在第三部分,您會看到書中的編碼風(fēng)格是如何根據(jù)我們面對的世界而變化的?! ≡诒緯?,我們將使用術(shù)語“對象”來指具有標(biāo)識符、狀態(tài)和處理過程的實(shí)例,而不用于指值。似乎沒有其他可以接受的術(shù)語同時包含這兩種含義(如實(shí)體或過程)?! ?.3 對象通信  只有當(dāng)對象設(shè)計容易組合時,我們才能從這種高層次的、聲明式的方式中獲益。在實(shí)踐中,這意味著它們遵循相同的通信模式,也意味著它們之間的依賴關(guān)系是顯式的。通信模式是一組規(guī)則,決定了一組對象相互交談的方式。這些規(guī)則包括它們扮演的角色、它們可以發(fā)送什么消息、何時可以發(fā)送等。在Java這樣的語言中,我們可以利用(抽象的)接口來標(biāo)識對象的角色,而不是利用(具體的)類——雖然接口不能定義任何我們想說的內(nèi)容?! 「鶕?jù)我們的觀點(diǎn),領(lǐng)域模型就在這些通信模型之中,因?yàn)檎撬鼈優(yōu)閷ο箝g可能的關(guān)系賦予了意義。以動態(tài)的、互相通信的結(jié)構(gòu)來思考一個系統(tǒng),這對于靜態(tài)的分類來說是思考方式的巨大轉(zhuǎn)變,而我們中的大多數(shù)人在剛接觸對象時學(xué)到的都是靜態(tài)的分類。領(lǐng)域模型甚至都不是明顯可見的,因?yàn)樵谖覀兪褂玫木幊陶Z言中,通信模式?jīng)]有明確表達(dá)出來。本書希望展示測試和模擬對象如何幫助我們更清楚地看到對象之間的通信。  這里有一個小例子,說明關(guān)注對象間的通信是怎樣指導(dǎo)設(shè)計的?! ≡谝粋€視頻游戲中,對象可能包括:參與者(如玩家和敵人)、場景(玩家飛過的環(huán)境)、障礙(玩家遇上就會撞毀)、效果(如爆炸和煙霧)。還有一些腳本,它們在游戲過程中在后臺大量生成對象。  從玩家的視角來說,這是一種很好的分類,因?yàn)樗С治覀冊谕嬗螒驎r需要做出的決定,也就是從外界與游戲進(jìn)行交互時做決定。但是,對于實(shí)現(xiàn)這個游戲來說,這不是很有用的分類。游戲引擎必須顯示可見的對象,告訴對象隨時間產(chǎn)生動畫效果,檢測實(shí)體對象間的碰撞,并在實(shí)體對象發(fā)生碰撞時,把決定代理給碰撞處理器,如圖2-2所示。  正如您在圖2-2中看到的,這兩種視角是不同的,一個是從游戲引擎的角度來看,另一個是從參與對象實(shí)現(xiàn)的角度來看。例如,障礙是可見的、實(shí)體的,而腳本是碰撞處理器和動畫的,但不是可見的。游戲中的對象扮演了不同角色,取決于引擎當(dāng)時對它們的需要。這種靜態(tài)分類與動態(tài)通信之間的不匹配意味著,我們不太可能對游戲?qū)ο蟮玫揭粋€整齊的類層次結(jié)構(gòu),同時又能適合引擎的需要?! ≡谧詈玫臅r候,類層次結(jié)構(gòu)代表了應(yīng)用的一個維度,它提供了一種機(jī)制,讓對象之間能共享實(shí)現(xiàn)細(xì)節(jié)。例如,我們可能有一個基類來實(shí)現(xiàn)基于幀的動畫的共同特征。在最壞的時候,我們曾看到許多代碼庫(包括我們自己的),充滿了復(fù)雜性和重復(fù),因?yàn)槭褂靡环N機(jī)制來表達(dá)多個概念。

媒體關(guān)注與評論

  “終于有一本書用豐富的代碼揭示TDD和OOD之間的共生關(guān)系。本書值得保存。”  ——Robert C.Martin  “如果您想成為當(dāng)前TDD領(lǐng)域的一名專家,就需要理解本書中的思想?!薄  狹ichael Feathers

編輯推薦

  《測試驅(qū)動的面向?qū)ο筌浖_發(fā)》對于更快交付更好的軟件,測試驅(qū)動開發(fā)(TDD)現(xiàn)在是一種已經(jīng)確立的技術(shù)。TDD基于一個簡單的思想:在寫產(chǎn)品代碼之前先寫它的測試代碼。但是,這個“簡單”的思想需要一些技能和判斷才能做得好?,F(xiàn)在有了一本TDD實(shí)踐指南。讓您深入理解那些基本概念,并向您展示了如何讓測試來引導(dǎo)開發(fā),“培育”出一致的、可靠的??删S護(hù)的軟件?! ∽髡呙枋隽怂麄兪褂玫倪^程,努力實(shí)現(xiàn)的設(shè)計原則。以及完成工作的一些工具。通過一個詳細(xì)實(shí)現(xiàn)的例子,您可以看到TDD如何在各個層次上工作,如何利用測試來驅(qū)動特征開發(fā)和代碼的面向?qū)ο蠼Y(jié)構(gòu),如何利用模擬對象來發(fā)現(xiàn)并描述對象之間的關(guān)系。在這個過程中?!稖y試驅(qū)動的面向?qū)ο筌浖_發(fā)》系統(tǒng)地討論了開發(fā)團(tuán)隊在使用TDD時遇到的挑戰(zhàn)——從過程中集成TDD到測試最難的特征?! ∨f代碼帶來的新思維,Robert C.Martin高度評價,Kent Berk作序推薦。  《測試驅(qū)動的面向?qū)ο筌浖_發(fā)》包括以下內(nèi)容:  ●如何有效實(shí)現(xiàn)TDD:啟動,然后在整個項(xiàng)目中保持你們的沖勁。  ●如何創(chuàng)建更干凈的、更有表現(xiàn)力的、更可維護(hù)的代碼。  ●如何利用測試。對可持續(xù)的品質(zhì)保持最嚴(yán)格的關(guān)注。  ●理解在真實(shí)軟件開發(fā)的環(huán)境中,TDD、模擬對象、面向?qū)ο笤O(shè)計如何交織在一起?!  袢绾卫媚M對象來指導(dǎo)面向?qū)ο笤O(shè)計?!  袢绾卧赥DD困難的地方取得成功:管理復(fù)雜的測試數(shù)據(jù)。測試持久層和并發(fā)。

圖書封面

圖書標(biāo)簽Tags

評論、評分、閱讀與下載


    測試驅(qū)動的面向?qū)ο筌浖_發(fā) PDF格式下載


用戶評論 (總計13條)

 
 

  •   這本書有兩大看點(diǎn),一是如何執(zhí)行測試驅(qū)動的開發(fā),二是面向?qū)ο蟮能浖O(shè)計,都融合實(shí)例演繹的非常透徹,十分推薦。
  •   早就聽說過TDD在程序開發(fā)中的重要性,限于時間,一直未能好好的學(xué)習(xí)一下該項(xiàng)技術(shù)?,F(xiàn)在終于到了學(xué)習(xí)TDD的時候了,就從本書開始我的TDD之旅吧!
  •   搞活動時買的超值
  •   剛看了幾眼 感覺還行吧~
  •   比較泛,感覺不好
  •   少有的面向?qū)ο蟮臏y試驅(qū)動書籍
  •   書還湊合,紙張有點(diǎn)弱,不影響閱讀,還行
  •   看了一點(diǎn)點(diǎn),書中用的講解的例子挺高深的
  •     例子有些過于復(fù)雜,再加上代碼沒有有效組織,很容易迷路。書中甚至沒有提到代碼的下載。
      
      
      建議學(xué)習(xí)《單元測試的藝術(shù)》,更為清晰。
      
      建議學(xué)習(xí)《單元測試的藝術(shù)》,更為清晰。
      
      建議學(xué)習(xí)《單元測試的藝術(shù)》,更為清晰。
      
      建議學(xué)習(xí)《單元測試的藝術(shù)》,更為清晰。
      
      建議學(xué)習(xí)《單元測試的藝術(shù)》,更為清晰。
      
  •       這本書2009年10月就出來了,當(dāng)時沒來得及細(xì)看,只是把它放入了我的待讀列表中。后來查到2010年8月也出了中文版,書名叫《測試驅(qū)動的面向?qū)ο筌浖_發(fā)》。看完全書后,我發(fā)現(xiàn)本書重點(diǎn)談的還是軟件培養(yǎng)問題。Growing這個詞出現(xiàn)在書的標(biāo)題中,非常吸引我的思路。
      
        在前言中,作者開宗明義,講了本書要強(qiáng)調(diào)的五個問題:1.如何讓測試驅(qū)動開發(fā)適應(yīng)我的工程;2.從那里開始做TDD;3.如何寫單元測試與端對端測試;4.測試驅(qū)動開發(fā)的“驅(qū)動”是何意;5.如何測試某一個困難的功能。
      
        第一部分是簡介。導(dǎo)言部分說了,TDD不僅是XP(極限編程)的核心實(shí)踐,而且也被Crystal Clear,Scrum等敏捷開發(fā)方法才用。敏捷和非敏捷項(xiàng)目都可應(yīng)用TDD,甚至是純研究項(xiàng)目都可以。
      
        第一章重申TDD的紀(jì)律——“在沒有一個失敗的用例之前,不要寫任何功能”。其后提出,將傳統(tǒng)的“測試-實(shí)現(xiàn)-重構(gòu)”小迭代外面,包上一個驗(yàn)收測試(Acceptance Test)。驗(yàn)收測試是測試整個系統(tǒng)是否能工作的。與之區(qū)別的是用于測試現(xiàn)有代碼與我們不能改變其代碼的模塊是否能配合工作的集成測試(Integration Test),以及測試對象本身功能的單元測試(Unit Test)。最后強(qiáng)調(diào)了單元測試能夠給我們一個發(fā)現(xiàn)不良設(shè)計以及重構(gòu)代碼的機(jī)會。
      
        接下來第二章講述了“值類”和“對象類”的區(qū)別。針對不變的數(shù)量和度量進(jìn)行建模,就是“值類”,它有些類似“不可變類”(Immutable Class)或者無狀態(tài)(Stateless)類。如果針對行為進(jìn)行建模,則是“對象類”了。最后講述了要使用單一的“告知型”調(diào)用代替請求式的一連串調(diào)用,例如用“master.allowSavingOfCustomisations();”來代替“((EditSaveCustomizer)master.getModelisable().getDockablePanel().getCustomizer()).getSaveItem().setEnabled(Boolean.FALSE.booleanValue());"。第三章介紹了一些TDD的基本工具。
      
        第二部分講述了TDD的具體過程。第四章講了如何確定測試驅(qū)動開發(fā)的第一個迭代周期。提出先實(shí)現(xiàn)最少量的真實(shí)功能以便可以自動地構(gòu)建、部署、端對端測試。這叫做“行走骨架”(Walking Skeleton),具體的說,是通過“理解問題->設(shè)計草圖->自動化構(gòu)建,部署,端對端測試->普通迭代”這個流程來做的。其后說道,測試先行的工程早起會引入混亂,但是迅速降低,因?yàn)檎业搅税l(fā)展的方向,預(yù)見了可能發(fā)生的錯誤。相反,測試后行(或到發(fā)布期限前才集成)的工程在最后會出現(xiàn)大量的混亂。這可以作為是否選取TDD的一個參考標(biāo)準(zhǔn)。而“行走骨架”的好處就是,能讓我們在仍有時間、預(yù)算和解決問題的意愿時,去解決問題,而不至于到了發(fā)布前才發(fā)現(xiàn)工程已經(jīng)失控。
      
        第五章講了如何維護(hù)測試驅(qū)動周期。作者提出,將衡量進(jìn)度的測試(針對新功能的驗(yàn)收測試)和用以捕捉“功能破壞”(Regression)的測試(已有的驗(yàn)收測試、整合測試、單元測試)分隔開來。“筆者注:廣義的回歸測試即為了保證正在開發(fā)的新功能不破壞既有功能而寫的測試,狹義的回歸測試專指前述的驗(yàn)收測試。”此后提到兩個問題,一是不要著急寫單元測試,以免整合時發(fā)現(xiàn)功能不符合需要,二是要學(xué)會“傾聽測試”——難于測試的功能往往意味著設(shè)計需要改進(jìn)。如不改進(jìn),如果功能增多,則該有問題的設(shè)計會更難于修改。
      
        第六章講述了如何在TDD中使用面向?qū)ο蟮娘L(fēng)格。作者講述了Cockburn的“端口與適配器”架構(gòu),業(yè)務(wù)領(lǐng)域的代碼應(yīng)該同技術(shù)設(shè)施,例如數(shù)據(jù)庫,UI等,分離開來。不要讓技術(shù)概念泄漏入應(yīng)用程序模型。所以要通過接口將應(yīng)用程序核心業(yè)務(wù)與每個技術(shù)領(lǐng)域橋接起來。這就是Eric Evans在《領(lǐng)域驅(qū)動設(shè)計》中所說的防腐層(Anticorruption Layer)。其后又講了封裝和信息遮掩的區(qū)別。封裝主要是相對于“對端”(Peer)來說的,強(qiáng)調(diào)訪問只能通過API進(jìn)行。而信息遮掩主要是針對上層業(yè)務(wù)來說的,意在使得高層邏輯不需關(guān)注低層細(xì)節(jié)。封裝和信息遮掩中的兩個常見問題即是通過API返回內(nèi)部實(shí)現(xiàn)而產(chǎn)生的“別名”效果。以及沒能提供直接的API調(diào)用,導(dǎo)致客戶代碼通過自己組合API來完成任務(wù),就像前述的一連串調(diào)用那樣,暴露了過多細(xì)節(jié)。接下來講了達(dá)成“單一責(zé)任原則”的一個口訣:不用任何連詞(和,或,但)去描述對象。如果有從句,那么應(yīng)該按照從句,把大對象拆分成一個個互相合作的小對象。這對于我們檢視自己的設(shè)計很有幫助。作者將設(shè)計中一個對象的協(xié)作者,分為三種角色模板。即依賴其服務(wù)方能運(yùn)轉(zhuǎn)的“依賴物”(Dependencies),用于通知事件而不關(guān)注其具體身份的“被通知物”(Notifications),以及利用其調(diào)整自身行為以符合系統(tǒng)需求之“調(diào)整物”(Adjustments)。其后作者講了“組合體對象”(筆者注:即組合各種對象來完成自身任務(wù)的功能模組,不同于設(shè)計模式中的組合體模式)所提供的API要比其各自部分的API總和簡單。它封裝了組件的存在及其內(nèi)部互動,為其對端展示出一個更簡單的抽象接口。本章的最后講述了“環(huán)境獨(dú)立性”的重要?!碍h(huán)境獨(dú)立性”規(guī)則幫我們判斷一個對象是否隱藏的太多或者隱藏了錯誤的信息。當(dāng)執(zhí)行環(huán)境變化時,環(huán)境獨(dú)立的對象是易于改變的。其運(yùn)行大環(huán)境可以通過構(gòu)造器(如果對于該對象是貫穿生命期的)或需要環(huán)境的方法(如果是瞬態(tài)的)傳入。
      
        第七章繼續(xù)講述如何達(dá)成面向?qū)ο蟮脑O(shè)計。首先講述TDD對OO設(shè)計的幫助:1.我們必須先描述我們要做什么,而后才是怎么做;2.為了使得單元測試易懂(由此變得可維護(hù)),我們必須限定它們的范圍(筆者注:如果單元測試過長或者setup階段太繁復(fù),則意味著受測的那個大對象需要拆解);3.我們必須將其依賴物傳給它,這意味著我們必須知道它依賴的都是些什么東西。再說了接口和協(xié)議的作用:接口描述了兩個組件是否互相適配,而協(xié)議則描述了他們是否能一起運(yùn)轉(zhuǎn)。又講了測試可以幫助我們發(fā)現(xiàn)設(shè)計中的問題:一個雜亂或不清晰的測試暗示著我們暴露了太多實(shí)現(xiàn),而且我們應(yīng)該重新考量該對象及其臨接物件的責(zé)任分配。在講到值類和對象類的設(shè)計時,作者提出了三個技巧:打散(將一個大對象分割成一組互相協(xié)作的小對象)、剝離(定義一個對象所需的新服務(wù),增加一個提供該服務(wù)的新對象)、捆綁(將相關(guān)對象藏入一個容器對象中)。最后在談到接口問題時,作者提出了兩個觀點(diǎn)。一個說道:針對某一個接口的實(shí)現(xiàn)而寫的Impl類是沒有意義的。如果實(shí)現(xiàn)類真的沒有一個好名字,那可能意味著接口的命名或者設(shè)計很糟。可能它因?yàn)橛刑嗟呢?zé)任而喪失了重點(diǎn);也可能它是以實(shí)現(xiàn)的角度命名,而非以其在客戶代碼的角度上;又或者它是一個值而非一個實(shí)體對象——這種不協(xié)調(diào)有時會在寫單元測試時呈現(xiàn)出來。(例如MyInteger和MyIntegerImpl這種接口分離就是很糟糕的)另一個說:應(yīng)該根據(jù)需要合并或者拆分接口。在發(fā)現(xiàn)實(shí)現(xiàn)類的結(jié)構(gòu)不清晰時,應(yīng)考慮接口是否沒有側(cè)重點(diǎn),需要拆解。
      
        第八章講如何在第三方代碼之上構(gòu)建自己的工程。作者建議寫一個適配器對象層,其使用第三方API實(shí)現(xiàn)它們的接口。我們用有重點(diǎn)的集成測試去測試這些適配器,以確認(rèn)我們理解了第三方API是如何工作的。
      
        第三部分講了一個例子,用開發(fā)一個捕捉拍賣行情而自動出價的競拍器,來說明如何以測試為指導(dǎo),去培養(yǎng)OO軟件開發(fā)。本部分跨越了十一章。在這個過程中,穿插著對前兩章所講原則的實(shí)例化運(yùn)用。第十一章演示了如何用最少的代碼搭建起來可以執(zhí)行的端對端測試。在本例中,僅有一個測試用空殼服務(wù)器,一個Swing窗口(最少的代碼),主程序向“服務(wù)器”發(fā)送加入消息,核實(shí)服務(wù)器確實(shí)收到消息;服務(wù)器關(guān)閉競拍,窗口顯示失敗消息,核實(shí)窗口確實(shí)顯示了失敗消息(可執(zhí)行的端對端測試)。第十二章對如何組織測試提出了小建議:將測試放在一個不同的包中。防止通過包級別的后門去測試,同時方便在IDE中瀏覽。第十五章講述了修改命名的重要性:重命名代碼中的若干功能,這是開發(fā)進(jìn)程的一個重要部分,就像我們可以用已經(jīng)寫出的代碼來更好地理解結(jié)構(gòu)應(yīng)該如何發(fā)展一樣,我們也通過用已經(jīng)修改過的名字去編程以更好地理解這些名字的意義。我們可以理解類型和方法名是如何互相配合起來工作的,以及概念是否清晰,這都會激發(fā)我們發(fā)現(xiàn)新的想法。如果一個功能的名字不對,唯一能做的明智事情就是改變它,以免過后閱讀代碼的人花了數(shù)不清的時間也弄不清代碼在干什么。第十七章說到靜態(tài)設(shè)計和動態(tài)設(shè)計的問題:重構(gòu)非常關(guān)注于靜態(tài)結(jié)構(gòu)(類與接口),以至于很容易忽略應(yīng)用程序動態(tài)結(jié)構(gòu)(實(shí)例與線程)。有時我們需要退一步考慮,去畫一個類似互動圖那樣的東西。其后的第十八章說道TDD應(yīng)該和其它的建模手段結(jié)合起來使用,并且不要把其它的建模技巧當(dāng)作一種目的,而是要理解它們,并且把它們當(dāng)作支持與指導(dǎo)開發(fā)的一種手段。最后第十九章說我們必須知道如何漸進(jìn)式的改變代碼,尤其是使得代碼結(jié)構(gòu)良好,以至于我們可以根據(jù)需求的改變把代碼帶我們想去的地方。
      
        第四部分標(biāo)題“可持續(xù)的測試驅(qū)動開發(fā)”,意為教大家如何提高測試的質(zhì)量,以便讓測試能夠更及時、更好地提供關(guān)于設(shè)計缺陷的反饋。第二十章講了幾個知識點(diǎn)。當(dāng)我們在測試驅(qū)動開發(fā)的過程中提取一個接口,我們就必須想出一個名字來描述剛剛發(fā)現(xiàn)的關(guān)系。我們覺得這使我們深入思考領(lǐng)域問題,并梳理出可能會錯過的概念。只覆寫可見的方法(即保護(hù)的和公有的)。這個規(guī)則防止了僅僅為了測試能覆寫而暴露了內(nèi)部方法。在談到模仿對象(Mock Object)時,作者說有兩個試探法可以決定一個類是不是像值類從而不值得去仿造它。第一,它的值是不可變的;第二,我們想不出來一個有意義的名字來描述把這個類當(dāng)作接口之后,實(shí)現(xiàn)它的那個類。在對付膨脹的(參數(shù)過多的,過于復(fù)雜的)構(gòu)造器時,作者提出可以提取出隱含的組件。其要尋找兩個條件:經(jīng)常在類里一起使用的參數(shù);擁有相同生命期的參數(shù)。當(dāng)我們剛好找到了這種情況時,就得努力想出一個好名字來解釋這個概念。一個做得好的設(shè)計,其標(biāo)志之一即是這種改變可以很容易集成進(jìn)來。我們堅持依賴物應(yīng)該通過構(gòu)造器傳入,但是被通知物和調(diào)整物可以設(shè)置為缺省值,稍后再行配置。當(dāng)一個構(gòu)造器太大了,并且我們不認(rèn)為參數(shù)中隱含有一個新的類型時,我們可以用更多的缺省值,僅在有特殊的測試用例時才覆蓋掉它們。在談到期望陳述時,作者說要避免太多的期望。如果我們有很多期望,要么就是視圖測試一個過于龐大的單位,要么就是鎖定了太多的對象交流行為。作者還談到了傾聽測試給我們帶來的四個好處:使領(lǐng)域知識局部化;將對象間的關(guān)系抽象并命名成類;通過定義類型和角色而帶來更多的名字,就意味著帶來更多的領(lǐng)域信息;與其提供數(shù)據(jù),不如提供行為。本章最后總結(jié)說:測試驅(qū)動開發(fā)是低容忍度的。低質(zhì)量的測試會使得開發(fā)速度變得非常慢,而且受測系統(tǒng)內(nèi)部代碼質(zhì)量低的話,會導(dǎo)致測試的質(zhì)量也跟著變低。
      
        第二十一章講了測試的可讀性問題。以下五種情況應(yīng)當(dāng)改進(jìn):1.測試名稱沒有清晰的描述出每個測試用例的重點(diǎn),以及它和其余測試用例的差別;單一的測試用例執(zhí)行了多個功能;測試用例間的結(jié)構(gòu)差異很大,以至于讀者不能通過速讀來理解它們的意圖;過多的設(shè)置和異常處理代碼,將業(yè)務(wù)邏輯淹沒其中;測試使用了不明其意的字面值(魔法數(shù)字)。在講到如何命名測試時,作者介紹了TestDox約定法,即使每一個名字讀起來像一個句子,其隱含主語即為測試目標(biāo),例如:A List holds items in the order they were added. A List can hold multiple references to the same item. A List throws an exception when removing an item it doesn’t hold.即可翻譯成三個測試方法的名稱:holdsItemsInTheOrderTheyWereAdded(),canHoldMultipleReferencesToTheSameItem(),throwsAnExceptionWhenRemovingAnItemItDoesntHold()。在變量的命名上,作者強(qiáng)調(diào)我們應(yīng)該用能夠顯示這些值或者對象在測試中所扮演的角色以及他們同目標(biāo)對象的關(guān)系的名字來命名。
      
        第二十二章講了如何構(gòu)建復(fù)雜的測試數(shù)據(jù)。測試數(shù)據(jù)構(gòu)建器的一個好處是,我們可以寫出易于閱讀且便于發(fā)現(xiàn)錯誤的測試代碼,因?yàn)槊總€構(gòu)建器方法都指明了它的參數(shù)的意圖。
      
        第二十三章講述了如何從測試失敗信息中演進(jìn)工程代碼。作者說,就算是發(fā)生在和我們現(xiàn)在所做無關(guān)的領(lǐng)域里面,未預(yù)期的測試失敗,也可能是有價值的。因?yàn)樗鼈兘沂玖舜a中我們所未注意到的隱含關(guān)系。如果一個失敗的測試清楚的解釋了失敗的東西和原因,我們就可以快速的排查并修正代碼。同時作者建議,“經(jīng)常同源代碼庫同步——可以到隔幾分鐘就一次的頻度——以便一旦一個測試突然失敗了,你不需要花費(fèi)多長時間就能撤銷最近的修改,并去嘗試另一個方法。……比起一直查錯,有時候回滾代碼并以一個清晰的頭腦重新思考“如何去寫”,可能會更快?!?br />   
        第二十四章講了測試的靈活性。如果一個對象因?yàn)橛刑嗟囊蕾囄锘蛘咂湟蕾囄锸请[藏的,從而很難從它的環(huán)境中解耦,那么當(dāng)系統(tǒng)的某個偏遠(yuǎn)角落改變了,測試就會失敗。
      
        最后的第五部分講述了一些高級話題,第二十五章講述了持久化。作者提出將影響持久化狀態(tài)的測試孤立開來。將執(zhí)行持久話操作的測試和針對被持久話對象進(jìn)行的測試分開來做。并且提及一個小技巧:不要以模式來命名類或者接口,它們與系統(tǒng)其它類之間的關(guān)系才是重要的。當(dāng)它們的工作方式改變時,這樣做會使得名稱具有誤導(dǎo)性。第二十六章講述了單元測試和線程。作者提出,并發(fā)是一個系統(tǒng)級別的關(guān)注點(diǎn),我們應(yīng)該在需要執(zhí)行并發(fā)任務(wù)的對象“功能對象”之外來操控它。最后第二十七章講述了測試異步代碼的問題。作者指出,一個測試可以有兩種方式觀察系統(tǒng):采樣可被觀測的狀態(tài)或者監(jiān)聽它發(fā)出的事件。同時還指出了異步測試的一個注意點(diǎn):測試可能會在系統(tǒng)之前運(yùn)行以至于沒有測試任何有用的東西。這會造成貌似正確的結(jié)果:錯誤的代碼看起來好像能正常運(yùn)行。還提出,采樣測試與監(jiān)聽事件測試的一個明顯區(qū)別是,輪詢可能會錯過被新近狀態(tài)所覆蓋掉的狀態(tài)更新。解決辦法是,可以查找記錄。觸發(fā)一個刺激事件,并等系統(tǒng)狀態(tài)穩(wěn)定再查詢。作者又提出,我們經(jīng)常采用一個命名方案去區(qū)分同步與斷言。例如waitUntil()是等待某一個受測系統(tǒng)穩(wěn)定(同步代碼),而assertEventually()則是斷言某個事件最終會發(fā)生。本章最后作者講述了測試排期事件的問題。通過將事件排期機(jī)制從系統(tǒng)中解耦,可以使得系統(tǒng)的行為具有確定性從而更易測試事件。我們可以將事件的生成抽取成一個由外部驅(qū)動的共享服務(wù)。
      
        本書的跋很值得一讀。寫了整個jMock從構(gòu)想,初創(chuàng),演進(jìn)到鞏固的過程。起初是為了方便測試某一個對象內(nèi)部的功能機(jī)制是否如我們預(yù)期,后來逐漸把關(guān)注點(diǎn)從參數(shù)的值轉(zhuǎn)移到了對象之間的信息溝通上。現(xiàn)在jMock已經(jīng)成為一個單元測試和驗(yàn)收測試中進(jìn)行期望陳述與斷言的常用庫了。讀者有必要熟悉并掌握它。最后的兩個附錄講了jMock2庫和Hamcrest匹配器的使用方法,如果對書前面的范例代碼中的用法不太熟悉,可以參考。
      
        總的說來,在讀此書的過程中我非常驚喜,發(fā)現(xiàn)盡管TDD有很多令人詬病的缺點(diǎn),但是仍然有人和我想像一樣,用不瘟不火的穩(wěn)健心態(tài)來創(chuàng)造性的加入“培養(yǎng)”要素,以使得TDD對工程開發(fā)有更大的促進(jìn)作用。測試是一個良好的反饋來源,可以真實(shí)的反映出我們在設(shè)計中考慮不周到之處,以及時督促我們改進(jìn)產(chǎn)品代碼的設(shè)計。要想讓測試能夠如此培養(yǎng)軟件的開發(fā),就必須著力于測試代碼的先行性、正確性、可讀性與靈活性。同時要注意用驗(yàn)收測試來催生新的迭代周期,在修改代碼時不僅要運(yùn)行單元測試,更要及時運(yùn)行驗(yàn)收測試以獲得更多回饋。我想信,用心于測試的努力,必能在產(chǎn)品代碼的研發(fā)中產(chǎn)生加倍的回報。
      
      本文為原創(chuàng),如需轉(zhuǎn)載請聯(lián)系作者(Email eastarstormlee@gmail.com 微博 http://weibo.com/eastarlee)
  •     有很多書說過要寫好的代碼,代碼要高內(nèi)聚,低耦合。代碼要符合SOLID原則。我們都知道這些說教,這些原則;但是,我們?nèi)绾尾拍苤牢覍懙囊欢未a不好呢,原則往往漂浮在理論層次,理論來源于實(shí)踐,但是高于實(shí)踐。我們必須需要一些“硬指標(biāo)”來衡量我的代碼,為什么說這段代碼是不好的呢?所以我們必須找到一些信號。
      這些信號可以來自哪里,測試就是其中一個信號源。
      1、一段代碼難以測試?需要構(gòu)建很多其他對象,然后才能實(shí)例化這個對象?請你務(wù)必檢查一下這個對象的職責(zé)是否單一。
      2、一段代碼難以測試?需要構(gòu)建一些很難構(gòu)建的對象,而這些對象由不受我們的控制。請你務(wù)必檢查一下我們是否需要對這些我們沒法控制的難以創(chuàng)建的對象進(jìn)行抽象,進(jìn)行適配。
      3、很難給一個測試方法起名字?是否意味著被測試的方法功能不明確或者職責(zé)太多。
      
      我已經(jīng)讀完了本書的第一、二以及四部分,我就覺得收獲良多,如果你想實(shí)行測試驅(qū)動開發(fā),那么這本書絕對是你的良師益友。
      唯獨(dú)有點(diǎn)缺陷的是,本書翻譯不是很通順,有些地方稍顯生硬,不過絕對不影響閱讀,我是這么覺得~~~
  •     書很薄,思想很豐富,結(jié)合了TDD思想與OOD思想的融合,還介紹了JMOCK2、HAMCREEST、JUnit4三個最有價值的工具。作者10余年的TDD經(jīng)驗(yàn)指導(dǎo)性很強(qiáng),堪稱神作。
      
      我相信它可以提升你至少一個檔次!
  •     本書作者是Mock技術(shù)的早期創(chuàng)始人,對OO理論和TDD的理解很深。讀本書不僅是學(xué)習(xí)TDD,更是學(xué)習(xí)OO思想和方法。相比Kent Beck的《TDD by Example》本書要好一個檔次。
 

250萬本中文圖書簡介、評論、評分,PDF格式免費(fèi)下載。 第一圖書網(wǎng) 手機(jī)版

京ICP備13047387號-7