Extract Function

練習用的 REPL

抽取時,若沒有任何變數會跑出 Scope,可以直接處理。

// Owing 欠款 function printOwing(invoice) { let outstanding = 0; console.log("***********************"); console.log("**** Customer Owes ****"); console.log("***********************"); // calculate outstanding(未清帳款) for (const o of invoice.orders) { outstanding += o.amount; } // record due date const today = Clock.today; invoice.dueDate = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 30); // 別這樣做 // print details console.log(`name: ${invoice.customer}`); console.log(`amount: ${outstanding}`); console.log(`due: ${invoice.dueDate.toLocaleDateString()}`); }
function printOwing(invoice) { let outstanding = 0; printBanner(); // 先把畫 banner 的任務抽出來 // calculate outstanding for (const o of invoice.orders) { outstanding += o.amount; } // record due date const today = Clock.today; invoice.dueDate = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 30); // print details console.log(`name: ${invoice.customer}`); console.log(`amount: ${outstanding}`); console.log(`due: ${invoice.dueDate.toLocaleDateString()}`); } function printBanner() { // 這裡不是 nested function console.log("***********************"); console.log("**** Customer Owes ****"); console.log("***********************"); }

試著把註解內 print details 的部分都取出來。

function printOwing(invoice) { let outstanding = 0; printBanner(); // calculate outstanding for (const o of invoice.orders) { outstanding += o.amount; } // record due date const today = Clock.today; invoice.dueDate = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 30); printDetails(); function printDetails() { // 把印出 details 的任務再抽出來,這邊是 nested function,可以直接取用所有變數 console.log(`name: ${invoice.customer}`); console.log(`amount: ${outstanding}`); console.log(`due: ${invoice.dueDate.toLocaleDateString()}`); } } function printBanner() { // 這裡不是 nested function console.log("***********************"); console.log("**** Customer Owes ****"); console.log("***********************"); }

也可以直接傳遞變數

function printOwing(invoice) { let outstanding = 0; printBanner(); // calculate outstanding for (const o of invoice.orders) { outstanding += o.amount; } // record due date const today = Clock.today; invoice.dueDate = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 30); printDetails(invoice, outstanding); } function printDetails(invoice, outstanding) { // 不是 nested-function,需要傳遞參數 console.log(`name: ${invoice.customer}`); console.log(`amount: ${outstanding}`); console.log(`due: ${invoice.dueDate.toLocaleDateString()}`); }

有時候,需要處理一下變數才能抽取。

function printOwing(invoice) { let outstanding = 0; printBanner(); // calculate outstanding for (const o of invoice.orders) { outstanding += o.amount; } recordDueDate(invoice); printDetails(invoice, outstanding); }
function printOwing(invoice) { printBanner(); // calculate outstanding let outstanding = 0; // 換位子,方便抽取成 function for (const o of invoice.orders) { outstanding += o.amount; } recordDueDate(invoice); printDetails(invoice, outstanding); }
function printOwing(invoice) { printBanner(); // calculate outstanding let outstanding = 0; for (const o of invoice.orders) { outstanding += o.amount; } recordDueDate(invoice); printDetails(invoice, outstanding); } function calculateOutstanding(invoice) { // 經過 slide statement 後,可以整塊複製貼上 let outstanding = 0; for (const o of invoice.orders) { outstanding += o.amount; } return outstanding; }
function printOwing(invoice) { printBanner(); let outstanding = calculateOutstanding(invoice); // 把程式碼換成 function recordDueDate(invoice); printDetails(invoice, outstanding); } function calculateOutstanding(invoice) { let outstanding = 0; for (const o of invoice.orders) { outstanding += o.amount; } return outstanding; }
function printOwing(invoice) { printBanner(); const outstanding = calculateOutstanding(invoice); // 改成 const,避免被意外重新賦值 recordDueDate(invoice); printDetails(invoice, outstanding); } function calculateOutstanding(invoice) { let result = 0; // 命名成 result 是 Martin Fowler 的習慣 for (const o of invoice.orders) { result += o.amount; } return result; }