ข้าม​ไป​ยัง​เนื้อหา

Murphy’s Law

อะไร​ที่​ผิดพลาด​ได้ มัน​จะ​ผิดพลาด

Murphy’s Law กล่าว​ว่า “อะไร​ที่​ผิดพลาด​ได้ มัน​จะ​ผิดพลาด” (Anything that can go wrong will go wrong) เป็น​หนึ่ง​ใน “กฎ” พื้นบ้าน​ที่​ถูก​อ้างอิง​มาก​ที่สุด​ใน​วงการ​วิศวกรรม ไม่ใช่​ทฤษฎี​ทาง​ฟิสิกส์​หรือ​สถิติ แต่​เป็น​คำ​เตือน​เชิง​ปฏิบัติ​ที่​บอกว่า: ถ้า​ระบบ​มี​ช่อง​โหว่​หรือ​ทาง​ที่​จะ​พัง​ได้ สัก​วัน​หนึ่ง​มัน​จะ​พัง​ตาม​ทาง​นั้น​จริง ๆ โดย​เฉพาะ​เมื่อ​ระบบ​ถูก​ใช้งาน​ซ้ำ ๆ เป็น​เวลา​นาน หรือ​มี​ผู้​ใช้​จำนวน​มาก

เมื่อ​ออกแบบ​และ​สร้าง​ระบบ สิ่ง​สำคัญ​คือ​ต้อง​คิดถึง​ทุก​วิถีทาง​ที่​ระบบ​อาจ​ล้มเหลว เพราะ​สัก​วัน​สิ่ง​เหล่า​นั้น​จะ​เกิด​ขึ้น​จริง Defensive programming คือ​การ​เขียน code ที่​คาด​การณ์​ปัญหา​และ​จัดการ​มัน​ก่อน​ที่​จะ​ลุกลาม​กลาย​เป็น​ความ​เสียหาย​ใหญ่ และ​หลัก​ที่​มัก​ใช้​คู่​กัน​คือ fail fast — ยิ่ง​ตรวจ​พบ input ที่​ผิด​เร็ว​เท่าไร ความ​เสียหาย​ก็​ยิ่ง​น้อย ใช้​ทรัพยากร​จัดการ​น้อย​ลง และ​ผู้​ใช้​แก้ไข​ได้​เร็ว​ขึ้น

ที่มา​ของ​วลี​นี้​ย้อน​ไป​ถึง​ปี 1949 ที่ Muroc Army Air Field (ต่อ​มา​คือ Edwards Air Force Base) ใน​โครงการ​ทดสอบ MX981 ของกองทัพ​อากาศสหรัฐฯ ซึ่ง​ศึกษา​ผล​ของ​แรง g ต่อ​ร่างกาย​มนุษย์​ด้วย​การ​เลื่อน​แท่น​จรวด (rocket sled) นำ​โดย​พัน​เอก John Stapp วิศวกร​การ​บิน Edward A. Murphy Jr. เป็น​ผู้​เสนอ​ให้​ใช้ strain gauge วัด​แรง​บน​สาย​รัด​ของ Stapp แต่​เกจ​ถูก​ต่อ​สาย​ผิด​จน​อ่าน​ค่า​ได้​ศูนย์​ทุก​ตัว Murphy จึง​บ่นถึง​ผู้​ช่วย​ของ​เขา​ใน​ทำนอง​ว่า “ถ้า​มี​ทาง​ทำ​ผิด​ได้ เขา​จะ​ทำ​ผิด​ทาง​นั้น” คำ​พูด​นี้​ถูก​เพื่อน​ร่วม​งาน​นำ​ไป​สรุป​ย่อ​เป็น “If it can happen, it will happen” และ​ตั้ง​ชื่อ​ล้อเลียน​ตาม Murphy ภายหลัง Stapp เอง​กลับ​นำ​วลี​นี้​ไป​เผยแพร่​ใน​เชิง​บวก — เป็น​หลัก​คิด​เรื่อง​การ​วางแผน​ป้องกัน​ความ​หายนะ​ล่วงหน้า ไม่ใช่​คำ​พูด​ใน​แง่​ร้าย​อย่าง​ที่​หลาย​คน​เข้าใจ

น่า​สังเกต​ว่า​ถ้อยคำ​ดั้งเดิม​ของ Murphy เอง​มี​ความ​จำเพาะ​เจาะจง​กว่า​ที่​คน​ทั่วไป​จำ​กัน คือ​ประมาณ​ว่า “ถ้า​มี​สอง​วิธี​ขึ้น​ไป​ใน​การ​ทำ​สิ่ง​หนึ่ง และ​วิธี​หนึ่ง​จะ​นำ​ไป​สู่​หายนะ จะ​มี​คน​เลือก​ทำ​วิธี​นั้น” นัก​วิทยาศาสตร์​บาง​คน เช่น Richard Dawkins และ David Hand ก็​ตั้ง​ข้อสังเกต​ว่า​ปรากฏการณ์​นี้​อาจ​อธิบาย​ได้​ด้วย confirmation bias และ selection bias — เหตุการณ์​ที่​ไม่​พึง​ประสงค์​เกิด​ขึ้น​ตาม​ความ​น่า​จะ​เป็น​ปกติ แต่​คน​จะ​จดจำ​เฉพาะ​ครั้ง​ที่​มัน​สร้าง​ปัญหา​เท่านั้น

