服務計算 TDD實踐——實現快速排序演算法
服務計算 TDD實踐——實現快速排序演算法
1. 概念理解——TDD
1.1 什麼是TDD?
TDD 是 Test-Driven Development 的首字母縮寫,其中文為 “測試驅動開發”,在百度百科中,TDD 的定義如下:
TDD 是敏捷開發中的一項核心實踐和技術,也是一種設計方法論。TDD的原理是在開發功能程式碼之前,先編寫單元測試用例程式碼,測試程式碼確定需要編寫什麼產品程式碼。TDD 是 XP(Extreme Programming)的核心實踐。它的主要推動者是 Kent Beck。
1.2 TDD 程式設計方式
在傳統的程式設計方式中,程式設計師在需求分析結束後開始編碼,直到編寫完成之後才開始業務邏輯的測試,這使得程式的除錯變的困難,而且通過這種方式編寫的程式通常邏輯不夠清晰,可讀性較差,使得程式的修改和維護變得十分困哪。為了消除傳統程式設計方式帶來的弊端,TDD 的程式設計方式與傳統方式有很大不同:
- 先分解任務,將大問題分解為若干個小問題;
- 舉例,用例項化需求,澄清需求細節;
- 寫測試,只關注需求,程式的輸入輸出,不關心中間過程;
- 寫實現,不考慮別的需求,用最簡單的方式滿足當前這個小需求;
- 重構,使先前編寫的程式碼變得整潔規範;
- 執行測試,若出現問題則補充測試用例,並修正程式碼;
- 程式碼編寫完成。
1.3 TDD 的優點
- 我們每次只需實現一個子任務,降低了開發者的思維負擔;
- 每次實現一個子任務都需進行單元測試,可以及時修正錯誤;
- 提前編寫測試可以幫助我們明確需求及其細節,避免需求理解的偏差等問題;
- 覆蓋完全的單元測試使得優化程式碼或修改業務邏輯時變得安全;
1.4 TDD 的流程
- 寫一個測試用例;
- 嘗試執行測試(必然失敗);
- 先用最少的程式碼通過編譯,執行測試;
- 把程式碼補充完整,使得它能通過測試;
- 程式碼重構,提高程式碼質量;
- 編寫、執行基準測試。
1.5 相關詞彙理解
- 重構:改善程式碼的內部結構,提升程式碼的質量和效能;
- 測試:功能測試,用於測試程式的邏輯是否正確;
- 基準測試:效能測試,用於測試函式效能。
2. TDD實現快速排序
2.1 編寫測試用例 quicksort_test.go
單元測試的編寫格式為:
- 檔名必須以 _test.go 結尾;
- 方法名必須是 Test 開頭;
- 方法引數必須是 t *testing.T
因為我們需要實現的功能為快速排序,因此我們需要測試一個無序陣列在經過 Quicksort 函式處理後是否有序(升序),據此可以編寫如下測試:
package sort
import "testing"
func TestQuicksort(t *testing.T){
cases := []struct {
in, want []int
}{
{ []int{5, 3, 2, 1, 4}, []int{1, 2, 3, 4, 5} },
}
for _, c := range cases {
temp := c.in
Quicksort(c.in)
for i := 0; i < len(c.in); i++ {
if c.in[i] != c.want[i] {
t.Errorf("Quicksort(%q) == %q, want %q", temp, c.in, c.want)
break
}
}
}
}
2.2 嘗試執行測試
使用 go test ./sort
嘗試執行測試,顯然,因為我們尚未實現 Quicksort 函式,因此該測試必定是失敗的。雖然我們知道該測試不可能成功,但我們還是必須進行此次嘗試,使得執行結果使我們所期待的失敗(找不到 Quicksort 函式),而不是其他失敗(編譯錯誤等),這樣當程式出現錯誤的時候,我們可以很快定位到出錯的位置。執行測試的結果如下:
2.3 用最少的程式碼通過編譯,執行測試
為了使測試過程不再出現編譯錯誤,我們需要先定義 Quicksort 函式供測試函式呼叫:
package sort
func Quicksort(s []int) []int {
return s
}
此時執行測試的結果如下:
2.4 把程式碼補充完整,使得它能通過測試
package sort
func Quicksort(s []int) {
if len(s) > 0 {
x := s[0]
i := 0
j := len(s) - 1
for i < j {
for ; i < j; j-- {
if s[j] < x {
s[i] = s[j]
i++
break
}
}
for ; i < j; i++ {
if s[i] > x {
s[j] = s[i]
j--
break
}
}
}
s[i] = x
Quicksort(s[:i])
Quicksort(s[i+1:])
}
}
執行測試,如果測試失敗,根據失敗資訊可以快速定位到出錯位置進行更正,直到通過測試:
2.5 程式碼重構,提高程式碼質量
對過長的快速排序函式進行重構,將其分解為較短的,易理解的,重用性較高的幾個函式:
package sort
func AdjustNum(s []int, x int, i int, j int) (int, int) {
for ; i < j; j-- {
if s[j] < x {
s[i] = s[j]
i++
break
}
}
for ; i < j; i++ {
if s[i] > x {
s[j] = s[i]
j--
break
}
}
return i, j
}
func AdjustSlice(s []int) int {
x := s[0]
i := 0
j := len(s) - 1
for i < j {
i, j = AdjustNum(s, x, i, j)
}
s[i] = x
return i
}
func Quicksort(s []int) {
if len(s) > 0 {
i := AdjustSlice(s)
Quicksort(s[:i])
Quicksort(s[i+1:])
}
}
再次執行測試,確保快速排序函式的功能不發生改變:
2.6 編寫、執行基準測試
基準測試的編寫格式為:
- 檔名必須以 _test.go 結尾;
- 方法名必須是 Test 開頭;
- 方法引數必須是 b *testing.B
按照上面的要求編寫基準測試(將基準測試與單元測試放在同一測試檔案中):
func BenchmarkQuicksort(b *testing.B) {
for i := 0; i < b.N; i++ {
Quicksort([]int{5, 3, 4, 2, 1})
}
}
基準測試的結果為:
相關文章
- 排序演算法-Java實現快速排序演算法排序演算法Java
- 排序演算法之快速排序的實現排序演算法
- 快速排序(quicksort)演算法實現排序UI演算法
- 信用算力實現金融級資料服務的實踐
- python排序演算法的實現-快速排序Python排序演算法
- 快速排序演算法C++實現排序演算法C++
- bash shell 實現快速排序演算法排序演算法
- js實現兩種實用的排序演算法——冒泡、快速排序JS排序演算法
- TDD 實踐-FizzFuzzWhizz(二)
- TDD 實踐-FizzFuzzWhizz(一)
- TDD 實踐-FizzFuzzWhizz(三)
- 快速排序演算法(C語言實現)排序演算法C語言
- GO 實現快速排序Go排序
- 快速排序 java實現排序Java
- Swift實現快速排序Swift排序
- java實現快速排序Java排序
- 快速排序(java實現)排序Java
- 快速排序的實現排序
- 演算法單鏈錶快速排序演算法實現演算法排序
- 二十、快速排序演算法——JAVA實現(遞迴)排序演算法Java遞迴
- python實現氣泡排序、插入排序以及快速排序演算法Python排序演算法
- php實現 歸併排序,快速排序PHP排序
- Semgrep結合GitLab實現程式碼審計實踐-服務端Gitlab服務端
- 快速排序三種實現排序
- python實現快速排序Python排序
- 資料結構和演算法(Golang實現)(25)排序演算法-快速排序資料結構演算法Golang排序
- 微服務實戰:服務發現的可行方案以及實踐案例微服務
- Go實現氣泡排序和快速排序Go排序
- Array.sort 演算法原理(插入排序\快速排序in-place實現)演算法排序
- 服務API版本控制設計與實踐API
- 排序演算法集:冒泡、插入、希爾、快速(陣列實現、連結串列實現)排序演算法陣列
- JavaScript實現標準快速排序JavaScript排序
- Python實現的快速排序Python排序
- 快速排序(Quicksort)的Javascript實現排序UIJavaScript
- golang快速實現服務端網頁截圖Golang服務端網頁
- 用 Go + WebSocket 快速實現一個 chat 服務GoWeb
- 如何快速自建Git服務,實現異地同步?Git
- 排序演算法:Java實現希爾排序排序演算法Java