要讓軟體具備模組特質,相關的元素得待在一起。這件事會動態發生:越了解要做的事,就越知道該如何妥善聚集元素。持續地聚集,正顯示我們的理解在持續提升。
🧠 Why It's a Problem
一個函式若一直在存取「別人家」的資料,它其實住錯了地方。當它參考其他環境元素的量大於當前環境時,就該搬過去——這通常能改善封裝。
- 函式參考別的環境較多:它用到目標類別的資料,多過用到自己現在所在類別的資料。
- 搬動能改善封裝:把行為挪到資料旁邊,減少跨環境的存取與暴露。
TIP
Fowler 提醒:這個決定不容易,而越難決定的搬動,往往越不重要——若兩邊看起來都合理,那多半怎麼放差別都不大,別為此糾結太久。
⚖️ Refactoring
機械步驟:① 檢查函式在原環境用到的所有元素,判斷是否也該一起搬 → ② 把函式複製到目標環境、調整成貼合新家(存取改為 this) → ③ 讓原處委託給新函式或直接更新呼叫端 → ④ 測試 → ⑤ 移除原函式。
前 — send_email 住在 Employee 外面
class Employee {
constructor(name, email) {
this.name = name;
this.email = email;
}
printEmployeeDetails() {
console.log(`Name: ${this.name}, Email: ${this.email}`);
}
}
function sendEmail(employee, message) {
console.log(`Sending email to ${employee.email} with message: '${message}'`);
}
const employee = new Employee('John Doe', 'john@example.com');
sendEmail(employee, 'Welcome to the team!');sendEmail 只靠 employee.email 運作——它參考的全是 Employee 的資料,卻住在外面。
後 — 把它搬進 Employee
class Employee {
constructor(name, email) {
this.name = name;
this.email = email;
}
printEmployeeDetails() {
console.log(`Name: ${this.name}, Email: ${this.email}`);
}
sendEmail(message) {
console.log(`Sending email to ${this.email} with message: '${message}'`);
}
}
const employee = new Employee('John Doe', 'john@example.com');
employee.sendEmail('Welcome to the team!');函式搬到資料旁邊,email 參數消失、改用 this.email。行為與它依賴的資料終於同住,封裝更緊。
NOTE
當你發現「該一起搬的其實是一整群資料加方法」,那已經是 Extract Class 的場景了——Move Function 是它的組成步驟之一。
🔑 Takeaways
- Move Function 把函式搬到它最常參考的那個環境,讓行為與資料同住。
- 觸發訊號:函式用到別的環境的元素,多過用到自己所在環境。
- 好處:改善封裝、讓模組的相關元素聚在一起。
- 難以抉擇的搬動通常不重要,別過度糾結。
- 常作為 Extract Class 的組成步驟。
No notes yet — jot your takeaways or Q&A here.