長函式 (Long Function)

★★★★★Reviewed

FromRefactoringClean CodeCode Complete

📚 From the Books

長函式 (Long Function)Code Smells

函式越長,要讀懂它、安全地改它就越難。長度本身不是病,「為了理解它必須在腦中同時裝下太多細節」才是。最該被抽出來的,往往就是那些你得停下來寫一行註解解釋的片段。

🧠 Why It's a Problem

NOTE

判準不是「行數超過 N 就是壞」,而是 Fowler 的提問:這段程式碼在做什麼? 只要答案需要一個「而且…」,它大概就承擔了不只一件事。

⚖️ Refactoring

核心解法幾乎永遠是 Extract Function:把「做什麼(意圖)」和「怎麼做(細節)」分到不同層。

前 — 一個函式做完所有事
function printOwing(invoice) {
  let outstanding = 0;

  console.log('***********************');
  console.log('**** Customer Owes ****');
  console.log('***********************');

  for (const o of invoice.orders) {
    outstanding += o.amount;
  }

  const today = new Date();
  invoice.dueDate = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 30);

  console.log(`name: ${invoice.customer}`);
  console.log(`amount: ${outstanding}`);
  console.log(`due: ${invoice.dueDate.toLocaleDateString()}`);
}
後 — 用具名函式描述意圖
function printOwing(invoice) {
  printBanner();
  const outstanding = calculateOutstanding(invoice);
  recordDueDate(invoice);
  printDetails(invoice, outstanding);
}

function printBanner() {
  console.log('***********************');
  console.log('**** Customer Owes ****');
  console.log('***********************');
}

function calculateOutstanding(invoice) {
  return invoice.orders.reduce((sum, o) => sum + o.amount, 0);
}

function recordDueDate(invoice) {
  const today = new Date();
  invoice.dueDate = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 30);
}

function printDetails(invoice, outstanding) {
  console.log(`name: ${invoice.customer}`);
  console.log(`amount: ${outstanding}`);
  console.log(`due: ${invoice.dueDate.toLocaleDateString()}`);
}

printOwing 現在讀起來像一段摘要:四個步驟、四個名字。細節各自退到自己的函式裡,需要時才展開。

🔑 Takeaways

✍️ My Notes

No notes yet — jot your takeaways or Q&A here.

📖 Further Reading