ใน​บริบท​ซอฟต์แวร์ Murphy’s Law ไม่​ได้​บอกว่า​จักรวาล​มี​เจตนา​ร้าย​ต่อ​โปรแกรมเมอร์ แต่​สื่อ​ถึง​ข้อเท็จจริง​เชิง​สถิติ​ง่าย ๆ ว่า: ระบบ​ที่​มี​ขนาด​ใหญ่​พอ มี​ผู้​ใช้​มาก​พอ หรือ​ทำงาน​นาน​พอ จะ​เจอ​ทุก edge case ที่​เป็น​ไป​ได้​ทาง​คณิตศาสตร์​ใน​ที่สุด ไม่​ว่า​จะ​เป็น null reference, race condition, network timeout, disk เต็ม, clock skew, หรือ input ประหลาด​ที่​ผู้​ใช้​พิมพ์​เข้า​มา นัย​ยะ​เชิง​ปฏิบัติ​ของ​กฎ​นี้​คือ:

  • อย่า​คิด​ว่า “คง​ไม่มี​ใคร​ทำ​แบบ​นั้น​หรอก” — ถ้า input นั้น​เป็น​ไป​ได้​ทาง​เทคนิค ใน​ที่สุด​จะ​มี​คน​หรือ​ระบบ​อื่น​ส่ง​มัน​เข้า​มา​จริง
  • ความ​ล้มเหลว​มัก​เกิด​ใน​เวลา​ที่​แย่​ที่สุด — ระหว่าง demo สำคัญ ตอนพีค​โหลด​สูงสุด หรือ​กลาง​ดึก​วัน​หยุด​ยาว​ตอน​ไม่มี​ใคร​เฝ้า​ระบบ เพราะ​นั่น​คือ​ช่วง​ที่​ระบบ​ถูก​ใช้งาน​ใน​รูปแบบ​ที่​ไม่​เคย​ถูก​ทดสอบ​มา​ก่อน หรือ​ถูก​ใช้งาน​หนัก​ผิด​ปกติ
  • การ​ป้องกัน​ล่วงหน้า​ถูก​กว่า​การ​แก้ไข​ทีหลัง — costs ของ​การ​เขียน validation, error handling และ test edge case ตั้งแต่​ต้น ต่ำ​กว่า​การ debug production incident ที่​เกิด​ขึ้น​แล้ว​มาก

กฎ​นี้​จึง​เป็น​เหตุผล​เชิง​ปรัชญา​ที่​หนุนหลัง​แนว​ปฏิบัติ​หลาย​อย่าง​ใน​วิศวกรรม​ซอฟต์แวร์ ตั้งแต่ defensive programming, การ​เขียน​เทส (โดย​เฉพาะ​เทส edge case และ negative case), การ​ทำ code review, ไป​จนถึง​การ​มี rollback plan, monitoring/alerting และ on-call rotation ใน​ระดับ DevOps — ทั้งหมด​นี้​คือ​การ​ยอมรับ​ว่า “มัน​จะ​พัง​แน่ ๆ สัก​วัน” แล้ว​วาง​ระบบ​ให้​รับมือ​ได้ ไม่ใช่​หวัง​ว่า​มัน​จะ​ไม่​พัง

