火龍果-測試驅動開發(fā)_第1頁
火龍果-測試驅動開發(fā)_第2頁
火龍果-測試驅動開發(fā)_第3頁
火龍果-測試驅動開發(fā)_第4頁
火龍果-測試驅動開發(fā)_第5頁
已閱讀5頁,還剩149頁未讀 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、L/O/G/O測試驅動開發(fā)測試驅動開發(fā)敏捷開發(fā)培訓系列敏捷開發(fā)培訓系列 The Money實例實例 初步接觸初步接觸TDD 快速建立測試代碼 運行測試代碼,發(fā)現(xiàn)失敗 做一個“小”調整 運行測試代碼,使其全部成功 通過重構消除冗余 基本需求基本需求 實現(xiàn)一個多幣種資金的功能實現(xiàn)一個多幣種資金的功能設備設備數(shù)量數(shù)量單價單價小計小計IBM100025USD25000USDGE400100CHF60000CHFTotal65000USD貨幣貨幣1貨幣貨幣2匯率匯率CHFUSD1.5 很簡單的需求很簡單的需求 好像沒有什么難度好像沒有什么難度 內容并不完全清晰內容并不完全清晰 如何作出最優(yōu)的設計如何作出

2、最優(yōu)的設計 讓我們看讓我們看TDD是怎樣開始的是怎樣開始的 Chapter 1開始開始 To-do list 導航員的主要工作導航員的主要工作 隨時想到隨時添加隨時想到隨時添加 從小步伐開始從小步伐開始 準備工作準備工作 創(chuàng)建一個創(chuàng)建一個Java項目項目 引用引用Junit類庫類庫 打包規(guī)則:打包規(guī)則:com.focoon.tdd Src目錄為源文件目錄目錄為源文件目錄 Test目錄為測試文件目錄目錄為測試文件目錄 To-do list $5+10CHF= $10 if rate is 2:1 $5*2=$10 不知道從哪開始?不知道從哪開始? 就從最基本的開始就從最基本的開始 不用擔心,以后

3、想法會自然冒出來的不用擔心,以后想法會自然冒出來的 找一個找一個To-do list開始開始 創(chuàng)建一個測試創(chuàng)建一個測試public void testMultiplication() Dollar five = new Dollar (5);five.times(2);assertEquals(10, five.amount); 沒有沒腦的代碼沒有沒腦的代碼 編譯都過不了編譯都過不了 但是這就是開始但是這就是開始 讓我們先運行測試,雖然肯定不會過讓我們先運行測試,雖然肯定不會過 讓我們來解決問題讓我們來解決問題 創(chuàng)建創(chuàng)建Dollar類類 沒有實現(xiàn)沒有實現(xiàn) 但已經編譯通過但已經編譯通過 運行測試

4、,看結果,注意錯誤和失敗的區(qū)別運行測試,看結果,注意錯誤和失敗的區(qū)別 慢慢形成習慣慢慢形成習慣public class Dollar int amount;Dollar(int amount) void times(int multiplier) 快速解決失敗快速解決失敗 成功!成功! 雖然沒有解決問題,但是是有效的一部了public class Dollar int amount = 10;Dollar(int amount) void times(int multiplier) 應用變量應用變量amount 仍然成功!仍然成功!public class Dollar int amount

5、= 10;Dollar(int amount) this.amount = amount;void times(int multiplier) amount *= 2; 應用變量應用變量multiplier 仍然成功!仍然成功!public class Dollar int amount = 10;Dollar(int amount) this.amount = amount;void times(int multiplier) amount *= multiplier; To-do list又想到一些,至少有完成的: $5+10CHF= $10 if rate is 2:1 $5*2=$10

