Skip to main content

เนื้อหาภาษาไทย / Thai content

System guide Content reviewed

Clean Code: ฟังก์ชันควรทำอะไร?

บทความนี้กล่าวถึงหลักการเขียนฟังก์ชันที่ดีตามแนวคิด Clean Code โดยเน้นที่ **Single Responsibility Principle (SRP)** ซึ่งหมายถึงฟังก์ชันควรมีหน้าที่เดียว, **ขนาด...

Clean Code: ฟังก์ชันควรทำอะไร?

จากบทที่แล้วที่เราได้พูดคุยกันเรื่องความสำคัญของการตั้งชื่อที่ดีใน Clean Code วันนี้เราจะมาเจาะลึกกันต่อในเรื่องของฟังก์ชัน หนึ่งในองค์ประกอบพื้นฐานที่สุดของการเขียนโปรแกรม ฟังก์ชันที่ดีนั้น นอกจากจะมีชื่อที่สื่อความหมายแล้ว ยังต้องมีคุณสมบัติอื่นๆ ที่จะช่วยให้โค้ดของเราสะอาด อ่านง่าย และบำรุงรักษาง่ายอีกด้วย

Single Responsibility Principle: หนึ่งฟังก์ชัน หนึ่งหน้าที่

หัวใจสำคัญของการเขียนฟังก์ชันที่ดีคือ Single Responsibility Principle (SRP) หรือหลักการความรับผิดชอบเดียว ซึ่งหมายความว่า แต่ละฟังก์ชันควรมีหน้าที่เดียวเท่านั้น

ลองจินตนาการว่าคุณมีเครื่องมืออเนกประสงค์ที่ทำได้ทุกอย่าง ตั้งแต่ปอกผลไม้ ยันซ่อมรถยนต์ มันคงจะใช้งานยากและประสิทธิภาพไม่ดีเท่าเครื่องมือเฉพาะทางใช่ไหมครับ? ฟังก์ชันก็เช่นกัน ถ้าฟังก์ชันหนึ่งทำหลายอย่างเกินไป จะทำให้โค้ดซับซ้อน เข้าใจยาก และแก้ไขยาก

ตัวอย่างที่ไม่ดี:

function processOrder($orderId) {
  // 1. ดึงข้อมูล Order จาก Database
  $order = getOrderFromDatabase($orderId);

  // 2. คำนวณราคารวม
  $total = calculateTotal($order);

  // 3. ส่งอีเมลยืนยันการสั่งซื้อ
  sendConfirmationEmail($order['email'], $total);

  // 4. อัพเดทสถานะ Order ใน Database
  updateOrderStatus($orderId, 'confirmed');
}

ฟังก์ชัน processOrder นี้ทำถึง 4 อย่าง ซึ่งเป็นการละเมิดหลักการ SRP

ตัวอย่างที่ดี:

function processOrder($orderId) {
  $order = getOrder($orderId);
  $total = calculateOrderTotal($order);
  confirmOrder($order, $total);
}

function getOrder($orderId) {
  return getOrderFromDatabase($orderId);
}

function calculateOrderTotal($order) {
  return calculateTotal($order);
}

function confirmOrder($order, $total) {
  sendConfirmationEmail($order['email'], $total);
  updateOrderStatus($order['id'], 'confirmed');
}

เราได้แยกฟังก์ชัน processOrder ออกเป็นฟังก์ชันย่อยๆ ที่มีหน้าที่เดียว ทำให้โค้ดอ่านง่ายขึ้น และถ้าต้องการแก้ไขส่วนใดส่วนหนึ่ง ก็สามารถทำได้โดยไม่กระทบส่วนอื่น

ฟังก์ชันขนาดเล็ก: ยิ่งเล็ก ยิ่งดี

โดยทั่วไปแล้ว ฟังก์ชันที่ดีควรมีขนาดเล็ก โดยไม่ควรเกิน 20-30 บรรทัด หากฟังก์ชันของคุณยาวกว่านี้ ลองพิจารณาแยกฟังก์ชันออกเป็นฟังก์ชันย่อยๆ ที่มีหน้าที่เดียว เหมือนที่เราทำในตัวอย่างก่อนหน้านี้

