Devfavor

Back

Declarative vs Imperative — บอกคอมพิวเตอร์ว่า 'ทำยังไง' หรือ 'อยากได้อะไร'Blur image

ลองนึกภาพว่าคุณเขียนโค้ดวนลูปนับเลขทีละตัว สร้างตัวแปรเก็บผลรวม แล้วค่อย ๆ บวกเข้าไป — โค้ดยาวเหยียด แถมต้องคอยระวัง off-by-one error จนหัวหมุน

แล้ววันหนึ่งเพื่อนข้างโต๊ะเขียน SELECT SUM(amount) FROM orders บรรทัดเดียวจบ ได้ผลรวมเหมือนกัน แต่ไม่เห็นมีลูปสักตัว

ความต่างตรงนี้ไม่ใช่เรื่องภาษาไหนเก่งกว่า แต่เป็นวิธีคิดสองแบบที่อยู่เบื้องหลังโค้ดทุกบรรทัดที่เราเขียน — Imperative กับ Declarative

ถ้าเข้าใจสองคำนี้ คุณจะอ่านโค้ดของคนอื่นออกเร็วขึ้น และเลือกเครื่องมือให้เหมาะกับงานได้ดีขึ้น


🎯 แก่นความต่าง: HOW กับ WHAT#

วิธีจำที่ง่ายที่สุดคือ Imperative บอก “ทำยังไง” (HOW) ส่วน Declarative บอก “อยากได้อะไร” (WHAT)

Imperative programming คือการเขียนคำสั่งทีละขั้น ที่คอยเปลี่ยน state ของโปรแกรมไปเรื่อย ๆ — สร้างตัวแปร วนลูป เช็คเงื่อนไข อัปเดตค่า ทุกอย่างคุณต้องสั่งเองหมด

Declarative programming คือการบอกแค่ผลลัพธ์ที่ต้องการ แล้วปล่อยให้ภาษาหรือ framework จัดการรายละเอียด control flow ให้เอง

เปรียบเทียบให้เห็นภาพง่าย ๆ คือเรื่องอาหาร:

  • Imperative = สูตรอาหาร บอกขั้นตอนทีละขั้น ตั้งไฟกี่นาที ใส่อะไรก่อนหลัง
  • Declarative = สั่งอาหารจากเมนู บอกแค่ว่า “เอาผัดกะเพราหนึ่งจาน” ที่เหลือเป็นเรื่องของครัว

👀 ตัวอย่างที่เห็นภาพชัดที่สุด#

ลองดูโจทย์เดียวกัน: เอา array ของตัวเลขมา เลือกเฉพาะเลขคู่ คูณสอง แล้วหาผลรวม

แบบ Imperative ด้วย JavaScript จะเป็นแบบนี้ — สั่งทุกขั้นตอนเอง:

const numbers = [1, 2, 3, 4, 5, 6];
let sum = 0;

for (let i = 0; i < numbers.length; i++) {
  if (numbers[i] % 2 === 0) {
    const doubled = numbers[i] * 2;
    sum += doubled;
  }
}
javascript

แบบ Declarative ด้วย array methods จะเหลือแค่นี้ — บอกเป็นขั้น ๆ ว่าต้องการอะไร โดยไม่ต้องจัดการ index หรือตัวแปรสะสมเอง:

const numbers = [1, 2, 3, 4, 5, 6];

const sum = numbers
  .filter(n => n % 2 === 0)
  .map(n => n * 2)
  .reduce((total, n) => total + n, 0);
javascript

ที่เห็นได้ชัดคือโค้ดแบบ imperative มักยาวกว่า ขณะที่แบบ declarative อ่านแล้วเข้าใจ “เจตนา” ได้ทันที — กรองคู่ คูณสอง บวกรวม

ความต่างเชิงเทคนิคที่ซ่อนอยู่คือ ฝั่ง imperative จะเข้าถึงและแก้ state โดยตรง (sum +=) ขณะที่ declarative ใช้ expression ที่ประเมินออกมาเป็นค่า โดยไม่ไปแตะตัวแปรภายนอก


