Refactoring Code OOP: การปรับปรุง Code ให้ดีขึ้น
หลังจากที่เราได้เรียนรู้การเขียน Unit Tests เพื่อตรวจสอบคุณภาพของโค้ด OOP ในบทที่แล้ว คราวนี้เราจะมาดูกันว่าเราจะปรับปรุงโค้ดของเราให้ดียิ่งขึ้นไปอีกได้อย่างไร ด้วยกระบวนการที่เรียกว่า "Refactoring"
ความหมายของการ Refactoring
Refactoring คือการปรับปรุงโครงสร้างภายในของโค้ด (Internal Structure) โดย**ไม่เปลี่ยนแปลงพฤติกรรมภายนอก (External Behavior)** ของโค้ดนั้น พูดง่ายๆ คือ เปลี่ยนแปลงวิธีที่โค้ดทำงานเบื้องหลัง แต่ผลลัพธ์ที่ได้ยังคงเหมือนเดิม
เปรียบเทียบง่ายๆ เหมือนกับการที่เราปรับปรุงบ้านใหม่ ทาสีใหม่ จัดเฟอร์นิเจอร์ใหม่ แต่บ้านยังคงเป็นบ้านหลังเดิม มีฟังก์ชั่นการใช้งานเหมือนเดิม แต่สวยงามและน่าอยู่กว่าเดิม โค้ดที่ผ่านการ Refactoring ก็เช่นกัน อ่านง่ายขึ้น เข้าใจง่ายขึ้น บำรุงรักษาง่ายขึ้น แต่ยังคงทำงานได้เหมือนเดิม
ทำไมต้อง Refactoring?
- อ่านง่ายขึ้น (Readability): โค้ดที่อ่านง่าย ช่วยให้เราเข้าใจโค้ดได้เร็วขึ้น แก้ไขได้ง่ายขึ้น และลดโอกาสเกิดข้อผิดพลาด
- บำรุงรักษาง่ายขึ้น (Maintainability): โค้ดที่บำรุงรักษาง่าย ช่วยให้เราสามารถแก้ไข ปรับปรุง หรือเพิ่มฟีเจอร์ใหม่ๆ ได้ง่ายขึ้น โดยไม่ต้องกลัวว่าจะทำให้ระบบเสียหาย
- ลดความซับซ้อน (Reduce Complexity): โค้ดที่ซับซ้อน มักจะเต็มไปด้วยข้อผิดพลาด และยากต่อการแก้ไข Refactoring ช่วยลดความซับซ้อนของโค้ด ทำให้โค้ดง่ายต่อการเข้าใจและจัดการ
- เตรียมพร้อมสำหรับการเปลี่ยนแปลง (Prepare for Change): โค้ดที่ผ่านการ Refactoring จะมีความยืดหยุ่นมากขึ้น ทำให้เราสามารถปรับเปลี่ยนโค้ดให้เข้ากับความต้องการใหม่ๆ ได้ง่ายขึ้น
- ปรับปรุงประสิทธิภาพ (Improve Performance): ถึงแม้ว่า Refactoring จะไม่ได้เน้นที่การปรับปรุงประสิทธิภาพโดยตรง แต่บางครั้งการปรับโครงสร้างโค้ดใหม่ ก็อาจช่วยให้โค้ดทำงานได้เร็วขึ้น
เทคนิคการ Refactoring
มีเทคนิคการ Refactoring มากมาย แต่ในบทนี้เราจะมาดูกันที่เทคนิคพื้นฐานที่ใช้กันบ่อยๆ:
1. Extract Method
เทคนิคนี้คือการแยกส่วนของโค้ดที่ยาวและซับซ้อน ออกมาเป็น Method ใหม่ ที่มีชื่อสื่อความหมาย ทำให้โค้ดอ่านง่ายขึ้น และสามารถนำ Method ใหม่นี้ไปใช้ซ้ำได้อีกด้วย
ตัวอย่าง:
class Order {
private $items;
public function printInvoice() {
$totalAmount = 0;
foreach ($this->items as $item) {
$totalAmount += $item->getPrice() * $item->getQuantity();
echo "Item: " . $item->getName() . ", Price: " . $item->getPrice() . ", Quantity: " . $item->getQuantity() . "\n";
}
echo "Total Amount: " . $totalAmount . "\n";
}
}
Refactor เป็น:
class Order {
private $items;
public function printInvoice() {
$this->printOrderDetails();
echo "Total Amount: " . $this->calculateTotalAmount() . "\n";
}
private function printOrderDetails() {
foreach ($this->items as $item) {
echo "Item: " . $item->getName() . ", Price: " . $item->getPrice() . ", Quantity: " . $item->getQuantity() . "\n";
}
}
private function calculateTotalAmount(): float {
$totalAmount = 0;
foreach ($this->items as $item) {
$totalAmount += $item->getPrice() * $item->getQuantity();
}
return $totalAmount;
}
}
ในตัวอย่างนี้ เราได้แยกส่วนของการคำนวณยอดรวม และการแสดงรายละเอียดของ Order ออกเป็น Method `calculateTotalAmount()` และ `printOrderDetails()` ทำให้ Method `printInvoice()` สั้นลงและอ่านง่ายขึ้น
2. Rename Variable/Method
การตั้งชื่อตัวแปรหรือ Method ให้สื่อความหมาย เป็นสิ่งสำคัญที่ช่วยให้โค้ดอ่านง่ายขึ้น หากชื่อเดิมไม่สื่อความหมายหรือไม่ชัดเจน เราสามารถเปลี่ยนชื่อใหม่ได้
ตัวอย่าง:
class User {
private $n; // name
public function __construct($n) {
$this->n = $n;
}
public function getN() {
return $this->n;
}
}
Refactor เป็น:
class User {
private $name;
public function __construct($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
}
เปลี่ยนชื่อตัวแปร `$n` เป็น `$name` และ Method `getN()` เป็น `getName()` ทำให้เข้าใจได้ง่ายขึ้นว่าตัวแปรและ Method นี้เกี่ยวข้องกับอะไร
3. Replace Magic Number with Symbolic Constant
Magic Number คือตัวเลขที่ปรากฏอยู่ในโค้ดโดยไม่มีคำอธิบายว่ามันคืออะไร การใช้ Magic Number ทำให้โค้ดอ่านยากและแก้ไขยาก เราสามารถแทนที่ Magic Number ด้วย Constant ที่มีชื่อสื่อความหมาย
ตัวอย่าง:
class DiscountCalculator {
public function calculateDiscount($price) {
return $price * 0.1; // 0.1 คืออะไร?
}
}
Refactor เป็น:
class DiscountCalculator {
const DISCOUNT_RATE = 0.1;
public function calculateDiscount($price) {
return $price * self::DISCOUNT_RATE;
}
}
แทนที่ `0.1` ด้วย `DISCOUNT_RATE` ทำให้ทราบได้ทันทีว่าตัวเลขนี้คืออัตราส่วนลด
4. Introduce Parameter Object
หาก Method ของเรามี Parameter จำนวนมาก อาจทำให้โค้ดอ่านยากและแก้ไขยาก เราสามารถรวม Parameter เหล่านั้นเป็น Object เดียว แล้วส่ง Object นั้นเป็น Parameter แทน
ตัวอย่าง:
class Product {
public function createProduct($name, $description, $price, $category, $imageUrl) {
// ...
}
}
Refactor เป็น:
class Product {
public function createProduct(ProductData $productData) {
// ...
}
}
class ProductData {
public $name;
public $description;
public $price;
public $category;
public $imageUrl;
}
สร้าง Class `ProductData` เพื่อเก็บข้อมูลของ Product แล้วส่ง Object `ProductData` เป็น Parameter แทน
5. Remove Dead Code
Dead Code คือโค้ดที่ไม่ถูกใช้งานแล้ว เช่น ตัวแปรที่ไม่ได้ใช้ Method ที่ไม่ได้เรียก หรือ Comment ที่ไม่จำเป็น การลบ Dead Code ช่วยให้โค้ดสะอาดและอ่านง่ายขึ้น
เครื่องมือที่ใช้ในการ Refactoring
มีเครื่องมือมากมายที่ช่วยในการ Refactoring โค้ด PHP แต่เครื่องมือที่นิยมใช้กันมากที่สุดคือ:
- PHPStorm: IDE ที่มีฟีเจอร์ Refactoring ครบครัน เช่น Rename, Extract Method, Inline Variable, Move Method, และอื่นๆ
- NetBeans: IDE ฟรีที่มีฟีเจอร์ Refactoring พื้นฐาน
- VS Code with extensions: VS Code เป็น Editor ที่ได้รับความนิยมและสามารถติดตั้ง Extension เพิ่มเติมเพื่อรองรับการ Refactoring ได้
เครื่องมือเหล่านี้ช่วยให้เรา Refactor โค้ดได้อย่างรวดเร็วและปลอดภัย โดยเครื่องมือจะช่วยตรวจสอบว่าการ Refactoring จะไม่ทำให้โค้ดเสียหาย
ข้อควรจำในการ Refactoring
- ทำทีละขั้นตอนเล็กๆ: อย่าพยายาม Refactor โค้ดทั้งหมดในครั้งเดียว ให้แบ่งเป็นขั้นตอนเล็กๆ แล้วทดสอบโค้ดหลังจากแต่ละขั้นตอน
- มี Unit Tests: ก่อนที่จะเริ่ม Refactoring ให้เขียน Unit Tests เพื่อตรวจสอบว่าโค้ดยังคงทำงานได้ถูกต้อง หลังจาก Refactoring
- สื่อสารกับทีม: หากคุณทำงานเป็นทีม ให้สื่อสารกับทีมของคุณเกี่ยวกับการ Refactoring เพื่อให้ทุกคนเข้าใจและเห็นด้วย
- ใช้เครื่องมือช่วย: ใช้เครื่องมือ Refactoring ที่มีอยู่ เพื่อช่วยให้คุณทำงานได้รวดเร็วและปลอดภัย
การ Refactoring เป็นกระบวนการต่อเนื่อง ที่เราควรทำเป็นประจำ เพื่อให้โค้ดของเรามีคุณภาพดีอยู่เสมอ ในบทถัดไป เราจะมาดูกันถึง Best Practices ในการเขียน Code OOP PHP เพื่อให้เราสามารถเขียนโค้ดที่ดีตั้งแต่เริ่มต้น