把一段程式碼抽成獨立函式,用一個好名字描述它「做什麼」。這是最常用、也最基礎的重構——多數其他手法都從它長出來。
🧠 Why It's a Problem
抽取的判準不是「程式碼夠長」,而是 意圖與實作的距離:當你得讀完一整段才搞懂它在幹嘛,就把那段封進一個名字。
- 看到一段需要註解解釋的程式碼 → 註解的內容通常就是函式名。
- 同一段邏輯出現第二次 → 抽取後消除重複(DRY)。
- 一個函式裡混了不同抽象層級(高層流程 + 低層位元運算)→ 抽取把它們拉平。
TIP
Fowler 的立場:只要命名能讓意圖更清楚,即使函式只有一行也值得抽。 函式的價值在「以名代義」,不在省行數。
⚖️ Refactoring
機械步驟:① 建新函式、用「意圖」命名 → ② 把選取片段複製過去 → ③ 處理區域變數(成為參數或回傳值)→ ④ 原處改成呼叫 → ⑤ 測試。
前 — 意圖埋在細節裡
function priceOrder(product, quantity) {
const basePrice = product.basePrice * quantity;
const discount =
Math.max(quantity - product.discountThreshold, 0) *
product.basePrice * product.discountRate;
const shipping = Math.min(basePrice * 0.1, 100);
return basePrice - discount + shipping;
}讀者得逐行算才知道「價格 = 底價 − 折扣 + 運費」。
後 — 每個概念有名字
function priceOrder(product, quantity) {
const basePrice = product.basePrice * quantity;
const discount = discountFor(product, quantity);
const shipping = shippingFor(basePrice);
return basePrice - discount + shipping;
}
function discountFor(product, quantity) {
return Math.max(quantity - product.discountThreshold, 0) *
product.basePrice * product.discountRate;
}
function shippingFor(basePrice) {
return Math.min(basePrice * 0.1, 100);
}主函式現在直接讀作公式本身;折扣和運費規則各自獨立,將來改規則只動一處。
WARNING
反向手法是 Inline Function:當函式本體已和名字一樣清楚、或一層間接反而礙事時,把它合回去。抽取不是越多越好——目標是清晰,不是數量。
🔑 Takeaways
- Extract Function 的本質是替一段邏輯命名,把「做什麼」與「怎麼做」分層。
- 觸發訊號:需要註解、出現重複、抽象層級混雜。
- 一行也能抽——只要名字讓意圖更清楚。
- 過猶不及時用 Inline Function 回收多餘的間接層。
- 它是 長函式 的標準解,也是許多進階重構的第一步。
No notes yet — jot your takeaways or Q&A here.