最近這段時間,我嘗試用TDD的方式來解了幾道算法題。其間頗有一些感觸,希望通過這個死磕系列的文章做個小結。
為什么
有個廣為流傳的說法:TDD不適合解決算法問題。
對此我一直是存疑的,機緣湊巧就親身驗證了一下,動機不外乎以下幾條:
- 作為TDD粉絲,難免會“不服氣”,總想證明自己喜歡的方法有更廣的應用范圍,更大的效力。
- 另有一種常見的說法,“我不會所有代碼都寫測試,因為大部分代碼都太簡單不值得測。只有核心的邏輯復雜的代碼才需要單元測試或TDD”。按照這種標準,涉及算法的代碼自然是復雜的。如果兩條都認同,基本上等于說TDD沒有什么適用的地方了。
- 現(xiàn)實工作中的問題不會在自己頭上貼張“我是算法問題”的標簽。即便真的TDD不適合算法,至少也應該嘗試找出一些經驗法則去察覺目前的問題需要改變方法。
特別是如果嚴格執(zhí)行TDD三法則的話,讓我們回顧一下三法則:
a. 在編寫失敗的測試前,不能編寫實現(xiàn)代碼;
b. 只編寫恰好能失敗的測試;
c. 只編寫恰好能通過測試的實現(xiàn)代碼;
可以看到整個步驟是按部就班,環(huán)環(huán)相扣,嚴格覆蓋所有代碼的。假定開發(fā)者真的接受這套方法,并且前面也進展順利??偛荒艿鹊揭徊讲缴钕菽嗵读瞬庞腥诉^來說:“bingo,這是個算法問題,不適合用TDD”。
這相當于司機跟著語言導航駕駛,結果不知不覺掉入坑里。然后卻去責怪他,“這段路的導航工作不正常,你怎么不停下來問問人啊?”完全是不負責任的說法。 - 雖然有相當數(shù)量的Kata可以作為TDD的練習題目。有時候我還是稍有懷疑這些Kata是不是因為恰巧適合TDD而被選中的。所以也想用具有一定挑戰(zhàn)的算法題目來驗證用這種方式對解決問題的幫助有多大。

導航
怎么開始的
因為一直有這個念頭,在今年初偶然看到@東東 同學組織的“每日一題”群時就加了進去。
每日一道算法題
軟廣一下
每日一題是個專注于刷題練習算法的社群。每天早晨群主大人都會準時喂一道算法題給嗷嗷待哺的碼農,每周有主題,定期有回顧,時不時還有直播講解。
有志于學習算法,或者準備刷題找工作的同學。都可以搜索微信公眾號“每日一道算法題”加入。
群里小伙伴都很厲害,往往一道題貼出來半個小時就有答案貼出來了。我是屬于“別有用心”加入的,并不為了學習某個具體算法,而是看到順眼題目就試試怎么在沒有思路的情況下解決掉它。常常一道題斷斷續(xù)續(xù)反復一兩個星期。還好有這么個大部隊,三天打魚兩天曬網的也還不至于完全扔下。
一點心得
本文只是個開篇,這里只是泛泛而談。具體的心得可能結合題目實踐過程才能完全說清。

爬出來
- 收集了很多失敗。
雖然預料到不是那么容易,但是碰到的失敗還是超出了預期。網上可見的TDD的例子中大多是怎么成功解決問題的。很少有失敗的例子。失敗而又不是用來證明TDD沒用處的例子就更少了。
我在練習中,明顯的感覺到了Uncle bob稱之為“僵局”的模式。和同好交流時我們也會稱作“掉坑”里去了??梢哉f,沒有掉進坑里并爬出來的經歷,基本還沒有真的開始采用TDD。
從這個角度而言,展示具體的“掉坑”經歷,并復盤分析有它特有的價值。 - TDD是更有條理的進行開發(fā)的方法,解決的是編碼活動帶來的額外復雜度,而不是解決問題本身。
換句話說,TDD是幫助你綁緊鞋帶以免跑起來的時候絆倒自己,但是并不會讓你從不會跑步變得會飛。
更多還是后面具體例子細說吧
練習回顧
目前總結了兩道題目,第一篇特意詳細描述了失敗的經過。
[TDD磕算法] 排排隊,吃果果(一)失敗嘗試
[TDD磕算法] 排排隊,吃果果(二)先實現(xiàn)再優(yōu)化
[TDD磕算法]排排隊,吃果果(三)優(yōu)化效率
