大家寫了不少四則運算的練習,這些代碼都各有特色,大家寫的 “軟體” 也有一定的用處。 如果我們要把這個功能放到不同的環境中去 (例如,指令行,windows 圖形界面程式,網頁程式,手機App), 就會碰到困難, 因為目前代碼的普遍問題是代碼都散落在main() 函數或者其他子函數中,我們很難把這些功能完整地剝離出來,作為一個獨立的子產品滿足不同的需求。
我們看到,不同的代碼解決不同層面的問題,有些是内部資料的計算 (例如四則運算);有些是和使用者輸入相關的 (例如 scanf,cin,圖形界面的輸入字段),有些是和資料的展現相關的 (例如 printf ,cout,println),有些是和程式所在平台的架構相關的(例如 main 函數,并不是所有的程式都需要某個特定格式的main)。 這就需要我們對軟體的架構做一些整理和優化。
是以,接下來我們要做的是:
在我們第三次練習中,還是采用結對程式設計的方式 ,但是大家必須換一個隊友,我們會了解到子產品化程式設計,資訊隐藏,接口設計,TDD,等。
大家把四則運算的計算功能包裝在一個子產品中 (這個子產品可以是一個類 Class, 一個DLL,等等), 為了友善起見,我們叫它 “計算核心” 子產品, 這個子產品至少在兩個地方可以使用:
測試程式,這個可以是一個指令行的程式,或者是JUnit 的架構,或者是Visual Studio 單元測試的架構。這樣,我們在算法層級保證了這個子產品的正确性。
實際的軟體,這是傳遞給最終使用者的軟體,有一定的界面和必要的輔助功能。
那麼這個“計算核心”子產品和使用它的其他子產品之間是什麼關系呢? 它們要通過一定的API (Application Programming Interface) 來和其他子產品交流。 這個API 接口應該怎麼設計呢(有經驗和實力的童鞋可以考慮一下)? 為了簡單,我們可以從下面的最簡單的接口開始:
這個Calc 函數接受字元串的輸入(字元串裡就是運算式子,例如 “ 5+3.5“, “7/8 – 3/8 ”, “3 + 90 * (-0.3)“ 等等),這個子產品的傳回值是一個字元串,例如,前面幾個例子的結果就是 ( ”17.5“, “ 1/2”, “-24“).
假設我們用的是類,我們的測試程式剛開始可以是非常簡單的測試例子: (用僞代碼表示)
然後同學們實作自己 Core 的這個功能。
第一階段目标 - 能把計算的功能封裝起來,通過測試程式和API 接口測試其簡單的加法功能。
加法成功之後,然後我們再做減法, 乘法,除法,我們假設目前為止都是兩個操作數的運算,還是很容易實作的。 由于同學們已經在自己以前的程式中實作了各種算法,這時候隻要把實作的算法搬過來就好了。 大家可以不斷增加測試的數量,在每實作一個新的功能的時候,要保證以前運作正确的例子繼續是正确的, 通過這樣的 “回歸測試“, 來保證自己實作的函數一直是正确的。 (請看書中關于單元測試,回歸測試的内容)
第二階段目标 - 通過測試程式和API 接口測試其簡單的加減乘除功能。并能看到代碼覆寫率。
對于多個運算符的運算,帶負數的運算,我們這個子產品有一些參數要設定,例如,最多幾個運算符,資料範圍是多少,還要設定計算的精度(保留幾位小數,等等), 這是由什麼API 來決定呢? 我們可以擴充 Calc() 的定義,讓它接受一個新的參數 “precision”, 或者我們可以啟用一個新的函數 Setting()。如果我想表示:
最多4 個運算符
數值範圍是 -1000 到 1000
精度是小數點後兩位
怎麼通過API 告訴我們的子產品呢? 我們當然可以用函數的參數直接傳遞,但是參數的組合很多,怎麼定義好參數的規範呢? 建議大家考慮用 XML 來傳遞這些參數(實際就是在XML定義好規則,然後程式讀取XML規則來執行計算)。
增加了新的Setting() 函數之後,我們要讓子產品支援這樣的參數,同時,還要保證原來的各個測試用例繼續正确地工作。
第三階段目标 - 通過測試程式和API 接口測試對于各種參數的支援。并能看到代碼覆寫率。
這個時候,如果輸入是有錯誤的,例如 “1 ++ 2”, 在數值範圍是 -1000 .. 1000 的時候,傳進去 “10000 + 32768”, 或者是 “ 248 / 0” 怎麼辦? 怎麼告訴函數的調用者 “你錯了”? 把傳回的字元串定義為 “-1” 來表示? 那麼如果真的計算結果是 “-1” 又怎麼處理呢?
建議這個時候,我們要定義各種異常 (Exception), 讓 Core 在碰到各種異常情況的時候,能告訴調用者 - 你錯了! 當然,這個時候,我們同樣要進行下面的增量修改:
定義要增加什麼功能 - 例如:支援 “運算式子格式錯誤” 異常
寫好測試用例,傳進去一個錯誤的式子,期望能捕獲這個 異常。 如果沒有,那測試就報錯。
在 Core 子產品中實作這個功能
測試這個功能
同時測試所有以前的功能,保證以前的功能還能繼續工作 (沒有 regression)
确認功能完成,繼續下一個功能
第四階段目标 - 通過增量修改改程序式, 完成對各種錯誤情況的處理。
幾點說明:
時間:兩周(具體杜老師這邊安排) 每周完成兩個階段目标。
結對必須換一個隊友。
參考資料:
《建構之法》 單元測試,回歸測試内容
Java解析XML:http://inotgaoshou.iteye.com/blog/1012188
Junit教程:http://pan.baidu.com/s/1qWsaMVM
XML教程:http://pan.baidu.com/s/1s3u3c#path=%252F
Java自定義異常:http://blog.csdn.net/stellaah/article/details/6738424