6、 amount應該是私有的 Dollar side-effects 貨幣取整 到目前為止到目前為止 建立測試清單(建立測試清單(To-do list) 從乘法的小故事開始從乘法的小故事開始 暫時忽略暫時忽略Junit的細節(jié)的細節(jié) 通過缺省或略等方法讓編譯通過通過缺省或略等方法讓編譯通過 通過無賴的方法先讓缺陷通過通過無賴的方法先讓缺陷通過 逐步讓代碼通用化,把變量使用起來逐步讓代碼通用化,把變量使用起來 又擴展了一些新又擴展了一些新to-do list項項 參見參見Chapter 1-Answer Chapter 2變質的對象變質的對象 一個一個TDD的過程如下的過程如下 寫一個測試寫一個測試

7、 讓它運行讓它運行 讓它正確讓它正確 目標:可運行的干凈代碼目標:可運行的干凈代碼 The clean code that worksRon Jeffries 先讓代碼先讓代碼Work,再讓它,再讓它Clean To-do list又想到一些,至少有完成的: $5+10CHF= $10 if rate is 2:1 $5*2=$10 amount應該是私有的 Dollar side-effects 貨幣取整 測試案例測試案例 換個數(shù)值,以防止寫死代碼的情況換個數(shù)值,以防止寫死代碼的情況 但失敗了但失敗了 找到原因找到原因 有時候修正的不一定是源程序有時候修正的不一定是源程序public voi

8、d testMultiplication() Dollar five = new Dollar (5);five.times(2);assertEquals(10, five.amount);five.times(3);assertEquals(15, five.amount); 測試案例測試案例 引入一個變量引入一個變量 出現(xiàn)編譯問題出現(xiàn)編譯問題 繼續(xù)解決問題繼續(xù)解決問題public void testMultiplication() Dollar five = new Dollar (5);Dollar product = five.times(2);assertEquals(10, pr

9、oduct.amount);product = five.times(3);assertEquals(15, product.amount); Dollar 增加一個返回值增加一個返回值 先返回先返回null 編譯通過但是失敗了編譯通過但是失敗了Dollar times(int multiplier) amount *= multiplier;return null;Dollar times(int multiplier) return new Dollar(amount * multiplier); 成功!成功! To-do list又想到一些,至少有完成的: $5+10CHF= $10 i

10、f rate is 2:1 $5*2=$10 amount應該是私有的 Dollar side-effects 貨幣取整 我們能讓測試快速通過的方法我們能讓測試快速通過的方法 我們已經用到了三個中的兩個我們已經用到了三個中的兩個 方法一:先寫死,然后慢慢替換代碼方法一:先寫死,然后慢慢替換代碼 方法二:直接寫入實際代碼方法二:直接寫入實際代碼 如果覺得復雜方法一,如果想清楚了方如果覺得復雜方法一,如果想清楚了方法二法二 請參見請參見Chaper 2-Answer Chapter 3等于等于 To-do list又想到一些,至少有完成的: $5+10CHF= $10 if rate is 2:1

11、 $5*2=$10 amount應該是私有的 Dollar side-effects 貨幣取整 equals()方法方法 測試案例測試案例 失敗失敗 對應的實現(xiàn)類對應的實現(xiàn)類Dollar Fakepublic void testEquality() assertTrue(new Dollar(5).equals(new Dollar(5);public boolean equals(Object object) return true 追加案例挑戰(zhàn)追加案例挑戰(zhàn)Fakepublic void testEquality() assertTrue(new Dollar(5).equals(new D

12、ollar(5); assertFalse(new Dollar(5).equals(new Dollar(6); Dollar類類 定義定義equal:amount相等相等 將來可能會變化將來可能會變化 三角法三角法public void testMultiplication() Dollar five = new Dollar (5);Dollar product = five.times(2);assertEquals(10, product.amount);product = five.times(3);assertEquals(15, product.amount); To-do l

13、ist又想到一些,至少有完成的: $5+10CHF= $10 if rate is 2:1 $5*2=$10 amount應該是私有的 Dollar side-effects 貨幣取整 equals()方法方法 equal空值的支持 equal對象 Chapter 4私有性私有性 To-do list又想到一些,至少有完成的: $5+10CHF= $10 if rate is 2:1 $5*2=$10 amount應該是私有的應該是私有的 Dollar side-effects 貨幣取整 equals()方法方法 equal空值的支持 equal對象 私有化的思路私有化的思路 將項目中直接調用

14、之處改為私有調用將項目中直接調用之處改為私有調用 我們已經實現(xiàn)了對象的我們已經實現(xiàn)了對象的equals方法方法public void testMultiplication() Dollar five = new Dollar (5);Dollar product = five.times(2);assertEquals(new Dollar(10), product);product = five.times(3);assertEquals(new Dollar(15), product); 私有化的思路私有化的思路 臨時變量沒有用處了臨時變量沒有用處了 修改屬性的私有化修改屬性的私有化pub

15、lic void testMultiplication() Dollar five = new Dollar (5);assertEquals(new Dollar(10), five.times(2);assertEquals(new Dollar(15), five.times(3); To-do list又想到一些,至少有完成的: $5+10CHF= $10 if rate is 2:1 $5*2=$10 amount應該是私有的應該是私有的 Dollar side-effects 貨幣取整 equals()方法方法 equal空值的支持 equal對象 Chapter 5引入法郎引入法

16、郎 To-do list又想到一些,至少有完成的: $5+10CHF= $10 if rate is 2:1 $5*2=$10 amount應該是私有的應該是私有的 Dollar side-effects 貨幣取整 equals()方法方法 equal空值的支持 equal對象 5CHF*2=10CHF,F(xiàn)ranc side effects 先寫先寫Franc的測試的測試 復制粘貼一段測試代碼,先復制粘貼一段測試代碼,先public void testFrancMultiplication() Franc five = new Franc (5);assertEquals(new Franc(

17、10), five.times(2);assertEquals(new Franc(15), five.times(3); 再寫再寫Franc讓測試通過讓測試通過 復制粘貼一段復制粘貼一段Dollar代碼,先代碼,先public class Franc private int amount;Franc(int amount) this.amount = amount;Franc times(int multiplier) return new Franc(amount * multiplier);public boolean equals(Object object) Franc franc

18、= (Franc)object;return amount = franc.amount; 消除冗余消除冗余 復制粘貼?冗余代碼?缺乏抽象?復制粘貼?冗余代碼?缺乏抽象? 消除冗余的重要性消除冗余的重要性 如果有冗余代碼,在消除冗余前別給別如果有冗余代碼,在消除冗余前別給別人看到。除了結對伙伴人看到。除了結對伙伴 暫時放下,計入暫時放下,計入To-do list To-do list又想到一些,至少有完成的:$5+10CHF= $10 if rate is 2:1$5*2=$10amount應該是私有的應該是私有的Dollar side-effects貨幣取整equals()方法方法equal

19、空值的支持equal對象5CHF*2=10CHF,F(xiàn)ranc side effectsDollar/Franc的冗余問題方法equals通用化方法times通用化 Chapter 6一切均等一切均等 To-do list又想到一些,至少有完成的:$5+10CHF= $10 if rate is 2:1$5*2=$10amount應該是私有的應該是私有的Dollar side-effects貨幣取整equals()方法方法equal空值的支持equal對象5CHF*2=10CHF,F(xiàn)ranc side effectsDollar/Franc的冗余問題方法方法equals通用化通用化方法times

20、通用化 消除冗余消除冗余 消除上一階段的欠賬消除上一階段的欠賬 思路思路1 選一個類繼承另一個選一個類繼承另一個 結果上沒有節(jié)省太多代碼(可以試一下)結果上沒有節(jié)省太多代碼(可以試一下) 思路思路2 “找找”一個公共超類一個公共超類 例如例如Money 增加增加Money類類 Moneypublic class Money Dollar繼承繼承Moneypublic class Dollar extends Money private int amount; 移動屬性移動屬性amount Money,注意,注意protectedpublic class Money protected int

21、amount; Dollarpublic class Dollar extends Money Equals方法方法 將將equals方法改成能上移方法改成能上移 也就是也就是Money的的equals 現(xiàn)在現(xiàn)在Dollar里改里改public boolean equals(Object object) Money money = (Money)object;return amount = money.amount; 再移動到再移動到Money中中 法郎的法郎的Equals方法方法 用于復制粘貼,法郎的用于復制粘貼,法郎的equals方法沒有方法沒有測試,需要補上測試,需要補上 永遠記住先寫測

22、試,再重構永遠記住先寫測試,再重構public void testEquality() assertTrue(new Dollar(5).equals(new Dollar(5);assertFalse(new Dollar(5).equals(new Dollar(6);assertTrue(new Franc(5).equals(new Franc(5);assertFalse(new Franc(5).equals(new Franc(6); 事實上我們又重復代碼了事實上我們又重復代碼了 先將法郎修改過來,記住先修改成一致先將法郎修改過來,記住先修改成一致在刪除冗余在刪除冗余 To-do

23、 list又想到一些,至少有完成的:$5+10CHF= $10 if rate is 2:1$5*2=$10amount應該是私有的應該是私有的Dollar side-effects貨幣取整equals()方法方法equal空值的支持equal對象5CHF*2=10CHF,F(xiàn)ranc side effectsDollar/Franc的冗余問題方法方法equals通用化通用化方法times通用化Dollar和Franc的equals問題 Chapter 7當蘋果遇到橘子當蘋果遇到橘子 To-do list又想到一些,至少有完成的:$5+10CHF= $10 if rate is 2:1$5*2=

24、$10amount應該是私有的應該是私有的Dollar side-effects貨幣取整equals()方法方法equal空值的支持equal對象5CHF*2=10CHF,F(xiàn)ranc side effectsDollar/Franc的冗余問題方法方法equals通用化通用化方法times通用化Dollar和和Franc的的equals問題問題 增加測試案例增加測試案例 首先測試不等首先測試不等public void testEquality() assertTrue(new Dollar(5).equals(new Dollar(5);assertFalse(new Dollar(5).equ

25、als(new Dollar(6);assertTrue(new Franc(5).equals(new Franc(5);assertFalse(new Franc(5).equals(new Franc(6);assertFalse(new Franc(5).equals(new Dollar(5); 失敗了,我們只判斷了金額失敗了,我們只判斷了金額 Equals方法方法 假定我們先使用類名來輔助判斷相等,假定我們先使用類名來輔助判斷相等,雖然這有脫離了業(yè)務的雖然這有脫離了業(yè)務的“味道味道” 但我們還沒有;類似幣種的概念,所以但我們還沒有;類似幣種的概念,所以權且用之權且用之public

26、boolean equals(Object object) Money money = (Money)object;return amount = money.amount & getClass().equals(money.getClass(); To-do list又想到一些,至少有完成的:$5+10CHF= $10 if rate is 2:1$5*2=$10amount應該是私有的應該是私有的Dollar side-effects貨幣取整equals()方法方法equal空值的支持equal對象5CHF*2=10CHF,F(xiàn)ranc side effectsDollar/Franc的冗余

27、問題方法方法equals通用化通用化方法times通用化Dollar和和Franc的的equals問題問題引入幣種的概念 Chapter 8制造對象制造對象 To-do list又想到一些,至少有完成的:$5+10CHF= $10 if rate is 2:1$5*2=$10amount應該是私有的應該是私有的Dollar side-effects貨幣取整equals()方法方法equal空值的支持equal對象5CHF*2=10CHF,F(xiàn)ranc side effectsDollar/Franc的冗余問題(的冗余問題(times方法明顯類同)方法明顯類同)方法方法equals通用化通用化方法

28、times通用化Dollar和和Franc的的equals問題問題引入幣種的概念 類同的代碼類同的代碼 Dollar FrancDollar times(int multiplier) return new Dollar(amount * multiplier);Franc times(int multiplier) return new Franc(amount * multiplier); 統(tǒng)一返回值統(tǒng)一返回值 Dollar FrancMoney times(int multiplier) return new Dollar(amount * multiplier);Money times

29、(int multiplier) return new Franc(amount * multiplier); 工廠方法替代工廠方法替代new 為了消除冗余我們先在為了消除冗余我們先在Money中引入一中引入一個工廠方法可以返回個工廠方法可以返回Dollar,在測試中,在測試中 Moneypublic void testMultiplication() Dollar five = Money.dollar(5);assertEquals(new Dollar(10), five.times(2);assertEquals(new Dollar(15), five.times(3);static

30、 Dollar dollar(int amount) return new Dollar(amount); 工廠方法替代工廠方法替代new 進一步我們是希望替換進一步我們是希望替換Dollar類,所以嘗類,所以嘗試想試想Money靠近靠近 出錯了,出錯了,Money沒有沒有times方法,但其子方法,但其子類有。先使用虛方法類有。先使用虛方法public void testMultiplication() Money five = Money.dollar(5);assertEquals(new Dollar(10), five.times(2);assertEquals(new Dollar

31、(15), five.times(3);public abstract class Moneyabstract Money times(int amount); 工廠方法替代工廠方法替代new 現(xiàn)在可以修改工廠方法的返回類了現(xiàn)在可以修改工廠方法的返回類了static Money dollar(int amount) return new Dollar(amount); 工廠方法替代工廠方法替代new 現(xiàn)在用工廠方法替代所有的現(xiàn)在用工廠方法替代所有的new方法方法 這樣沒有調用類需要知道有這樣沒有調用類需要知道有Dollar這個類這個類了,記住為取出重復掃清道路了,記住為取出重復掃清道路publ

32、ic void testMultiplication() Money five = Money.dollar(5);assertEquals(Money.dollar(10), five.times(2);assertEquals(Money.dollar(15), five.times(3);public void testEquality() assertTrue(Money.dollar(5).equals(new Dollar(5);assertFalse(Money.dollar(5).equals(new Dollar(6);assertTrue(new Franc(5).equa

33、ls(new Franc(5);assertFalse(new Franc(5).equals(new Franc(6);assertFalse(new Franc(5).equals(new Dollar(5); 工廠方法替代工廠方法替代new 同樣的工作做在同樣的工作做在Franc上,先測試上,先測試public void testEquality() assertTrue(Money.dollar(5).equals(Money.dollar(5);assertFalse(Money.dollar(5).equals(Money.dollar(6);assertTrue(Money.fr

34、anc(5).equals(Money.franc(5);assertFalse(Money.franc(5).equals(Money.franc(6);assertFalse(Money.franc(5).equals(Money.dollar(5);public void testFrancMultiplication() Money five = Money.franc(5);assertEquals(Money.franc(10), five.times(2);assertEquals(Money.franc(15), five.times(3); 工廠方法替代工廠方法替代new 實

35、現(xiàn)工廠方法,實現(xiàn)工廠方法,Money類類static Money franc(int amount) return new Franc(amount); 看起來看起來Dollar和和Franc分別測試的案例重分別測試的案例重復了,但是消除案例的重復不是簡單的復了,但是消除案例的重復不是簡單的刪除案例,否則會帶來測試不足的隱患,刪除案例,否則會帶來測試不足的隱患,所以我們先記下這個問題。所以我們先記下這個問題。 To-do list又想到一些,至少有完成的:$5+10CHF= $10 if rate is 2:1$5*2=$10amount應該是私有的應該是私有的Dollar side-effe

36、cts貨幣取整equals()方法方法equal空值的支持equal對象5CHF*2=10CHF,F(xiàn)ranc side effectsDollar/Franc的冗余問題的冗余問題方法方法equals通用化通用化方法times通用化Dollar和和Franc的的equals問題問題引入幣種的概念去除重復的testFrancMultiplicaion案例 Chapter 9多幣種多幣種 To-do list又想到一些,至少有完成的:$5+10CHF= $10 if rate is 2:1$5*2=$10amount應該是私有的應該是私有的Dollar side-effects貨幣取整equals(

37、)方法方法equal空值的支持equal對象5CHF*2=10CHF,F(xiàn)ranc side effectsDollar/Franc的冗余問題方法方法equals通用化通用化方法times通用化Dollar和和Franc的的equals問題問題引入幣種的概念(用最簡單的字符串表示幣種)引入幣種的概念(用最簡單的字符串表示幣種)去除重復的testFrancMultiplicaion案例 增加測試案例增加測試案例 USD和和CHFpublic void testCurrency() assertEquals(USD, Money.dollar(1).currency();assertEquals(C

38、HF, Money.franc(1).currency(); 實現(xiàn)多幣種實現(xiàn)多幣種 先和先和times一樣處理,一樣處理,Moneyabstract String currency(); DollarString currency() return USD; FrancString currency() return CHF; 實現(xiàn)多幣種實現(xiàn)多幣種 將幣種作為一個屬性可能更合理將幣種作為一個屬性可能更合理 做相應的調整,做相應的調整,Dollarprivate String currency;Dollar(int amount) this.amount = amount;currency =

39、USD;String currency() return currency; 實現(xiàn)多幣種實現(xiàn)多幣種 Franc 又重復,我忍又重復,我忍private String currency;Franc(int amount) this.amount = amount;currency = “CHF;String currency() return currency; 實現(xiàn)多幣種實現(xiàn)多幣種 將重復的將重復的currency屬性歸納到屬性歸納到Money中中protected String currency;String currency() return currency; 構造函數(shù)的微調構造函數(shù)的微

40、調 如果把構造函數(shù)中幣種字符串替換為變如果把構造函數(shù)中幣種字符串替換為變量,那么兩個構造函數(shù)內容就一致了量,那么兩個構造函數(shù)內容就一致了 以此為目標,先價格參數(shù),以此為目標,先價格參數(shù),F(xiàn)ranc開始開始Franc(int amount, String currency) this.amount = amount;currency = CHF; 構造函數(shù)的微調構造函數(shù)的微調 調用構造函數(shù)的地方出錯了,調用構造函數(shù)的地方出錯了,Moneystatic Money franc(int amount) return new Franc(amount, null); FrancMoney times(

41、int multiplier) return new Franc(amount * multiplier, null); 突然發(fā)現(xiàn)突然發(fā)現(xiàn)times用的是用的是new而不是工廠方而不是工廠方法,一般不要打斷現(xiàn)在的工作,先寫入法,一般不要打斷現(xiàn)在的工作,先寫入To-do List,不過這里就先改了,不過這里就先改了 構造函數(shù)的微調構造函數(shù)的微調 測試失敗了,需要將幣種字符串引測試失敗了,需要將幣種字符串引入入,FrancFranc(int amount, String currency) this.amount = amount;this.currency = currency; Moneyst

42、atic Money franc(int amount) return new Franc(amount, CHF); 心得心得 通過細小的變化可以使推進更加可靠通過細小的變化可以使推進更加可靠 但是否一直保持這樣細小的步伐?但是否一直保持這樣細小的步伐? 答案是:不答案是:不 只是需要有能力細小化只是需要有能力細小化 如果有信心就邁開大步,如果復雜了就如果有信心就邁開大步,如果復雜了就縮小步伐,就像汽車起步掛檔一樣??s小步伐,就像汽車起步掛檔一樣。 構造函數(shù)的微調構造函數(shù)的微調 同樣的工作在同樣的工作在Dollar上,我們又聞到上,我們又聞到“味味道道”了了 Moneystatic Mone

43、y dollar(int amount) return new Dollar(amount, “USD);Dollar(int amount, String currency) this.amount = amount;this.currency = currency;Money times(int multiplier) return Money.dollar(amount * multiplier); 構造函數(shù)的上移構造函數(shù)的上移 既然構造函數(shù)一致,就可以上移,既然構造函數(shù)一致,就可以上移,Money DollarDollar(int amount, String currency) su

44、per(amount, currency);Money(int amount, String currency) this.amount = amount;this.currency = currency; FrancFranc(int amount, String currency) super(amount, currency); To-do list又想到一些,至少有完成的:$5+10CHF= $10 if rate is 2:1$5*2=$10amount應該是私有的應該是私有的Dollar side-effects貨幣取整equals()方法方法equal空值的支持equal對象5C

45、HF*2=10CHF,F(xiàn)ranc side effectsDollar/Franc的冗余問題方法方法equals通用化通用化方法times通用化Dollar和和Franc的的equals問題問題引入幣種的概念(用最簡單的字符串表示幣種)引入幣種的概念(用最簡單的字符串表示幣種)去除重復的testFrancMultiplicaion案例 Chapter 10乘法的處理乘法的處理 To-do list又想到一些,至少有完成的:$5+10CHF= $10 if rate is 2:1$5*2=$10amount應該是私有的應該是私有的Dollar side-effects貨幣取整equals()方法

46、方法equal空值的支持equal對象5CHF*2=10CHF,F(xiàn)ranc side effectsDollar/Franc的冗余問題方法方法equals通用化通用化方法方法times通用化通用化Dollar和和Franc的的equals問題問題引入幣種的概念(用最簡單的字符串表示幣種)引入幣種的概念(用最簡單的字符串表示幣種)去除重復的testFrancMultiplicaion案例 兩個相似的乘法兩個相似的乘法 相似但不相同,相似但不相同,F(xiàn)ranc DollarMoney times(int multiplier) return Money.franc(amount * multipli

47、er);Money times(int multiplier) return Money.dollar(amount * multiplier); 沒有明顯的方法使其相同沒有明顯的方法使其相同 有時候需要采取以退為進的策略有時候需要采取以退為進的策略 回到回到new 相似但不相同,相似但不相同,F(xiàn)ranc DollarMoney times(int multiplier) return new Franc(amount * multiplier, “CHF”);Money times(int multiplier) return new Dollar(amount * multiplier,

48、USD); 沒有明顯的方法使其相同沒有明顯的方法使其相同 有時候需要采取以退為進的策略有時候需要采取以退為進的策略 回到回到new 我們也可以使用我們也可以使用currency屬性,這樣兩屬性,這樣兩個方法更接近寫,個方法更接近寫,F(xiàn)ranc DollarMoney times(int multiplier) return new Franc(amount * multiplier, currency);Money times(int multiplier) return new Dollar(amount * multiplier, currency); 如果用如果用Money會怎樣?會怎樣

49、? 我們總是嘗試讓實現(xiàn)趨同,我們總是嘗試讓實現(xiàn)趨同,F(xiàn)rancMoney times(int multiplier) return new Money(amount * multiplier, currency); 編譯器說編譯器說Money是個虛類是個虛類 實化實化Money 從最簡單的開始,從最簡單的開始,Moneypublic class Money Money times(int amount) return null; 兩個看不懂的失敗兩個看不懂的失敗 好象是對象比較的問題,先修改對象輸好象是對象比較的問題,先修改對象輸出,出,Money 實化實化Money Money的的toStr

50、ing方法方法 沒有測試代碼?沒有測試代碼? 這里這里toString只用于只用于debug,風險低,風險低 當我們在紅杠狀態(tài)時我們傾向于不額外當我們在紅杠狀態(tài)時我們傾向于不額外寫測試代碼寫測試代碼 通過新的通過新的toString我們看到內容是一致的我們看到內容是一致的 問題出在之前采用的類判斷上問題出在之前采用的類判斷上public String toString() return amount + + currency; 退回退回 為了解決上述問題我們需要改代碼為了解決上述問題我們需要改代碼 但當我們在紅杠狀態(tài)時,我們不能寫且但當我們在紅杠狀態(tài)時,我們不能寫且他測試代碼他測試代碼 而沒有

51、測試代碼我們就不能修改新代碼而沒有測試代碼我們就不能修改新代碼 所以正確的做法是退回所以正確的做法是退回Money times(int multiplier) return new Franc(amount * multiplier, currency); 現(xiàn)在可以寫測試了現(xiàn)在可以寫測試了 判斷不同類的幣種相同判斷不同類的幣種相同public void testDifferentClassEquality() assertTrue(new Money(10, CHF).equals(new Franc(10, CHF); 修改修改Equals方法方法 從判斷類到判斷幣種字符串,從判斷類到判斷幣

52、種字符串, Moneypublic boolean equals(Object object) Money money = (Money)object;return amount = money.amount & currency().equals(money.currency(); 再次嘗試用再次嘗試用Money FrancMoney times(int multiplier) return new Money(amount * multiplier, currency); 成功,而且代碼一樣,合并到成功,而且代碼一樣,合并到Money DollarMoney times(int multi

53、plier) return new Money(amount * multiplier, currency);Money times(int multiplier) return new Money(amount * multiplier, currency); To-do list又想到一些,至少有完成的:$5+10CHF= $10 if rate is 2:1$5*2=$10amount應該是私有的應該是私有的Dollar side-effects貨幣取整equals()方法方法equal空值的支持equal對象5CHF*2=10CHF,F(xiàn)ranc side effectsDollar/F

54、ranc的冗余問題方法方法equals通用化通用化方法方法times通用化通用化Dollar和和Franc的的equals問題問題引入幣種的概念(用最簡單的字符串表示幣種)引入幣種的概念(用最簡單的字符串表示幣種)去除重復的testFrancMultiplicaion案例 Chapter 11只有只有Money To-do list又想到一些,至少有完成的:$5+10CHF= $10 if rate is 2:1$5*2=$10amount應該是私有的應該是私有的Dollar side-effects貨幣取整equals()方法方法equal空值的支持equal對象5CHF*2=10CHF,F(xiàn)

55、ranc side effectsDollar/Franc的冗余問題(只剩下構造函數(shù)了)的冗余問題(只剩下構造函數(shù)了)方法方法equals通用化通用化方法方法times通用化通用化Dollar和和Franc的的equals問題問題引入幣種的概念(用最簡單的字符串表示幣種)引入幣種的概念(用最簡單的字符串表示幣種)去除重復的testFrancMultiplicaion案例 構造函數(shù)構造函數(shù) 嘗試替換對構造函數(shù)的調用,嘗試替換對構造函數(shù)的調用,Money 沒有對沒有對Dollar類的調用了,可以直接刪掉類的調用了,可以直接刪掉了了static Money dollar(int amount) re

56、turn new Money(amount, USD);static Money franc(int amount) return new Money(amount, CHF); 刪除刪除Franc 對對Franc類還有一處引用類還有一處引用 但是離開但是離開Franc類,這個測試就和另一個類,這個測試就和另一個測試等價了測試等價了public void testDifferentClassEquality() assertTrue(new Money(10, CHF).equals(new Franc(10, CHF);public void testEquality() assertTru

57、e(Money.dollar(5).equals(Money.dollar(5);assertFalse(Money.dollar(5).equals(Money.dollar(6);assertTrue(Money.franc(5).equals(Money.franc(5);assertFalse(Money.franc(5).equals(Money.franc(6);assertFalse(Money.franc(5).equals(Money.dollar(5); 刪除多余的測試刪除多余的測試 刪除對刪除對Franc類還有一處引用的測試類還有一處引用的測試 刪除等價測試刪除等價測試p

58、ublic void testDifferentClassEquality()public void testFrancMultiplication()public void testEquality() assertTrue(Money.dollar(5).equals(Money.dollar(5);assertFalse(Money.dollar(5).equals(Money.dollar(6);/assertTrue(Money.franc(5).equals(Money.franc(5);/assertFalse(Money.franc(5).equals(Money.franc(

59、6);assertFalse(Money.franc(5).equals(Money.dollar(5); To-do list又想到一些,至少有完成的:$5+10CHF= $10 if rate is 2:1$5*2=$10amount應該是私有的應該是私有的Dollar side-effects貨幣取整equals()方法方法hashCodeequal空值的支持equal對象5CHF*2=10CHF,F(xiàn)ranc side effectsDollar/Franc的冗余問題的冗余問題方法方法equals通用化通用化方法方法times通用化通用化Dollar和和Franc的的equals問題問題

60、引入幣種的概念(用最簡單的字符串表示幣種)引入幣種的概念(用最簡單的字符串表示幣種)去除重復的testFrancMultiplicaion案例 Chapter 12加法加法 To-do list新的一天我們得到一個精簡的to-do list: $5+10CHF= $10 if rate is 2:1 To-do list逐漸增加一些想法: $5+10CHF= $10 if rate is 2:1 $5+$5=$10 增加測試案例增加測試案例 簡單的測試簡單的測試public void testSimpleAddition() Money sum = Money.dollar(5).plus(M

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論