🌳 Declarative ไม่ได้มีแค่แบบเดียว#

หลายคนเข้าใจว่า declarative คือ functional programming อย่างเดียว แต่จริง ๆ แล้ว declarative เป็นร่มใหญ่ที่ครอบหลาย sub-paradigm:

  • Functional programming — เช่น Haskell
  • Logic programming — เช่น Prolog
  • Constraint programming — บอกเงื่อนไขที่ต้องเป็นจริง แล้วให้ระบบหาคำตอบ

ตัวอย่าง declarative ที่เป็น canonical และอ้างได้แน่นอนคือ SQL กับ Prolog เวลาเขียน SQL คุณบอกแค่ว่าอยากได้ recordset แบบไหน ไม่ได้บอกว่าให้ไล่อ่าน table ทีละแถวยังไง — ตรงนี้แหละคือหัวใจของ declarative ส่วน Prolog หาคำตอบด้วยการให้เหตุผลเชิงตรรกะ — คุณบอกข้อเท็จจริงและกฎ แล้วให้ระบบ deduce คำตอบเอง

ส่วนภาษาฝั่ง imperative ที่เจอบ่อยคือ C, Java, Python ซึ่งมีรากมาจาก von Neumann architecture (เก็บ instruction กับ data ไว้ใน memory แล้วรันทีละคำสั่งแบบ sequential ผ่านการแก้ค่าตัวแปรด้วย assignment)

น่าสนใจตรงที่ภาษายอดนิยมหลายตัว — Python, JavaScript, C++, C# — เป็น multi-paradigm เขียนได้ทั้งสองสไตล์ในภาษาเดียวกัน อยู่ที่ว่าคุณเลือกคิดแบบไหน


⚖️ ข้อดีข้อเสีย: ไม่มีฝั่งไหนชนะขาด#

Declarative — ข้อดี

  • อ่านง่าย กระชับ เพราะแยก “อยากได้อะไร” ออกจาก “ทำยังไง” ทำให้โฟกัสที่ปัญหาไม่ใช่ implementation
  • มีคุณสมบัติ idempotent ในหลายบริบท — รันคำสั่งซ้ำได้ผลลัพธ์เดิม (มีประโยชน์มากกับงาน config)
  • state ถูกจัดการอัตโนมัติโดยภาษาหรือ framework ไม่ต้อง track เอง

Declarative — ข้อเสีย

  • เสีย control เหนือขั้นตอนย่อย เพราะปล่อยให้ engine ตัดสินใจ
  • performance อาจสู้ไม่ได้ถ้า engine optimize ได้ไม่ดี บางทีการ tune ด้วยมือยังเร็วกว่า
  • debug ยากขึ้น เพราะรายละเอียดเชิง operation อย่าง evaluation order ถูกซ่อนไว้ (ในภาษาอย่าง Haskell เรื่องนี้ชัดเจน)

Imperative — ข้อดี

  • control ละเอียดทุกขั้นตอน เหมาะกับงาน low-level และ algorithm ซับซ้อน
  • ปรับจูน performance ได้เต็มที่

Imperative — ข้อเสีย

  • พอโปรแกรมโตขึ้น การจัดการ mutable state เริ่มยุ่งยาก
  • error มักเกิดจาก state เปลี่ยนแบบไม่คาดคิด ทำให้ debug เหนื่อย
  • ทำ parallel ยาก เพราะมี shared mutable state

🧭 แล้วเมื่อไหร่ควรใช้แบบไหน#

เลือก Declarative เมื่อ ปัญหาแก้ได้ด้วยการนิยาม rules หรือ transformations — เช่น query database (SQL), จัดการ config / Infrastructure as Code (Terraform, Puppet), โครงสร้าง UI (เช่น map data ไปเป็น DOM), data pipeline และ data transformation — งานเหล่านี้จะได้ความ readable และ maintainable มาเป็นของแถม

เลือก Imperative เมื่อ control flow และ state เปลี่ยนแปลงซับซ้อน หรือต้อง optimize ทุกรายละเอียด — เช่น game development, real-time processing, การคุมฮาร์ดแวร์ระดับล่าง, system / OS programming, graphics และงาน performance-critical

