ทำไมเราต้องปรับโครงสร้างโค้ดก่อนย้ายระบบ
เวลาทีมตัดสินใจจะย้าย Legacy Application (แอปพลิเคชันเก่าที่เขียนมานานแล้ว) ไปใช้เทคโนโลยีใหม่ มักจะมีแรงกดดันให้รีบย้ายโค้ดทันที เราอาจอยากย้ายฐานข้อมูล ย้าย API (ช่องทางเชื่อมต่อระหว่างแอป) หรือเปลี่ยนหน้าตาเว็บใหม่หมด แต่นี่เป็นจุดที่อันตรายมาก เพราะระบบเดิมมักรวมทุกอย่างไว้ในที่เดียว ทั้งกฎธุรกิจ การเก็บข้อมูล และการสื่อสารกับภายนอก
ลองนึกภาพว่าคุณกำลังจะย้ายบ้าน แต่ข้าวของทั้งหมดถูกวางกองรวมกันจนแยกไม่ออกว่าชิ้นไหนเป็นของใช้ส่วนตัว ชิ้นไหนเป็นของตกแต่งบ้าน ถ้าคุณพยายามยกไปทั้งกอง บ้านใหม่ของคุณก็จะรกเหมือนเดิม การ Refactor (การปรับปรุงโครงสร้างโค้ดโดยไม่เปลี่ยนการทำงาน) ก่อนย้าย จะช่วยให้เราแยกส่วนประกอบที่พันกันยุ่งเหยิงออกมาได้ ทำให้การย้ายระบบทำได้ง่ายและปลอดภัยขึ้นมาก
เป้าหมายไม่ใช่การทำให้โค้ดเก่าสวยงามสมบูรณ์แบบ แต่คือการทำให้โครงสร้างมัน "ขยับได้" โดยไม่พัง การทำแบบนี้จะช่วยประหยัดเวลาในระยะยาว เพราะเราจะค่อย ๆ ย้ายทีละส่วน (Incremental Migration) แทนที่จะต้องรื้อระบบทั้งหมดพร้อมกัน ซึ่งมีความเสี่ยงสูงที่จะเกิดข้อผิดพลาดจนระบบใช้งานไม่ได้
เลือกขอบเขตการย้ายให้ชัดเจน
ก่อนจะเริ่มลงมือแก้โค้ด อย่าเพิ่งคิดว่าจะแก้ทั้งโครงการ ให้เริ่มจากคำถามว่าเราจะย้ายส่วนไหนก่อน เช่น เราอาจเลือกย้ายระบบ Process Order (การจัดการคำสั่งซื้อ) เป็นอันดับแรก การกำหนดขอบเขตแบบนี้ช่วยให้เรารู้ว่า อะไรคือข้อมูลเข้า อะไรคือสิ่งที่ต้องทำ และอะไรคือผลลัพธ์ที่ต้องการ
มือใหม่มักพลาดด้วยการพยายามแก้ไฟล์ทั้งหมดในโปรเจกต์ ซึ่งทำให้หลงทางและเสียเวลาโดยใช่เหตุ ให้ลองวาดแผนภาพง่าย ๆ ว่าในส่วนที่เราจะย้าย มีการคุยกับฐานข้อมูลหรือบริการอื่นอย่างไรบ้าง การยึดตาม Capability (ความสามารถหรือฟังก์ชันการทำงานของระบบ) จะทำให้คุณเห็นภาพชัดกว่าการไล่แก้ไปตามชื่อโฟลเดอร์
เมื่อได้ขอบเขตแล้ว คุณต้องมีวิธีตรวจสอบว่าสิ่งที่คุณทำไม่ทำให้ระบบพัง วิธีที่ดีที่สุดคือการมี Characterization Tests (ชุดทดสอบที่เขียนไว้เพื่อระบุพฤติกรรมเดิมของระบบ) ถ้าคุณไม่มีการทดสอบเหล่านี้ การแก้โค้ดจะเหมือนการเดินในความมืด เพราะคุณไม่มีทางรู้เลยว่าคุณไปทำอะไรพังเข้าหรือเปล่า
แยกกฎธุรกิจออกจากโครงสร้างพื้นฐาน
โค้ดในระบบเก่ามักมีปัญหาคือ "กฎการคำนวณเงิน" ไปนอนรวมอยู่กับ "คำสั่งฐานข้อมูล" ทำให้เราไม่สามารถทดสอบหรือย้ายเฉพาะส่วนการคำนวณได้ การแยก Business Rules (กฎเกณฑ์หรือเงื่อนไขทางธุรกิจ) ออกจาก Infrastructure (ส่วนประกอบทางเทคนิค เช่น ฐานข้อมูลหรือเซิร์ฟเวอร์) คือหัวใจสำคัญของการเตรียมย้ายระบบ
ลองดูตัวอย่างโค้ดแบบเดิมที่รวมทุกอย่างไว้ด้วยกัน:
// โค้ดแบบเดิมที่รวมทุกอย่างไว้ในที่เดียว
async function processOrder(orderId) {
const order = await db.query("SELECT * FROM orders WHERE id = ?", [orderId]);
// กฎธุรกิจปนกับคำสั่งฐานข้อมูล
if (order.type === "PREMIUM") {
order.total = order.total * 0.9;
}
await db.query("UPDATE orders SET total = ? WHERE id = ?", [order.total, order.id]);
}
จากตัวอย่างข้างต้น บรรทัดที่ 3 คือการดึงข้อมูลจากฐานข้อมูล ส่วนบรรทัดที่ 5-7 คือกฎการคิดราคา ถ้าเราต้องการย้ายไปใช้ฐานข้อมูลใหม่ เราต้องแก้โค้ดทั้งหมด ซึ่งเสี่ยงมาก
ผลลัพธ์ที่ควรเห็นคือ เราควรแยกฟังก์ชัน calculateTotal ออกมาต่างหาก เพื่อให้มันรับค่ามาคำนวณแล้วส่งค่ากลับไป โดยไม่ต้องสนว่าข้อมูลนั้นมาจากฐานข้อมูลแบบไหน
สร้างช่องว่างให้ระบบด้วยการทำ Seams
Seams (จุดรอยต่อหรือช่องว่างที่เราสร้างขึ้นในโค้ด) คือเทคนิคการแทรกแซงโค้ดเพื่อให้เราสามารถเปลี่ยนพฤติกรรมบางอย่างได้โดยไม่ต้องแก้โค้ดเดิมทั้งหมด เปรียบเหมือนการติดตั้งสวิตช์ไฟไว้กลางสายไฟ เพื่อให้เราเปิด-ปิดไฟได้โดยไม่ต้องรื้อระบบสายไฟในผนังบ้านออกมาใหม่ทั้งหมด
ในการเขียนโปรแกรม เรามักใช้ Dependency Injection (การส่งสิ่งที่จำเป็นต้องใช้เข้าไปในฟังก์ชันแทนที่จะสร้างขึ้นมาข้างใน) เพื่อสร้างจุดรอยต่อเหล่านี้ วิธีนี้ช่วยให้เราสามารถส่ง "ตัวจำลอง" เข้าไปแทนของจริงได้ในระหว่างการทดสอบ ทำให้เราไม่ต้องเชื่อมต่อกับฐานข้อมูลจริงทุกครั้งที่รันโค้ด
มือใหม่มักจะลืมไปว่าการทำ Seams ไม่จำเป็นต้องสมบูรณ์แบบตั้งแต่แรก แค่สร้างจุดตัดให้เราสามารถแยกการทำงานออกเป็นส่วน ๆ ได้ก็เพียงพอแล้ว อย่าพยายามทำระบบ Dependency Injection ที่ซับซ้อนเกินความจำเป็น ให้เริ่มจากจุดที่ง่ายที่สุดที่ทำให้คุณทดสอบโค้ดได้ก็พอ
ใช้ AI ช่วยอย่างมีสติ
การใช้เครื่องมือ AI ในการช่วย Refactor เป็นเรื่องดี แต่ต้องระวังอย่าให้มันออกแบบสถาปัตยกรรมใหม่ทั้งหมดให้คุณโดยที่คุณไม่ได้ตรวจสอบ เพราะ AI อาจจะเสนอวิธีที่ดูดีในทางทฤษฎี แต่ใช้งานจริงในระบบเก่าไม่ได้ หรือสร้างความซับซ้อนใหม่ที่คุณไม่เข้าใจวิธีแก้ไข
กฎเหล็กคือ อย่าถาม AI ว่า "ช่วยออกแบบระบบใหม่ให้หน่อย" แต่ให้ถามว่า "ช่วยแยกฟังก์ชันนี้ออกจากฐานข้อมูลที" หรือ "ช่วยสร้าง Unit Test (การทดสอบโค้ดในระดับฟังก์ชันย่อย) ให้กับโค้ดชุดนี้หน่อย" การให้ AI ทำงานเฉพาะจุดจะช่วยลดความเสี่ยงจากการหลงทางได้ดีที่สุด
จงจำไว้ว่าคุณคือคนคุมเกม AI เป็นเพียงผู้ช่วยที่ทำตามคำสั่ง ถ้าผลลัพธ์ที่ได้ดูแปลกหรือซับซ้อนเกินไป ให้หยุดและทบทวนทันที อย่ากดรับโค้ดที่ AI เขียนให้โดยไม่อ่าน เพราะถ้ามันพัง คุณจะเป็นคนเดียวที่ต้องนั่งแก้ในภายหลัง
สรุป: การเตรียมตัวคือหัวใจของการย้ายระบบ
การย้ายระบบไม่ใช่แค่เรื่องของเทคโนโลยี แต่เป็นเรื่องของการจัดการความเสี่ยง การทำ Refactoring ก่อนย้ายจะทำให้คุณมีโอกาสเห็นปัญหาที่ซ่อนอยู่ และแก้ไขมันได้ทีละจุด การมี Characterization Tests คอยคุ้มครองพฤติกรรมเดิมไว้ จะช่วยให้คุณมั่นใจได้ว่าการย้ายของคุณจะไม่ไปกระทบกับสิ่งที่ลูกค้าใช้งานอยู่จริง
ลองนึกถึงสถานการณ์จริง: สมมติคุณต้องย้ายระบบชำระเงินจากธนาคารหนึ่งไปอีกธนาคารหนึ่ง แทนที่จะเขียนโค้ดใหม่ทั้งหมดทับของเก่า ให้คุณสร้าง Adapter (ตัวแปลงที่ทำหน้าที่เชื่อมต่อระหว่างระบบเก่ากับระบบใหม่) ขึ้นมาครอบโค้ดเดิมไว้ก่อน วิธีนี้จะช่วยให้ระบบเก่าของคุณคุยกับระบบใหม่ได้โดยไม่ต้องแก้ไส้ในของกฎธุรกิจ
สุดท้ายนี้ ขอให้จำไว้ว่า Refactoring คือการเตรียมตัว ไม่ใช่การย้ายระบบ อย่าหลงระเริงกับการแก้โค้ดจนลืมเป้าหมายหลัก เมื่อโค้ดส่วนที่คุณเลือกไว้แยกตัวออกมาเป็นอิสระและทดสอบได้ง่ายแล้ว นั่นคือสัญญาณว่าคุณพร้อมสำหรับการย้ายระบบจริง ๆ แล้วครับ
ที่มา: How to Refactor a Legacy Application Before Migrating It — freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More