ข้ามไปยังเนื้อหา

Replace Temp with Query

เอาตัวแปร local ที่รับค่าจากการคำนวณครั้งเดียวแล้วอ่านอย่างเดียว มาแทนด้วย function ที่คำนวณค่านั้นให้ (เรียกกันว่า “query”) ทุกจุดที่เคยใช้ temp ก็เปลี่ยนไปเรียก query แทน

นี่คือวิธีรักษาอาการ temp ตรึง logic ไว้กับที่ temporary variable ล็อกการคำนวณไว้ใน function เดียว คุณเอาผลลัพธ์ไปใช้ซ้ำที่อื่นไม่ได้ และจะ Extract Function ครอบ code ที่พึ่ง temp นั้นก็ไม่ได้ ถ้าไม่ลาก temp ตามไปเป็น parameter การเปลี่ยน temp ให้เป็น query ปลดล็อกการคำนวณนั้นออกมา ท่านี้มีค่าที่สุดในฐานะขั้น เตรียมพร้อม พอค่ากลายเป็น method แล้ว การ extract ก้อนใหญ่กว่าก็หลุดออกมาได้สะอาด

basePrice เป็น temp ที่คำนวณครั้งเดียวแล้วอ่านสองครั้ง เลื่อนขั้นขึ้นเป็น query method บน order ไปเลย

// Before
class Order {
constructor(private quantity: number, private itemPrice: number) {}
finalPrice(): number {
const basePrice = this.quantity * this.itemPrice;
const discount = Math.max(this.quantity - 100, 0) * this.itemPrice * 0.1;
return basePrice - discount;
}
}
// After
class Order {
constructor(private quantity: number, private itemPrice: number) {}
private basePrice(): number {
return this.quantity * this.itemPrice;
}
private discount(): number {
return Math.max(this.quantity - 100, 0) * this.itemPrice * 0.1;
}
finalPrice(): number {
return this.basePrice() - this.discount();
}
}
  1. เช็คว่า temp กำหนดค่าครั้งเดียวและไม่โดน mutate หลังจากนั้น ถ้ามีการกำหนดค่าใหม่ ให้แยกตัวแปรก่อน แต่ละค่าจะได้กำหนดที่เดียว
  2. ยืนยันว่าการคำนวณฝั่งขวาไม่มี side effect
  3. extract การคำนวณออกมาเป็น query function (ถ้าข้อมูลอยู่บน object ก็ทำเป็น method)
  4. แทนทุกจุดที่อ่าน temp ด้วยการเรียก query
  5. รัน test หลังแทนแต่ละจุด
  6. ลบบรรทัดประกาศ temp ที่ไม่มีใครใช้แล้วทิ้ง

ใช้ท่านี้เมื่อ temp ขวาง Extract Function ที่คุณอยากทำ เมื่อการคำนวณเดียวกันมีประโยชน์กับหลาย method หรือแค่อยากลด local state ของ method ยาว ๆ ข้อแลกเปลี่ยนหลักคือการคำนวณซ้ำ เพราะ query อาจคำนวณใหม่ทุกครั้งที่เรียก สำหรับ business logic ทั่วไปแทบไม่มีผล และความชัดเจนที่ได้ก็คุ้ม ส่วน hot path จริง ๆ ให้วัดก่อนตัดสินใจ

ทิศทางกลับกันคือ cache ค่าไว้ใน local อีกครั้ง เมื่อ profiling พิสูจน์แล้วว่า query เป็นคอขวดจริง แต่หยิบทางนี้มาใช้ก็ต่อเมื่อมีหลักฐานเท่านั้น

ใช้ Replace Temp with Query เมื่อหลีกเลี่ยงเมื่อ
temporary variable ใช้หลายครั้งใน functionquery แพง — เรียกซ้ำหลายครั้งแล้วช้า
ต้องการ extract function ที่ใช้ค่านั้นtemporary variable คือ accumulator ที่ค่าเปลี่ยนใน loop
ค่านั้นต้องการใน subclassfunction ที่ได้จะมีชื่อที่อธิบายแย่กว่า variable เดิม

⚠️ ไม่ควร Replace Temp with Query เมื่อ:

  • calculation มี side effect — เรียกซ้ำจะทำงานหลายครั้ง
  • ค่านั้นซับซ้อนและเรียกบ่อย — cache ไว้ใน variable ดีกว่า
  • context object ไม่มีข้อมูลที่จำเป็นสำหรับ query
Replace Temp with Query แทนที่ตัวแปร local ด้วยอะไร?
temp ต้องผ่านเงื่อนไขใดก่อนใช้ refactoring นี้?
ทำไม refactoring นี้จึงมักใช้เป็นขั้นเตรียมพร้อม?