มีสองกรณีที่ declarative ไม่เหมาะ และควรจำไว้:

  • embedded systems ที่ต้องการ timing แน่นอน — เพราะคำตอบที่ถูกต้องแต่มาช้าเกินไป ก็กลายเป็นคำตอบที่ผิด
  • งานแก้ไขเล็ก ๆ ที่ CLI script ธรรมดาทำได้ — การ wrap ด้วย declarative tooling จะซับซ้อนเกินจำเป็น

ที่สำคัญกว่านั้น โปรเจกต์ส่วนใหญ่ในโลกจริง ไม่ได้เลือกข้างใดข้างหนึ่ง แต่ผสมทั้งสองแบบ อยู่แล้ว แนวทางที่เจอบ่อยคือเขียน business logic แบบ declarative ให้อ่านง่ายเป็นหลัก แล้วค่อยสลับมาใช้ imperative เฉพาะจุดที่ต้องคุม performance หรือจัดการ error / retry ที่ซับซ้อน — คำถามจึงไม่ใช่ “เลือกแบบไหน” แต่เป็น “ตรงไหนควรใช้แบบไหน”


⚠️ กับดักที่เจอบ่อยที่สุด#

เข้าใจผิดยอดฮิตคือคิดว่า “พอเปลี่ยนมาใช้ map / filter / reduce หรือแยก logic เป็น function แล้ว โค้ดจะกลายเป็น declarative อัตโนมัติ”

จริง ๆ แล้วไม่ใช่อย่างนั้น เพราะคุณยังคิดแบบ procedural ได้อยู่ ทั้งที่ใช้ array methods — เครื่องมือพวกนี้เป็นกลาง ไม่ได้การันตีว่าคุณจะคิดแบบ declarative

แก่นจริง ๆ ของ declarative คือ การแสดงความสัมพันธ์ระหว่าง operation โดยไม่ผูกกับลำดับการ execute ส่วน procedural / imperative คือการเรียงลำดับขั้นตอนตาม temporal ordering — แก่นของเรื่องนี้คือการเปลี่ยน “วิธีคิด” ไม่ใช่แค่เปลี่ยน syntax

กับดักอื่นที่เจอบ่อยในงาน UI เช่น React คือไปแก้ DOM ตรง ๆ (ติดนิสัยมาจาก jQuery) หรือยัด logic เข้าไปใน template จนซับซ้อน ทั้งที่ paradigm พวกนี้ออกแบบมาให้บอก “ผลลัพธ์ที่อยากได้” ไม่ใช่ไปสั่งแก้ทีละขั้น


📝 สรุป#

Imperative บอกคอมพิวเตอร์ว่า “ทำยังไง” ทีละขั้น พร้อมจัดการ state เอง ส่วน Declarative บอกแค่ “อยากได้อะไร” แล้วปล่อยที่เหลือให้ระบบจัดการเอง ไม่มีฝั่งไหนดีกว่าโดยสมบูรณ์ — declarative ชนะเรื่อง readability และ maintainability ส่วน imperative ชนะเรื่อง control และ performance งานจริงจึงเป็นเรื่องของการเลือกแบบที่เหมาะกับแต่ละจุด ไม่ใช่ยึดติดแบบใดแบบหนึ่ง

ครั้งหน้าที่คุณเขียน for loop ลองหยุดคิดสักนิดว่า “อันนี้เขียนแบบ declarative ได้ไหม จะอ่านง่ายขึ้นหรือเปล่า” — แล้วลองหยิบ SQL หรือ array methods ในภาษาที่คุณถนัดมาเขียนโจทย์เดิมทั้งสองสไตล์ดู คุณจะเริ่ม “เห็น” สอง paradigm นี้ในโค้ดทุกบรรทัดที่เจอ

😎 ☕

Code, coffee, and calm — the holy trinity of a good day. ☕

Declarative vs Imperative — บอกคอมพิวเตอร์ว่า 'ทำยังไง' หรือ 'อยากได้อะไร'
Author Coffee Stack
Published at 15 มิถุนายน 2026