ทำไมฟังก์ชันขนาดเล็กถึงดี?

  • อ่านง่าย: ฟังก์ชันขนาดเล็กจะเข้าใจง่ายกว่า เพราะมีโค้ดน้อยกว่า
  • ทดสอบง่าย: ฟังก์ชันขนาดเล็กจะทดสอบง่ายกว่า เพราะมีกรณีทดสอบน้อยกว่า
  • นำกลับมาใช้ใหม่ได้ง่าย: ฟังก์ชันขนาดเล็กที่มีหน้าที่เดียว มักจะสามารถนำกลับมาใช้ใหม่ในส่วนอื่นๆ ของโปรแกรมได้
  • แก้ไขง่าย: ฟังก์ชันขนาดเล็กจะแก้ไขง่ายกว่า เพราะมีการเปลี่ยนแปลงที่กระทบกับส่วนอื่นๆ น้อยกว่า

แน่นอนว่าการกำหนดขนาดที่ตายตัวอาจไม่ใช่เรื่องที่ถูกต้องเสมอไป แต่โดยทั่วไปแล้ว ถ้าคุณรู้สึกว่าฟังก์ชันของคุณเริ่มยาวและซับซ้อนเกินไป นั่นอาจเป็นสัญญาณว่าถึงเวลาที่ต้อง Refactor แล้ว

หลีกเลี่ยง Side Effects: ฟังก์ชันควรทำตามที่บอกเท่านั้น

Side Effects คือการที่ฟังก์ชันเปลี่ยนแปลงสถานะภายนอก (เช่น ตัวแปร Global, Database, File) นอกเหนือจากค่าที่ฟังก์ชันส่งกลับมา

Side Effects เป็นสิ่งที่ควรหลีกเลี่ยง เพราะทำให้โค้ดคาดเดาได้ยาก และทำให้เกิด Bug ได้ง่าย

ตัวอย่าง:

$discount = 0.1; // ตัวแปร Global

function applyDiscount($price) {
  global $discount;
  $price = $price * (1 - $discount);
  $discount = 0.2; // เปลี่ยนค่าตัวแปร Global
  return $price;
}

$originalPrice = 100;
$discountedPrice = applyDiscount($originalPrice);

echo "Original Price: " . $originalPrice . "\n";
echo "Discounted Price: " . $discountedPrice . "\n";
echo "Discount: " . $discount . "\n";

ในตัวอย่างนี้ ฟังก์ชัน applyDiscount ไม่เพียงแต่คำนวณราคาที่ลดแล้วเท่านั้น แต่ยังเปลี่ยนแปลงค่าของตัวแปร Global $discount อีกด้วย ทำให้ผลลัพธ์ของโปรแกรมคาดเดาได้ยาก

วิธีแก้ไข:

function applyDiscount($price, $discount) {
  return $price * (1 - $discount);
}

$discount = 0.1;
$originalPrice = 100;
$discountedPrice = applyDiscount($originalPrice, $discount);

echo "Original Price: " . $originalPrice . "\n";
echo "Discounted Price: " . $discountedPrice . "\n";
echo "Discount: " . $discount . "\n";

เราได้แก้ไขฟังก์ชัน applyDiscount ให้รับค่า $discount เป็น Parameter แทนที่จะใช้ตัวแปร Global ทำให้ฟังก์ชันมีความเป็นอิสระมากขึ้น และไม่มี Side Effects

หลักการง่ายๆ ในการหลีกเลี่ยง Side Effects:

  • ฟังก์ชันควรรับข้อมูลที่ต้องการจาก Parameter เท่านั้น
  • ฟังก์ชันควรส่งกลับค่าที่คำนวณได้เท่านั้น
  • ฟังก์ชันไม่ควรเปลี่ยนแปลงตัวแปร Global หรือสถานะภายนอกอื่นๆ

สรุป

การเขียนฟังก์ชันที่ดีเป็นสิ่งสำคัญในการสร้าง Clean Code ที่อ่านง่าย บำรุงรักษาง่าย และลดความเสี่ยงในการเกิด Bug โดยสรุปแล้ว ฟังก์ชันที่ดีควรมีคุณสมบัติดังนี้:

  • Single Responsibility Principle: ทำหน้าที่เดียวเท่านั้น
  • ขนาดเล็ก: ไม่ยาวจนเกินไป
  • ไม่มี Side Effects: ไม่เปลี่ยนแปลงสถานะภายนอก

ในบทต่อไป เราจะมาพูดถึงเรื่อง Comments และวิธีเขียน Comments ที่ดี (และ Comments ที่ไม่ดี) เพื่อให้โค้ดของเราเข้าใจง่ายยิ่งขึ้น อย่าลืมติดตามกันนะครับ!

Office.in.th Custom Service

Want to build or adapt a system from this structure?

Office.in.th designs and develops enterprise web applications, API integrations, and public- and private-sector management systems, with long-term support.

See our software development service