graph TD
    A[Possible failure path exists] --> B{Path guarded}
    B -->|No| C[Eventually triggered in production]
    B -->|Yes| D[Validation or fail fast catches it]
    C --> E[Incident and firefighting]
    D --> F[Contained and logged safely]
  • Windows 98 Blue Screen of Death ต่อ​หน้า​สาธารณะ — วัน​ที่ 20 เมษายน 1998 ที่​งาน COMDEX ชิคาโก ผู้​ช่วย​ของ Bill Gates ชื่อ Chris Capossela สาธิต feature Plug and Play โดย​เสียบ​สแกนเนอร์​เข้า​กับ​เครื่อง​ที่​รัน Windows 98 บน​เวที ผล​คือ​เครื่อง​เด้ง Blue Screen ต่อ​หน้า​ผู้​ชม​นับ​พัน Gates พูด​ติดตลก​ว่า “That must be why we are not shipping Windows 98 yet” เหตุการณ์​นี้​เป็น​ตัวอย่าง​คลาสสิก​ที่​ว่า​ความ​ล้มเหลว​มัก​โผล่​มา​ใน​ช่วง​เวลา​ที่​สำคัญ​และ​ถูก​จับตา​มอง​ที่สุด (demo ต่อ​หน้า​สื่อ) เพราะ​อุปกรณ์​ที่​ไม่​เคย​ผ่าน​การ​ทดสอบ (scanner รุ่น​ที่​ทีม Windows ไม่​เคย​ตรวจสอบ) ถูก​ใช้งาน​ใน​เงื่อนไข​ที่​ไม่​คุ้น​เคย หลัง​เหตุการณ์​นี้ Microsoft ถึง​กับ​สร้าง​ห้อง​ทดสอบ demo โดย​เฉพาะ เพื่อ stress-test อุปกรณ์​ก่อน​ขึ้น​เวที​ทุก​ครั้ง
  • Null reference / unhandled exception ใน production — ทีม​พัฒนา​จำนวน​มาก​เจอ NullReferenceException หรือ undefined is not a function จาก field ที่ “ไม่​น่า​จะ​ว่างเปล่า” ตาม​สมมติฐาน​ตอน​ออกแบบ แต่​เมื่อ​ระบบ​มี​ผู้​ใช้​เป็น​ล้าน ใน​ที่สุด​ก็​มี record ที่ field นั้น​ว่าง​จริง ๆ เพราะ data migration เก่า หรือ integration จาก​ระบบ​ภายนอก​ที่​ส่ง​ข้อมูล​ไม่​ครบ
  • Deploy วัน​ศุกร์ — วัฒนธรรม “no deploy on Friday” ใน​หลาย​ทีม​วิศวกรรม​มา​จาก​ประสบการณ์​ตรง​ว่า ถ้า​มี bug แฝง​อยู่​ใน code ที่​เพิ่ง deploy มัน​จะ​โผล่​ตอน​บ่าย​วัน​ศุกร์ ทำให้​ทีม​ต้อง​แก้ไข​ฉุกเฉิน​ใน​วัน​หยุด​สุด​สัปดาห์​ที่​คน​พร้อม on-call น้อย​ที่สุด — สอดคล้อง​กับ​ข้อสังเกต​ที่​ว่า​ความ​ล้มเหลว​มัก​เกิด​ใน​เวลา​ที่​แย่​ที่สุด
  • Load testing ที่​มอง​ข้าม edge case — ระบบ​ผ่าน​การ​ทดสอบ load ปกติ​มา​ตลอด แต่​ล่ม​เมื่อ​เจอ traffic spike แบบ​เฉพาะ​เจาะจง (เช่น flash sale, ผล​บอล​ออก​พร้อม​กัน​หลาย​ล้าน​คน) เพราะ​เงื่อนไข​นั้น​ไม่​เคย​ถูก​จำลอง​ไว้​ใน​การ​ทดสอบ
  1. เขียน code แบบ defensive ตั้งแต่​ต้น — ตรวจสอบ input, จัดการ null/empty case, ห่อ external call ด้วย try/catch หรือ timeout เสมอ อย่า​รอ​ให้ production บอกว่า​มัน​พัง
  2. Fail fast แทนที่​จะ​ปล่อย​ให้ error ลุกลาม​เงียบ ๆ — ยิ่ง​ตรวจ​พบ​ปัญหา​ใกล้​จุด​กำเนิด​เท่าไร stack trace ก็​ยิ่ง​ชัดเจน และ​ผลกระทบ​ต่อ state ของ​ระบบ​ก็​ยิ่ง​น้อย
  3. เขียน​เทส​ให้​ครอบคลุม edge case ไม่ใช่​แค่ happy path — ทดสอบ input ที่​ผิด​ปกติ, ค่าที่​เป็น​ขอบเขต (boundary), และ​สถานการณ์ concurrency ที่​ไม่​น่า​จะ​เกิด​แต่​เป็น​ไป​ได้​ทาง​เทคนิค
  4. วางแผน​สำหรับ​ตอน​ที่​มัน​พัง​จริง ๆ ไม่ใช่​แค่​พยายาม​ไม่​ให้​มัน​พัง — มี rollback plan, feature flag, monitoring/alerting, และ runbook สำหรับ on-call เพราะ Murphy’s Law บอก​ไว้​แล้ว​ว่าการ​ป้องกัน 100% เป็น​ไป​ไม่​ได้
  5. อย่า demo หรือ deploy feature ที่​ยัง​ไม่​ผ่าน​การ​ทดสอบ​ใน​สภาพ​แวดล้อม​จริง​ต่อ​หน้า​ความ​เสี่ยง​สูง — บทเรียน​จาก COMDEX 1998 คือ​ให้ stress-test สถานการณ์ demo ใน​สภาพ​เดียว​กับ​ที่​จะ​ใช้​จริง​ก่อน​เสมอ
  6. มอง​กฎ​นี้​เป็น​เครื่องมือ​คิด​เชิง​ความ​น่า​จะ​เป็น ไม่ใช่​โชค​ชะตา — ใช้​มัน​เพื่อ​กระตุ้น​ให้​ทีม​ถาม​คำถาม​ว่า “ถ้า​สิ่ง​นี้​ผิดพลาด จะ​เกิด​อะไร​ขึ้น และ​เรา​จัดการ​อย่างไร” มากกว่า​จะ​ยอม​แพ้​ด้วย​ความ​รู้สึก​สิ้น​หวัง