霍爾筆記

Clean functions and classes

約 509 字 --

在讀 Clean Code 的時候,我覺得最讓我印象深刻的就屬 Functions 了。究竟要怎麼樣把 Function 寫得乾淨?我之前一直沒有仔細思考過,可能知道要單一職責、命名清晰,但要把 Function 寫的「夠小」,我還真的沒這麼想過。

小,還要更小

把 Function 寫小有一些明顯的好處,就有點像是文章中的句號、換行般,閱讀時斷點前的資訊會被暫存在大腦中,一個段落結束後喘口氣,稍微消化一下讀過內容,再往下一段去。

也就是說,如果一個 Function 長度有幾十行,甚至上百行,閱讀的壓力就會增加。那麼,怎麼樣的 Function 才稱「小」呢?

function isEmpty(value) {
  if (value == null) {
    return true;
  }
  if (
    isArrayLike(value) &&
    (Array.isArray(value) ||
      typeof value === "string" ||
      typeof value.splice === "function" ||
      isBuffer(value) ||
      isTypedArray(value) ||
      isArguments(value))
  ) {
    return !value.length;
  }
  const tag = getTag(value);
  if (tag == "[object Map]" || tag == "[object Set]") {
    return !value.size;
  }
  if (isPrototype(value)) {
    return !Object.keys(value).length;
  }
  for (const key in value) {
    if (hasOwnProperty.call(value, key)) {
      return false;
    }
  }
  return true;
}

這樣的 Function 夠簡潔嗎?以上節錄 lodash 這個 library 的 isEmpty.js

總共 27 行(原檔案 20 出頭,這裡是 format 過後的檔案),雖然不算少,但也不算太長了吧?但以作者的標準來看,這樣的 size 其實很大!如果我們稍微改寫一下呢,把這個 Function 拆開來組裝。

function isEmpty(value) {
  ...
  if (isArrayLike(value) && isTypeHasLengthProp(value)) {
    return !value.length;
  }
  ...
}

我們將 Array.isArray(value) || typeof value === 'string' 等等的一連串判斷式簡化成一個 Function(這樣命名不一定精確,但概念是簡化多個表達式成一個 Function),如此一來,在可讀性上就會好上一些。

更簡化一些,可以將 if, for, while 等結構直接轉換成 Function。如果能將程式碼縮減到個位數的行數,會大大的降低看一次段落的壓力,需要細節的時候,讀者再往更深入的 Function 去看就好。

(未完待續)

參考資料

  1. GitHub loadash - isEmpty.js
Clean Code