Race condition
ผมกำลังอ่านหนังสือ The Unicorn Project ซึ่งเป็นนิยายเกี่ยวกับ developer สาวคนหนึ่งที่ใช้ชีวิตในองค์กรท่ามกลางกระแส digital disruption อ่านแล้วสนุกมาก เป็นเรื่องที่ตื่นเต้น และหลาย ๆ dynamic ที่เกิดขึ้นก็คล้ายกับที่ผมพบเจอในบริษัทซอฟต์แวร์ เลยทำให้อินมาก แค่ในนิยายมันดราม่า และทุกอย่างมันดำเนินเร็วกว่าเท่านั้น ตอนนี้ที่อ่านมาจะจบเล่มแล้ว สิ่งหนึ่งที่ประทับใจคือ ความที่นางเอกรักการเขียนโปรแกรมแบบ functional programming เพราะบางปัญหา การคิดและแก้แบบ functional มันทำให้ได้วิธีการที่ง่ายกว่าแบบ imperative มาก และปัญหาหนึ่งที่ไม่มีวันเกิดในโลกของ functional คือปัญหาน่ากลัวที่เรียกว่า race conditions
หลักการของ Functional programming คือการสร้าง function ที่เป็นเหมือนท่อ รับ input เข้าไป ก็ตอบ output ออกมา โดยไม่มีการแก้ไขค่าตัวแปรไหนเลย ทำให้ไม่เกิด side effect ความสวยงามของการแก้ปัญหาแบบนี้คือ ทำให้โปรแกรมที่เป็น pure functional สามารถย้อนเวลากลับได้ง่ายมาก และที่สำคัญที่สุดคือ ไม่มีวันเจอปัญหา race condition ที่น่าสยดสยอง
ปัญหา Race condition race แปลว่าแข่ง ปัญหา race condition คือ เวลาเราเขียนโปรแกรม บางครั้งเราจะสร้าง worker หลาย ๆ ตัวมาทำงานพร้อม ๆ กัน เพื่อให้โปรแกรมทำงานเร็วขึ้น ปัญหา race condition คือ เวลาทำโปรแกรมมี bug แต่ว่าเงื่อนไขของการเกิด bug คือ โปรแกรมหลาย ๆ ตัวแย่งกันทำงานในลำดับที่เป็นรูปแบบเฉพาะ เช่น worker A ทำก่อน แล้ว B แล้ว C แล้วกลับมา B ถึงจะเกิด bug ปัญหาแบบนี้แก้ยากมาก เพราะเวลาเรามาลองเล่นเอง มันมักจะไม่เจอ เพราะ การเกิดของปัญหามันต้องให้ worker แข่งกัน แล้วเข้าเส้นชัยตามลำดับที่กำหนด ถึงจะเกิด bug ได้ วิธี reproduce ปัญหาเลยต้องทำซ้ำหลาย ๆ รอบ หรือจำลองงานมหาศาลให้เกิดในเวลาสั้น ๆ เพื่อให้ bug มีโอกาสเกิด ซึ่งเป็นงานที่ยากและหลอกหลอนโปรแกรมเมอร์ที่เคยแก้มันหนักมาก ในหนังสือ มีตอนหนึ่งที่นางเอกช่วยเพื่อนแก้ bug ที่เป็น race condition และนางเอกก็ได้ list สมมติฐาน 3 ข้อเพื่อคอนเฟิร์มว่ามันเป็นปัญหา race condition จริง ๆ 3 ข้อนั้นมีดังนี้
- มี worker หลาย ๆ ตัวจัดการ messages
- มีตัวแปรที่แชร์ระหว่างหลาย ๆ worker
- ขณะที่ worker ส่งตัวแปรไปมา มีการ mutate (แก้ไขค่า) ระหว่างที่ worker ทำงาน
หลังจากนางเอกคอนเฟิร์มว่ามันเป็น race condition แล้ว นางเอกก็ชวนเพื่อน rewrite โปรแกรมตรงนั้นใหม่ด้วยหลักการ functional programming ซึ่งทำให้ reproduce bug ได้อย่างสม่ำเสมอ และแก้มันได้โดยไม่กลับมาอีก แถมโค้ดยังอ่านง่ายขึ้นเหลือเพียงไม่กี่บรรทัดด้วย สาเหตุที่ functional programming ปราบ race condition อยู่หมัดมาก เพราะใน functional programming จะไม่มีการแก้ค่าตัวแปร (mutate) ทุกตัวแปรที่ถูกกำหนดค่าแล้ว จะเป็นค่านั้นตลอดไป พอไม่มีการแก้ไขค่าตัวแปร เราจะแชร์ให้กี่ worker ตัวแปรก็มีค่าเดิมเสมอไป ทำให้ไม่มีปัญหา race condition ที่เกิดจากการที่ตัวแปรที่ worker ตัวหนึ่งทำงานอยู่ ถูกเพื่อนเปลี่ยนกลางอากาศ bug ประเภทนี้ก็เลยเกิดไม่ได้ ความเท่อีกอย่างคือ เวลานางเอก rewrite มันด้วย functional programming แล้ว โค้ดที่ซับซ้อนยาว ๆ ก็เหลือแค่ไม่กี่บรรทัดที่เข้าใจง่าย ทำให้ทุกคนทึ่งกันไปหมด ในประสบการณ์ผมก็เคยเจอเหตุการณ์คล้าย ๆ ที่นางเอกเจอบ้าง แต่นั่นเป็นเพราะ ปัญหาบางประเภท วิธีคิดแบบ functional มันแก้ง่ายกว่าการคิดแบบ imperative มาก ทำให้นึกถึงตอนไปเรียน Problem Solving Leadership เลย คนสอนบอกว่า
"ปัญหาคือปัญหา ไม่มีง่ายหรือยาก ง่ายหรือยากขึ้นอยู่กับ solution เท่านั้นโลกนี้ไม่มีปัญหาไหนยาก มีแต่ปัญหาที่เรายังไม่รู้วิธีแก้ง่าย ๆ เฉย ๆ" – Gerald M.Weinberge