iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 12
0
Software Development

在Kata中尋找Clean Code是否搞錯了什麼系列 第 12

Day 12 這個方法掛羊頭賣狗肉

相信大家多多少少都有遇過,看到某一段類似下面的代碼。

看上去HasEvenNumber會判斷numbers中是否存在。

if (!HasEvenNumber(numbers))
{
    return 0;
}
return _evenNumbers.Sum();

但是如果移進HasEvenNumber一看可以發現

private bool HasEvenNumber(List<int> numbers)
{
    bool hasEvenNumber = false;
    foreach (var number in numbers)
    {
        if (number % 2 == 0)
        {
            hasEvenNumber = true;
            _evenNumbers.Add(number);
        }
    }
    return hasEvenNumber;
}

HasEvenNumber這個方法做了兩件事情

  1. 判斷是否有偶數
  2. 把偶數加到_evenNumbers

假設其他團隊成員讀到這段代碼,當他看到HasEvenNumber這個名稱,通常會預期這個方法會判斷是否numbers中包含偶數,而不會預期還會把偶數加到_evenNumbers。

如果他在其他地方也需要判斷偶數,他拿著這個方法到處使用,卻發現怎麼程式錯了,除錯除了半天發現_evenNumbers怎麼出現一大堆重複的偶數,在追到原來是HasEvenNumber在搞鬼,此時他的眼白已經佔據了整個眼眶。

所以在抽取方法時,讓方法名稱描述方法的行為是非常重要的事情。以HasEvenNumber為例,可以發現如果想把方法命名精準,會變成HasAndUpdateEvenNumber、HasEvenNumberAndUpdate...之類。

可以發現上面的名字都很長,而且十分難以命名。此時應該就要意識到這個方法做了太多事情了,我們應該要把他拆開,讓他們的功能單一。

private void UpdateEvenNumber(List<int> numbers)
{
    foreach (var number in numbers)
    {
        if (number % 2 == 0)
        {
            _evenNumbers.Add(number);
        }
    }
}

private bool HasEvenNumber(List<int> numbers)
{
    return _evenNumbers.Any(number => true);
}

不論變數名稱或方法名稱,命名時都盡量讓名稱能正確表達他們的內容。維持這個原則之後,當發現名稱非常不好命名時,就會發現這個變數儲存了不同意義的東西或方法做了太多事情,此時就應該思考應該要怎麼調整,而不是埋了一個地雷給隊友。


上一篇
Day 11 抽取方法的時機
下一篇
Day 13 工廠方法
系列文
在Kata中尋找Clean Code是否搞錯了什麼30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言