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

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

前言

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

內(nèi)容概要

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

作者簡(jiǎn)介

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

書籍目錄

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

章節(jié)摘錄

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

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

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

編輯推薦

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

圖書封面

圖書標(biāo)簽Tags

評(píng)論、評(píng)分、閱讀與下載


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


用戶評(píng)論 (總計(jì)13條)

 
 

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

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

京ICP備13047387號(hào)-7