[TDD][Codewars] Mumbling

上回邀請朋友一起來進行 pair programming,隨機挑了一個 Codewars 的題目來練習:Mumbling

題目描述:

【題目說明】給一個字串 s, 將第 n 個字母,重複 N 次,並用 "-" 串接起來。每個字母重複 N 次的第一次要轉成大寫,其他的要轉成小寫。

例如:s 為 "cwAT", 期望回傳值為 "C-Ww-Aaa-Tttt"

Step 1, 新增測試案例,s 長度為 1,結果應轉大寫 

【新增測試代碼】s_is_b_should_return_B()

Step 2, hard-code 實作生產代碼,針對第一個字母 ToUpper() 轉大寫後回傳

【生產代碼】

【重構測試代碼】封裝 assertion 行為,AccumShouldBe()

Step 3, 新增測試案例,s 長度為 2,應處理第二個字母重複 2 次,第一次轉大寫,並使用連接號相加

【測試代碼】

Step4, hard-code 處理 s[0]s[1] 轉大寫與連接號串接

【生產代碼】

【重構生產代碼】將 char 呼叫 ToString()ToUpper() 重構,擷取方法至 ToUpperChar()

Step 5, 新增測試案例,s 長度仍為 2,但 s 第二個字母為大寫。在重複時,應該轉為小寫。

【新增測試代碼】

【調整生產代碼】增加 ToLower() 處理,以通過測試案例

【重構生產代碼】重構擷取方法,將 char 轉成小寫也封裝成 ToLowerChar()

Step 6, 新增測試案例, s 長度為 3

【新增測試代碼】

【調整生產代碼】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 供各位朋友參考:

  1. 3 人 coding dojo 版本的 commit history
  2. 本文 TDD 過程的 commit history 版本

生產代碼的主邏輯最後其實可以一行代碼就搞定,但 TDD 延展出來的思路還是本文練習的重點,而且可以看到每一行都是其來有自,為了滿足某個需求而驅動出來的代碼。

這一道 kata 題目實在是相當單純,不論是拿來練習 LINQ to Objects 或是 TDD 或是 coding dojo 的重構與 pair programming,都單純到挺合適的。而且隨時可以進行「需求異動」來增加變化與難度,推薦給大家。

對敏捷開發有興趣的朋友,可以參考我的粉絲專頁:91敏捷開發之路

若需要聯絡我,可以透過粉絲專頁私訊或是側欄的關於我。