ความไม่เปลี่ยนรูปและผลข้างเคียง
ทำความเข้าใจความสำคัญของความไม่เปลี่ยนรูปในการเขียนโปรแกรมเชิงฟังก์ชัน และวิธีจัดการผลข้างเคียงอย่างมีประสิทธิภาพ
ความไม่เปลี่ยนรูปและผลข้างเคียง เป็นบทเรียน Scala for Backend Engineering & Functional Programming ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 3 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Scala for Backend Engineering & Functional Programming และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Scala for Backend Engineering & Functional Programming มีบทเรียนทั้งหมด 3 บทเรียน
ไม่เปลี่ยนแปลงโดยการออกแบบ
ยินดีต้อนรับสู่บทเรียนเรื่อง ความไม่เปลี่ยนแปลงและผลข้างเคียง ครับ/ค่ะ! แนวคิดเหล่านี้เป็นหลักสำคัญของการเขียนโปรแกรมเชิงฟังก์ชัน (FP) และช่วยให้เราเขียนโค้ดที่สะอาดและคาดเดาได้มากขึ้น
ในการเขียนโปรแกรมเชิงฟังก์ชัน เรานิยมทำงานกับข้อมูลที่ไม่เปลี่ยนแปลง ซึ่งหมายความว่า เมื่อสร้างข้อมูลขึ้นมาแล้ว ข้อมูลนั้นจะไม่สามารถเปลี่ยนแปลงได้ ลองนึกถึงภาพถ่าย คุณดูภาพได้ แต่ไม่สามารถเปลี่ยนแปลงช่วงเวลาเดิมที่ภาพบันทึกไว้ได้
val เทียบกับ var ใน Scala
Scala ช่วยให้ประกาศค่าที่ไม่เปลี่ยนแปลงได้ง่ายโดยใช้คีย์เวิร์ด val ซึ่งเป็นการอ้างอิงค่าคงที่ที่ไม่สามารถกำหนดค่าใหม่ได้หลังจากประกาศครั้งแรก หากต้องการใช้ตัวแปรที่เปลี่ยนแปลงได้ ให้ใช้ var
มาดูความแตกต่างกัน:
object Main {
def main(args: Array[String]): Unit = {
// Immutable value
val greeting = "Hello"
// greeting = "Hi" // This would cause a compile error!
// Mutable variable
var count = 0
count = 1 // This is allowed
println(greeting)
println(count)
}
}เหตุใดความไม่เปลี่ยนแปลงจึงสำคัญ
ความไม่เปลี่ยนแปลงนำประโยชน์สำคัญหลายประการมาสู่โค้ด โดยเฉพาะในระบบที่ทำงานพร้อมกันและระบบที่ซับซ้อน:
- คาดเดาได้: คุณมั่นใจได้เสมอว่าค่าจะไม่เปลี่ยนแปลงโดยไม่คาดคิด
- ปลอดภัยต่อการทำงานพร้อมกัน: หลายส่วนของโปรแกรมสามารถอ่านข้อมูลเดียวกันได้โดยไม่ต้องกังวลว่าส่วนอื่นจะเปลี่ยนแปลงข้อมูลนั้น ไม่จำเป็นต้องใช้กลไกล็อกที่ซับซ้อน!
- แก้จุดบกพร่องได้ง่ายขึ้น: การติดตามหาจุดบกพร่องทำได้ง่ายขึ้น เพราะไม่ต้องกังวลว่าสถานะจะเปลี่ยนไปตามเวลา
คอลเลกชันที่ไม่เปลี่ยนแปลง
ไลบรารีมาตรฐานของ Scala สนับสนุนคอลเลกชันที่ไม่เปลี่ยนแปลงเป็นค่าเริ่มต้น เมื่อคุณ 'แก้ไข' คอลเลกชันที่ไม่เปลี่ยนแปลง จริง ๆ แล้วคุณจะได้รับคอลเลกชันใหม่ที่มีการเปลี่ยนแปลง โดยคอลเลกชันเดิมยังคงไม่ถูกแตะต้อง
ตัวอย่างคอลเลกชัน List ที่ไม่เปลี่ยนแปลงมีดังนี้:
object Main {
def main(args: Array[String]): Unit = {
val numbers = List(1, 2, 3)
val newNumbers = numbers :+ 4 // Creates a new list
println(s"Original list: $numbers")
println(s"New list: $newNumbers")
}
}ทำความเข้าใจผลข้างเคียง
ผลข้างเคียงแตกต่างจากความไม่เปลี่ยนแปลง โดยเกิดขึ้นเมื่อฟังก์ชันหรือนิพจน์ทำสิ่งอื่นนอกเหนือจากการส่งคืนค่าเพียงอย่างเดียว เช่น โต้ตอบกับ 'โลกภายนอก' หรือเปลี่ยนแปลงสถานะที่เปลี่ยนแปลงได้
ผลข้างเคียงที่พบบ่อย ได้แก่:
- การแก้ไขตัวแปรส่วนกลางหรือออบเจ็กต์ที่เปลี่ยนแปลงได้
- การพิมพ์ลงคอนโซล (I/O)
- การเขียนลงไฟล์หรือฐานข้อมูล
- การเปลี่ยนแปลงนาฬิกาของระบบ
ปัญหาของผลข้างเคียง
แม้ว่าบางครั้งผลข้างเคียงจะจำเป็น แต่ในการเขียนโปรแกรมเชิงฟังก์ชัน เรามุ่งลดและแยกผลข้างเคียงเหล่านี้ออกจากส่วนอื่น เหตุใดจึงเป็นเช่นนั้น
- ทำความเข้าใจได้ยากขึ้น: ผลลัพธ์ของฟังก์ชันอาจขึ้นอยู่กับสถานะภายนอก ทำให้คาดเดาได้ยาก
- ทดสอบได้ยาก: การทดสอบต้องเตรียมและล้างสถานะภายนอก
- ปัญหาการทำงานพร้อมกัน: เธรดหลายรายการที่ก่อผลข้างเคียงอาจทำให้เกิดสภาวะแข่งขันและจุดบกพร่อง
การระบุผลข้างเคียงในโค้ด
มาดูตัวอย่าง Scala กัน ฟังก์ชันหนึ่งมีผลข้างเคียง ส่วนอีกฟังก์ชันไม่มี คุณสังเกตเห็นความแตกต่างได้หรือไม่
object Main {
var total = 0 // A mutable global variable
// Function with a side effect
def addAndPrint(x: Int, y: Int): Int = {
total = x + y // Modifies global state
println(s"Sum is: $total") // I/O side effect
total
}
// Function without side effects (pure function)
def pureAdd(x: Int, y: Int): Int = {
x + y // Only returns a value
}
def main(args: Array[String]): Unit = {
addAndPrint(5, 3)
println(s"Global total: $total")
println(s"Pure sum: ${pureAdd(5, 3)}")
}
}ฟังก์ชันบริสุทธิ์: อุดมคติของ FP
เป้าหมายสูงสุดของ FP คือการเขียนฟังก์ชันบริสุทธิ์ ฟังก์ชันบริสุทธิ์มีลักษณะสำคัญสองประการ:
- ให้ผลลัพธ์เดียวกันเสมอเมื่อได้รับอินพุตเดียวกัน (กำหนดผลลัพธ์ได้แน่นอน)
- ไม่ก่อให้เกิดผลข้างเคียง (ไม่เปลี่ยนแปลงสิ่งใดนอกขอบเขตของฟังก์ชัน)
ฟังก์ชัน pureAdd ในตัวอย่างก่อนหน้านี้เป็นฟังก์ชันบริสุทธิ์!
การจัดการผลข้างเคียง
เนื่องจากผลข้างเคียงบางอย่างหลีกเลี่ยงไม่ได้ (เช่น การพิมพ์ผลลัพธ์หรือการบันทึกข้อมูล) แนวทางของ FP คือ:
- แยกผลข้างเคียงออก: แยกฟังก์ชันที่มีผลข้างเคียงออกจากฟังก์ชันบริสุทธิ์
- ผลักไปไว้ที่ขอบของระบบ: ดำเนินการ I/O ในตอนเริ่มต้นหรือตอนสิ้นสุดโปรแกรม หรือภายในส่วนที่จัดไว้เฉพาะสำหรับการทำงานที่ก่อผล
- ใช้โครงสร้างของ FP: ไลบรารีมักมีชนิดข้อมูล (เช่น
IOหรือTask) สำหรับแทนค่าและจัดการผลกระทบอย่างชัดเจน
ตรวจสอบความเข้าใจ
จากสิ่งที่คุณเรียนรู้มา ข้อความใดต่อไปนี้เกี่ยวกับความไม่เปลี่ยนแปลงและผลข้างเคียงในการเขียนโปรแกรมเชิงฟังก์ชันเป็นจริง
ทบทวน: ความไม่เปลี่ยนแปลงและผลกระทบ
ทำได้ดีมากครับ/ค่ะ! ในบทเรียนนี้ เราได้สำรวจแนวคิดสำคัญเรื่องความไม่เปลี่ยนแปลงและผลข้างเคียงในการเขียนโปรแกรมเชิงฟังก์ชัน
- เราได้เห็นว่า
valส่งเสริมความไม่เปลี่ยนแปลงใน Scala ทำให้โค้ดคาดเดาได้มากขึ้นและปลอดภัยต่อการทำงานพร้อมกัน - เรานิยามผลข้างเคียงว่าเป็นการโต้ตอบที่อยู่นอกเหนือค่าที่ฟังก์ชันส่งคืน และเข้าใจว่าเหตุใดผลข้างเคียงจึงทำให้โค้ดซับซ้อนขึ้นได้
- สุดท้าย เราได้เรียนรู้เกี่ยวกับฟังก์ชันบริสุทธิ์ในฐานะอุดมคติของ FP ซึ่งให้ผลลัพธ์ที่กำหนดได้แน่นอนและไม่มีผลข้างเคียง รวมถึงแนวทางจัดการผลข้างเคียงที่จำเป็น
การเชี่ยวชาญแนวคิดเหล่านี้เป็นกุญแจสำคัญในการเขียนแอปพลิเคชัน Scala เชิงฟังก์ชันที่แข็งแกร่งและสวยงาม!
คำถามที่พบบ่อย
บทเรียน “ความไม่เปลี่ยนรูปและผลข้างเคียง” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “ความไม่เปลี่ยนรูปและผลข้างเคียง” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Scala for Backend Engineering & Functional Programming ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Scala for Backend Engineering & Functional Programming มีบทเรียนทั้งหมด 3 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “ความไม่เปลี่ยนรูปและผลข้างเคียง”
ทำความเข้าใจความสำคัญของความไม่เปลี่ยนรูปในการเขียนโปรแกรมเชิงฟังก์ชัน และวิธีจัดการผลข้างเคียงอย่างมีประสิทธิภาพ คุณปฏิบัติ Scala for Backend Engineering & Functional Programming ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Scala for Backend Engineering & Functional Programming หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Scala for Backend Engineering & Functional Programming บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 3 บทเรียน
บทเรียน “ความไม่เปลี่ยนรูปและผลข้างเคียง” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Scala for Backend Engineering & Functional Programming นี้ได้ไหม
ได้ บทเรียน Scala for Backend Engineering & Functional Programming ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- ฟังก์ชันในฐานะค่าอันดับหนึ่ง
- ฟังก์ชันลำดับสูงและการทำเคอร์รี
- ความไม่เปลี่ยนรูปและผลข้างเคียง