上回邀請朋友一起來進行 pair programming,隨機挑了一個 Codewars 的題目來練習:Mumbling。
題目描述:
例如:s 為 "cwAT", 期望回傳值為 "C-Ww-Aaa-Tttt"
【新增測試代碼】s_is_b_should_return_B()
ToUpper()
轉大寫後回傳【生產代碼】
【重構測試代碼】封裝 assertion 行為,AccumShouldBe()
【測試代碼】
s[0]
與 s[1]
轉大寫與連接號串接【生產代碼】
【重構生產代碼】將 char 呼叫 ToString()
與 ToUpper()
重構,擷取方法至 ToUpperChar()
【新增測試代碼】
【調整生產代碼】增加 ToLower()
處理,以通過測試案例
【重構生產代碼】重構擷取方法,將 char 轉成小寫也封裝成 ToLowerChar()
【新增測試代碼】
【調整生產代碼】hard-code 處理 s[2]
的部分,等等再來重構商業邏輯
【重構生產代碼】使用 GetRepeatLetters()
取代原本 hard-code 的重複字母
【重構生產代碼】使用 Loop 取代 s[0]
, s[1]
, s[2]
hard-code index
【重構生產代碼】以 LINQ 的 Aggregate()
取代 for loop 不斷串接 result 的邏輯。
【重構生產代碼】將每個 char 透過 Select()
轉成對應的重複字串,再用連接號連接每個 element
public class Accumul
{
public static String Accum(string s)
{
var result = s.Select((c, i) => ToUpperChar(c) + GetRepeatLetters(c, i));
return string.Join("-", result);
}
private static string GetRepeatLetters(char letter, int repeatTimes)
{
return string.Concat(Enumerable.Repeat(letter.ToString().ToLower(), repeatTimes));
}
private static string ToUpperChar(char letter)
{
return letter.ToString().ToUpper();
}
}
結論
同樣的題目,練習不只一次,有時思路會很不一樣。這一題 Codewars 一開始其實是三個人以 TDD 一起做 coding dojo 的過程,我們最後一起完成了這一題,但我當天晚上重新練習了一次,讓整個過程更貼近精簡的 TDD 堆砌出生產代碼。
附上兩個版本的 commit history 供各位朋友參考:
生產代碼的主邏輯最後其實可以一行代碼就搞定,但 TDD 延展出來的思路還是本文練習的重點,而且可以看到每一行都是其來有自,為了滿足某個需求而驅動出來的代碼。
blog 與課程更新內容,請前往新站位置:http://tdd.best/