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

Inline Function

แทนที่การเรียก function เล็ก ๆ ด้วย body ของ function นั้น แล้วลบ function ทิ้ง ใช้ตอนที่ชื่อไม่ได้เพิ่มอะไรจากที่ body บอกชัดอยู่แล้ว

นี่คือวิธีรักษา needless indirection บางที helper เคยมีเหตุผลในอดีต แต่หดเหลือบรรทัดเดียวที่ไม่สำคัญ หรือไม่ชื่อก็แค่พูดซ้ำสิ่งที่ statement เดียวข้างในทำ การไล่ตามชื่อไปยังนิยามที่บอกอะไรไม่มากกว่าจุดที่เรียก คือความเหนื่อยเปล่าของคนอ่าน inline ตัดการกระโดดนั้นทิ้งไป และยังใช้เป็นขั้นตอนล้างบ้านได้ด้วย คือยุบ helper เล็ก ๆ ที่พันกันยุ่งมารวมไว้ที่เดียว แล้วค่อย extract ตามขอบเขตที่ดีกว่าออกมาใหม่

helper ที่แค่ส่งต่อไปยังการตรวจสอบบรรทัดเดียว เพิ่มชั้นขึ้นมาโดยไม่ได้อะไรกลับมา inline ทิ้งไปเลย

// Before
function deliveryFee(driver: Driver): number {
return moreThanFiveTrips(driver) ? 2 : 5;
}
function moreThanFiveTrips(driver: Driver): boolean {
return driver.trips > 5;
}
// After
function deliveryFee(driver: Driver): number {
return driver.trips > 5 ? 2 : 5;
}
  1. เช็กว่า function ไม่เป็น polymorphic เพราะ method ที่ subclass override ไว้ inline ไม่ได้
  2. หาจุดที่เรียกให้ครบ ถ้ามีเยอะให้คิดใหม่ เพราะ inline จะง่ายที่สุดตอนจุดเรียกมีไม่กี่จุด
  3. แทนที่การเรียกแต่ละครั้งด้วยสำเนาของ body แล้วปรับให้เข้ากับ argument จริง
  4. รัน test หลังแทนที่ทุกครั้ง
  5. พอไม่เหลือจุดเรียกแล้ว ก็ลบ function เดิมทิ้ง
  6. รันชุด test ทั้งหมดอีกรอบ เพื่อยืนยันว่าไม่มีใครอ้างถึง function นั้นแล้ว

inline เมื่อ body ชัดเจนอย่างน้อยเท่ากับชื่อ เมื่อกลุ่ม helper ที่จัดโครงสร้างมาไม่ดีควรรวมร่างก่อนแยกใหม่ หรือเมื่อ indirection มาขวางทางคนอ่าน แต่ อย่า inline function ที่ถูกเรียกจากหลายที่ หรือ function ที่ชื่อจับแนวคิดคลุมเครือไว้ได้จริง ๆ เพราะกรณีนั้นชื่อคือเอกสารที่ควรเก็บไว้

ท่าตรงข้ามคือ Extract Function สองท่านี้เป็นคู่หูกัน inline เพื่อยุบโครงสร้างที่ไม่ดี แล้ว extract เพื่อประกอบโครงสร้างที่ดีกว่าขึ้นมาใหม่

ใช้ Inline Function เมื่อหลีกเลี่ยงเมื่อ
ชื่อ function ไม่ได้บอกอะไรมากกว่า bodyfunction ถูกใช้งานหลายที่
function แค่ delegate ต่อไปยังอีก functionbody ซับซ้อนกว่าชื่อ — ชื่อยังมีประโยชน์
กำลังจัดระเบียบใหม่ และอยากรวม logic ก่อนแบ่งใหม่ต้อง override ใน subclass

⚠️ ไม่ควร Inline Function เมื่อ:

  • function นั้นซ่อน complexity จริง ๆ — inline แล้ว code จะอ่านยากขึ้น
  • เป็น API ที่ external caller ใช้อยู่
  • ต้องใช้ trace ตอน debug — ชื่อ function ช่วยให้อ่าน stack trace ออก
ควรใช้ Inline Function ตอนไหน?
Inline Function เป็นท่าตรงข้ามของ refactoring แบบใด?
ทำไมบางครั้งถึงจงใจ inline helper หลายตัวก่อนทำอย่างอื่น?