2 คะแนน โดย GN⁺ 2025-01-14 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • Debugging ของ David J. Agans ว่าด้วย พื้นฐานการดีบัก สำหรับการค้นหาสาเหตุและแก้ไขหลังพบบั๊ก โดยมอบหลักการที่ทั้งนักพัฒนามือใหม่ ระดับกลาง และผู้มีประสบการณ์สามารถย้อนกลับมาทบทวนได้ซ้ำๆ
  • หนังสือประกอบด้วย กฎ 9 ข้อ ที่เชื่อมโยงความเข้าใจระบบ การทำให้ความล้มเหลวเกิดซ้ำ การสังเกต การแบ่งแยกปัญหา การควบคุมการเปลี่ยนแปลง การเก็บร่องรอยตรวจสอบ การตรวจสมมติฐาน มุมมองจากภายนอก และการยืนยันผลการแก้ไข เข้ากับกรณีศึกษาจากงานจริง
  • แม้จะมีทั้งเทคโนโลยีเก่าและกรณีตัวอย่างนอกโลกคอมพิวเตอร์ แต่แก่นสำคัญไม่ใช่เครื่องมือเฉพาะทาง หากเป็น วิธีคิดเพื่อค่อยๆ ตีวงปัญหาให้แคบลง จึงประยุกต์ใช้ได้กับการดีบักทั้งฮาร์ดแวร์และซอฟต์แวร์
  • สำหรับบั๊กที่รับมือยากอย่างปัญหาที่เกิดเป็นครั้งคราว คำแนะนำใน Make it Fail มีประโยชน์เป็นพิเศษ แต่ก็น่าเสียดายที่ไม่ได้พูดถึงคำว่า Heisenbug โดยตรง
  • ต่างจากหนังสือที่สอนการใช้ GDB หรือการเขียนเทสต์ หนังสือเล่มนี้เน้น ภาพใหญ่ของการดีบัก จึงควรเสริมด้วยแหล่งข้อมูลอื่นสำหรับวิธีใช้เครื่องมือและ regression test

ปัญหาที่หนังสือเล่มนี้มุ่งแก้

  • Debugging: The 9 Indispensable Rules for Finding Even the Most Elusive Software and Hardware Problems ของ David J. Agans ว่าด้วยกระบวนการค้นหาสาเหตุและแก้ไขจริงหลังจากตรวจพบบั๊กแล้ว
  • แทนที่จะเน้นเทคโนโลยีหรือเครื่องมือเฉพาะ หนังสือเล่มนี้สรุป หลักการดีบัก ที่จำเป็นสำหรับ นักพัฒนาซอฟต์แวร์และฮาร์ดแวร์คอมพิวเตอร์
  • เหมาะอย่างยิ่งสำหรับนักพัฒนามือใหม่และระดับกลาง และยังช่วยให้ผู้มีประสบการณ์รื้อฟื้นพื้นฐานที่มักหลุดไปในสถานการณ์เร่งด่วน
  • จุดแข็งคือการกลั่นประสบการณ์ดีบักที่ปกติต้องเรียนรู้จากการลงมือทำ ให้กลายเป็นหลักการและกรณีศึกษาอย่างกระชับ

กฎการดีบัก 9 ข้อ

  • จงเข้าใจระบบ

    • อ่านคู่มือ ทำความเข้าใจโครงสร้างทั้งหมด และเข้าใจทั้งหลักการพื้นฐานกับพฤติกรรมรายละเอียด
    • ตรวจดูไปพร้อมกันว่าเครื่องมือที่ใช้แสดงอะไร และซ่อนอะไรไว้บ้าง
  • จงทำให้มันล้มเหลว

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

    • ก่อนจะเริ่มซ่อมแบบซับซ้อนจากการคาดเดา ให้หา ข้อมูลที่สังเกตได้จริง ก่อน
    • ตรวจดูความล้มเหลวและรายละเอียดต่างๆ พร้อมสร้างการวัดจากภายในหรือเพิ่มการวัดจากภายนอก
    • อย่าหลีกเลี่ยงการขุดลึกลงไป แต่ต้องระวังผลแบบ Heisenberg ที่การสังเกตเองอาจเปลี่ยนพฤติกรรมการทำงานได้
    • ใช้การคาดเดาเป็นเพียงเครื่องมือช่วยตีวงการค้นหาให้แคบลง ไม่ใช่ข้อสรุป
  • แบ่งแล้วพิชิต

    • ใช้การประมาณค่าแบบต่อเนื่อง (successive approximation) เพื่อลดขอบเขตการค้นหา และตัดสินว่าบั๊กอยู่ฝั่งไหน
    • ใช้รูปแบบการทดสอบที่สังเกตได้ง่าย และเริ่มจากสภาวะที่ผิดเพื่อค่อยๆ หาสาเหตุให้แคบลง
    • กำจัดบั๊กที่รู้อยู่แล้วและสัญญาณรบกวนออกก่อน เพื่อให้สิ่งที่ต้องสืบสวนง่ายขึ้น
  • เปลี่ยนทีละอย่าง

    • แยกปัจจัยหลักออกจากกัน และทำความเข้าใจก่อนว่าผิดตรงไหนก่อนลงมือแก้
    • เปลี่ยนการทดสอบทีละอย่าง และเปรียบเทียบกับกรณีปกติ
    • ตรวจสอบว่านับจากครั้งสุดท้ายที่มันยังทำงานได้ มีอะไรเปลี่ยนไปบ้าง
  • จงเก็บร่องรอยตรวจสอบไว้

    • บันทึกว่าได้ทำอะไรบ้าง ตามลำดับไหน และผลเป็นอย่างไรในรูปของ audit trail
    • แม้รายละเอียดเล็กน้อยที่ดูไม่สำคัญก็อาจเป็นสาเหตุได้ จึงควรเชื่อมโยงเหตุการณ์ต่างๆ แล้วจดไว้
    • audit trail ของกระบวนการออกแบบเองก็ช่วยในการทดสอบได้ จึงต้องบันทึกไว้ด้วย
  • ตรวจปลั๊กก่อน

    • ตั้งข้อสงสัยกับสมมติฐานที่คิดว่าแน่นอน และกลับไปตรวจใหม่ตั้งแต่ต้น
    • แม้แต่เครื่องมือที่ใช้ค้นหาปัญหาเองก็ต้องรวมอยู่ในขอบเขตของสิ่งที่ต้องทดสอบ
  • หามุมมองใหม่

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

    • หลังแก้ไขแล้ว ต้องตรวจสอบว่าแก้ได้จริงหรือไม่ และยืนยันว่าการเปลี่ยนแปลงของเรากำจัดสาเหตุที่แท้จริงได้จริง
    • ปัญหาไม่ได้หายไปเอง ดังนั้นต้องแก้ทั้งสาเหตุและกระบวนการร่วมกัน

วิธีที่กรณีศึกษาช่วยให้หลักการมีชีวิต

  • ถ้ามองแค่รายการกฎอาจดูแห้งแล้ง แต่คำอธิบายอย่างละเอียดและ เรื่องเล่ากรณีศึกษา ช่วยดึงหลักการลงสู่สถานการณ์จริง
  • หลายกรณีลงลึกถึงรายละเอียดทางเทคนิค จึงอาจหนักไปสำหรับผู้อ่านบางคน
  • แม้จะมีตัวอย่างที่ใช้เทคโนโลยีเก่า แต่หัวใจอยู่ที่หลักการ ไม่ใช่เทคโนโลยีเฉพาะ จึงไม่ใช่ปัญหาใหญ่
  • ไม่ใช่ทุกกรณีศึกษาจะเกี่ยวกับคอมพิวเตอร์ และยังมีกรณีสนุกๆ เกี่ยวกับการเดินสายไฟในบ้านด้วย
  • หากไม่มีพื้นฐานฮาร์ดแวร์และซอฟต์แวร์คอมพิวเตอร์เลย อาจตามตัวอย่างจำนวนมากได้ยาก
  • หลังคำอธิบายของแต่ละกฎ ยังมีเรื่องเล่าที่ใช้หลายกฎร่วมกัน แบบฝึกหัดง่ายๆ สำหรับผู้อ่าน เคล็ดลับจาก help desk และคำกล่าวสรุปตามมา

จุดเด่นและข้อจำกัดที่เห็นชัด

  • หลักการ “หยุดคิดแล้วดู” สำคัญเป็นพิเศษ
    • เพราะหลายคนพยายามแก้ปัญหาจากการคาดเดาก่อนจะรวบรวมข้อมูลที่จะใช้พิสูจน์หรือหักล้างสมมติฐาน
  • ถ้ายังไม่ได้แก้ ก็แปลว่ายังไม่หาย” ก็เป็นอีกหลักการที่ทิ้งความประทับใจอย่างมาก
    • เพราะไม่ใช่แค่ต้องตรวจว่าแก้แล้วหรือยัง แต่ต้องรู้ด้วยว่าอะไรคือสาเหตุ และทำไมมันจึงถูกแก้ได้
  • ประเด็น “กระตุ้นให้ความล้มเหลวเกิดขึ้น อย่าจำลองความล้มเหลว” อธิบายได้ไม่ชัดเท่าส่วนอื่นของหนังสือ แต่ก็ยังเป็นจุดที่ควรค่าแก่การทำความเข้าใจ
  • ปัญหาที่เกิดเป็นครั้งคราวมักจัดการยากที่สุด และหนังสือเล่มนี้ให้คำแนะนำตรงไปตรงมาในการรับมือผ่าน Make it Fail
  • มีการกล่าวถึง Heisenberg แต่ไม่ได้พูดถึงคำที่ใช้กันบ่อยในงานพัฒนาซอฟต์แวร์อย่าง Heisenbug
    • Heisenbug หมายถึงบั๊กที่หายไปหรือเปลี่ยนพฤติกรรมเมื่อพยายามสังเกตหรือแยกมันออกมาตรวจ

ความต่างจากแหล่งข้อมูลอื่น

  • หนังสือเล่มนี้แตกต่างจากคู่มือเครื่องมือหรือหนังสือเรื่องเทสต์ตรงที่เน้น หลักการพื้นฐานของการดีบัก เป็นศูนย์กลาง
  • Debugging with GDB: The GNU Source-Level Debugger ของ Richard Stallman และคนอื่นๆ อธิบายเทคนิคหรือคำสั่งของเครื่องมือเฉพาะเป็นหลัก
  • แม้จะมีแหล่งข้อมูลที่รวมคำแนะนำทั่วไปอย่าง Guide to Faster, Less Frustrating Debugging ของ Norman Matloff แต่ก็ยังไม่ครอบคลุมกว้างเท่าหนังสือของ Agans
  • หนังสือด้านเทสต์อย่าง Software Testing Techniques ของ Boris Beizer เน้นการเขียนเทสต์เพื่อค้นหาบั๊ก ขณะที่วิธีแก้บั๊กที่พบแล้วถูกกล่าวถึงน้อยกว่า
  • หลังพบบั๊กแล้ว ควรเพิ่มเทสต์ของบั๊กนั้นเข้าไปใน regression test suite แต่เรื่องการทดสอบและ regression test อยู่นอกขอบเขตของหนังสือเล่มนี้

แหล่งเสริมและจุดที่น่าเสียดาย

  • เว็บไซต์คู่หนังสือ debuggingrules.com มีลิงก์ข้อมูลที่เกี่ยวข้อง และโปสเตอร์กฎทั้ง 9 ข้อที่ดาวน์โหลดไปพิมพ์ได้
  • น่าเสียดายที่ รายการกฎย่อยทั้งหมด ซึ่งสำคัญต่อการทำความเข้าใจกฎหลัก ไม่ได้ถูกรวบรวมไว้ในหน้าเดียวทั้งในหนังสือหรือบนเว็บไซต์
  • ถ้ามีคำแนะนำและตัวอย่างที่เฉพาะเจาะจงกว่านี้เกี่ยวกับเครื่องมือทั่วไปและประเภทปัญหา เช่น symbolic debugger, digital logic probe หรือ ddd on gdb ก็จะมีประโยชน์มากขึ้น
  • ดูเหมือนว่าจะควรมีหนังสืออีกเล่มที่ขยายกฎชุดเดียวกันนี้ไปสู่การแก้ปัญหาทั่วไปนอกโลกคอมพิวเตอร์ แต่กรณีศึกษาของหนังสือเล่มนี้มีความเทคนิคมากเกินไปสำหรับผู้อ่านที่ไม่ใช่สายคอมพิวเตอร์
  • หลักการพื้นฐานเหล่านี้แม้ภายนอกจะดูเหมือนสามัญสำนึก แต่ผู้เริ่มต้นจำเป็นต้องเรียนรู้ และผู้มีประสบการณ์ก็ต้องคอยทบทวนซ้ำๆ ซึ่งหนังสือเล่มนี้เหมาะกับทั้งการเรียนรู้และการทบทวนดังกล่าว

1 ความคิดเห็น

 
GN⁺ 2025-01-14
ความคิดเห็นบน Hacker News
  • ผมคิดว่าสิ่งที่เป็นพิษที่สุดคือความเย้ายวนที่จะเติม “การแก้ไข” ลงไปใน โค้ดที่พังอยู่แล้ว เพื่อให้มันทำงานได้
    โค้ดที่พังมีจุดที่เปลี่ยนได้มากเกินไปจนแก้ยาก และการทำให้โค้ดที่ทำงานอยู่พังนั้นง่ายกว่ามาก
    วิธีไล่เปลี่ยนหลอดไฟทีละดวงเมื่อไฟคริสต์มาสทั้งสายไม่ติด จะล้มเหลวถ้ามีหลอดเสียหลายดวง
    แทนที่จะทำแบบนั้น ควรเริ่มจาก ตัวอย่างขั้นต่ำที่ทำงานได้ แล้วค่อย ๆ เพิ่มเข้าไปจนเจอจุดที่เกิดข้อผิดพลาด และในทางปฏิบัติ บ่อยครั้งการเริ่มใหม่ตั้งแต่ต้นกลับช่วยประหยัดเวลาได้มากกว่า

    • ถ้าเป้าหมายหลักไม่ใช่การเรียนรู้จากปัญหา การ เปลี่ยนไฟทั้งสาย แทนที่จะตรวจหลอดทีละดวงอาจเป็นวิธีที่เร็วที่สุด
      เคยมีกรณีปัญหาในโปรดักชันที่จับได้ยาก สมาชิกทีมบางคนเขียนรูทีนที่มีปัญหาใหม่ และเวอร์ชันที่เขียนใหม่นั้นถูกปล่อยใช้งานก่อน ในขณะที่คนอื่น ๆ ยังดีบักอยู่
      อย่างน้อยครั้งหนึ่ง เราไม่สามารถใช้เวลากับปัญหาที่ “แก้แล้ว” ได้ไม่จำกัด จึงไม่เคยหาบั๊กเดิมเจอจนจบ
  • กฎข้อ 0 คือ อย่าตื่นตระหนก
    เดดไลน์และลูกค้าที่โกรธจะขัดขวางการคิดอย่างชัดเจน ดังนั้นผู้จัดการที่ดีและไว้ใจได้ควรกันวิศวกรออกจากแรงกดดันนั้น เพื่อให้พวกเขาโฟกัสกับการแก้ปัญหาได้

    • เห็นด้วยอย่างยิ่ง ตอนเข้าเวรออนคอล SEV-2 แล้วผู้จัดการของทีมที่ได้รับผลกระทบเข้ามากันเต็มสาย ต่างคนต่างแทรก มันน่าหงุดหงิดมาก
      ผู้จัดการที่ดีคนหนึ่งย้ายพวกเราไปอีกสายแล้วบอกว่า “ไม่ต้องสนใจที่คนพวกนั้นพูด ตั้งสมาธิไป เดี๋ยวผมจัดการเอง” หลังจากนั้นความเคารพที่มีต่อผู้จัดการคนนั้นก็เพิ่มขึ้นมาก
    • มีเรื่องหนึ่งในหนังสือว่า บน เรือดำน้ำนิวเคลียร์ จะมีแท่งทองเหลืองอยู่หน้าหน้าปัดและด้ามจับต่าง ๆ และวิศวกรถูกฝึกว่าเมื่อเกิดปัญหา อย่าเอื้อมไปแตะด้ามจับทันที แต่ให้ “จับแท่งนั้นไว้” ก่อน
    • ช้าคือราบรื่น และราบรื่นคือเร็ว
      ถ้าไม่มีเวลาทำให้ถูกต้อง แล้วทำไมถึงคิดว่าจะมีเวลาทำซ้ำสองรอบ
    • อดีตหัวหน้าของผมเรียกบทบาทของตัวเองว่า “ร่มกันอึ”
      หมายถึงบทบาทที่คอยกันสิ่งที่หล่นลงมาจากข้างบน เพื่อให้วิศวกรโฟกัสกับงานหลักได้
    • หลักการที่ตามมาคือ ต้องมี แผนโรลแบ็ก ที่ดีเสมอ
      ถ้าย้อนกลับไปยังเวอร์ชันที่ทำงานได้ แล้วดีบักโดยไม่ต้องเจอแรงกดดันระดับวิกฤตได้ จะดีกว่ามาก
  • สำหรับข้อ 4 “แบ่งแล้วพิชิต” git bisect ช่วยได้มาก
    ถ้ามีคอมมิตที่ปกติหนึ่งอัน และในบรรดาคอมมิตถัดมาอีกหลายสิบถึงหลายร้อยอันมีคอมมิตเสียอยู่หนึ่งอัน ก็สามารถตีวงคอมมิตหรือโค้ดที่เป็นปัญหาให้แคบลงได้ในไม่กี่ขั้น
    ตัวอย่างการใช้งานอยู่ที่ https://nickjanetakis.com/blog/using-git-bisect-to-help-find...
    ผมเคยใช้วิธีนี้ตีวงปัญหาในโค้ดเบสขนาดใหญ่ที่ไม่คุ้นเคยได้อย่างรวดเร็วระหว่างให้คำปรึกษาแบบสด ๆ ไม่อย่างนั้นขอบเขตที่อาจพังได้คงกว้างเกินไปมาก

    • เพราะ git bisect ผมจึงรักษาวินัยว่า ทุกคอมมิตที่เข้าไปในแบรนช์ “จริง” ต้อง build ได้เป็นรายคอมมิต ผ่านเทสต์ที่รู้จักในเวลานั้น และตามความรู้ที่มีควร deploy ได้
      ผมให้ความสำคัญกับเรื่องนี้มากกว่าหลักการอย่างการเก็บทุกการกดคีย์ไว้ หรือคงคอมมิต “Fixes.” สุดท้ายเอาไว้ เพราะหลักการแบบนั้นทำให้การค้นหาแบบทวิภาคใช้การไม่ได้
      ไม่ได้ใช้บ่อยนัก แต่กับบั๊กที่ใหญ่และลึกลับที่สุด แค่ใช้ถูกสักครั้งก็ให้เบาะแสที่เทียบเท่าหลายวันในคราวเดียว จึงคุ้มค่ามากพอ
    • ตอนดีบักปัญหาการตั้งค่าเครือข่ายในยุค 1990 เพื่อนร่วมงานที่มีประสบการณ์มากกว่าสอนหลักการทั่วไปที่อยู่เบื้องหลัง git bisect ให้
      คือวิธี เปรียบเทียบระบบที่พังกับระบบที่ทำงานได้ แล้วกำจัดความแตกต่างอย่างเป็นระบบเพื่อหาข้อบกพร่อง
      ใช้ได้ไม่ใช่แค่กับซอฟต์แวร์หรือฮาร์ดแวร์ และเมื่อก่อนตอนมีเจ็ตสกีรุ่นเดียวกันสองลำ การซ่อมลำหนึ่งโดยเทียบกับอีกลำก็ช่วยได้มาก
    • แก่นสำคัญตรงนี้ไม่ใช่ตัว git bisect เอง แต่เป็นหลักการ ค้นหาแบบทวิภาค ที่ทั่วไปกว่า
      ใช้ได้ไม่เพียงกับช่วงของคอมมิต แต่ยังใช้แบ่งพื้นที่ของระบบได้ด้วย
      ตัวอย่างเช่น ถ้าเวิร์กโฟลว์ 10 ขั้นตอนพัง ก็ตรวจว่าขั้นที่ 5 ยังปกติไหม หรือค่อย ๆ ตีวงว่าเป็นปัญหาฮาร์ดแวร์หรือไม่ใช่
      เรื่องนี้สำคัญเป็นพิเศษเมื่อสาเหตุของปัญหาอาจไม่ใช่คอมมิตของโค้ดในรีโพซิทอรีที่กำลัง bisect อยู่
    • bisect ยอดเยี่ยม แต่ต้องแยกระหว่าง “กฎ” ซึ่งเป็น ปรัชญาและวิธีคิด ของหนังสือเล่มนี้ กับ “เครื่องมือ” ซึ่งเป็นคำแนะนำเชิงปฏิบัติ
      คนที่เริ่มจากคำถามว่า “จะใช้เครื่องมืออะไรดี” เสียเปรียบคนที่เริ่มจาก “อันนี้เมื่อก่อนมันไม่ได้ทำงานอยู่เหรอ?”
      โลกเต็มไปด้วยเครื่องมือ และถ้าพยายามเก็บเครื่องมือทั้งหมดไว้ในหัวก็คงเป็นบ้าไปก่อน ดังนั้นรับเอาปรัชญาไว้ก่อนจะดีกว่า
    • ขอเสริมบทความที่เขียนเกี่ยวกับ git bisect run เป็นเครื่องมือเล็ก ๆ ที่น่าทึ่งจริง ๆ
      https://andrewrepp.com/git_bisect_run
  • ต้องแน่ใจว่ากำลังแก้ ไฟล์ที่ถูกต้อง บน เครื่องที่ถูกต้อง

    • เป็นอีกรูปแบบหนึ่งของ “ตรวจปลั๊กก่อน”
      ทุกวันนี้ผมมักเพิ่มบรรทัดที่จงใจให้เกิดข้อผิดพลาดร้ายแรงชั่วคราว เพื่อยืนยันว่าไฟล์ที่แก้อยู่ถูกต้อง และในบางกรณีก็ยืนยันว่าบรรทัดถูกต้องด้วย
    • มีแต่พระเจ้าเท่านั้นที่รู้ว่าเราเสียเวลาไปเท่าไรกับการแก้ไฟล์ที่ถูก generate ขึ้นมา ไฟล์คนละเวอร์ชัน หรือแค่ลืมบันทึก
    • หลักการสำคัญที่สุดที่ผมบอกตัวเองและคนที่ผมสอนเสมอคือ ให้ยืนยันว่า โค้ดที่กำลังรันอยู่ คือโค้ดที่ผมคิดว่าเป็นจริง ๆ
    • ดังนั้นก่อนอื่นต้องทำให้มัน พังในแบบที่ต่างออกไป
      เพื่อยืนยันว่าการเปลี่ยนแปลงของเรามีผลจริง
  • มีกฎเพิ่มเติมอยู่
    “ทั้งหมดเป็นความผิดของฉันเอง”: อาจเป็นบั๊กของคอมไพเลอร์หรือข้อผิดพลาดของฮาร์ดแวร์ก็ได้ แต่พบได้น้อยมาก ดังนั้นก่อนอื่นควรสงสัยการเปลี่ยนแปลงในโค้ดของตัวเองก่อน
    “ถ้าเจอบั๊ก ให้ตามหาครอบครัวและเพื่อน ๆ ของมันด้วย”: ต้องคิดและตรวจสอบว่าสิ่งประเภทเดียวกันอาจเกิดขึ้นที่ไหนอีกบ้าง
    “ปรับให้เหมาะที่สุดเพื่อผู้ใช้ก่อน โปรแกรมเมอร์ที่ดูแลรักษาเป็นลำดับสอง และคอมพิวเตอร์เป็นลำดับสุดท้าย”

    • กฎข้อแรกเป็นที่รู้จักใน The Pragmatic Programmer ว่า “select ไม่ได้พัง
      มีสรุปอยู่ที่ https://blog.codinghorror.com/the-first-rule-of-programming-...
    • แนวทางที่ว่า “ลองสร้าง test case ที่รายงานไปยัง mailing list ได้ เพราะอาจเป็นบั๊กก็ได้” บางครั้งก็มีประโยชน์
      โดยปกติระหว่างกระบวนการลดโค้ดที่ทำให้เกิดข้อผิดพลาดให้เหลือกรณีที่ง่ายขึ้น จะพบว่าบั๊กอยู่ในตรรกะของตัวเอง
      มีครั้งสองครั้งที่เหลือผลลัพธ์ที่ควรรายงานให้นักพัฒนาจริง ๆ และส่วนใหญ่เป็นไลบรารีที่มีผู้ใช้ไม่เกินหลักร้อยจึงมีการทดสอบไม่มาก
    • ผมมีทัศนคติว่า “เป็นความผิดของฉันเอง” อยู่เสมอ แต่ตอนที่ Linux workstation ของผม crash อยู่เรื่อย ๆ เพราะ i9-13900K นั้น พูดตรง ๆ ว่าน่าอับอายมาก
      สุดท้ายพอรู้ว่าไม่ใช่ข้อผิดพลาดในโค้ดที่ดูเป็นไปไม่ได้ แต่เป็นปัญหาของ CPU ก็โล่งใจมาก
    • การสมมติว่าโค้ดของตัวเองผิดเป็นทางเลือกที่ดีต่อสุขภาพกว่า
      ถึงอย่างนั้น สิ่งที่ดีที่สุดคือทำ binary search ไล่หาสายโซ่เหตุ-ผลเพิ่มอีกสักสองสามรอบเพื่อให้แน่ใจ
    • เกี่ยวกับ “ครอบครัวและเพื่อน ๆ” มีอยู่หลายครั้งที่ระหว่างแก้ปัญหารอบข้างเล็ก ๆ น้อย ๆ ที่ดูเหมือนไม่เกี่ยวข้องกัน บั๊กที่ตามหาอยู่ก็เผยตัวออกมา
  • คำแนะนำที่ว่า “จงเข้าใจระบบ: อ่านคู่มือ อ่านทุกอย่างอย่างลึกซึ้ง รู้พื้นฐาน รู้ roadmap เข้าใจเครื่องมือ และค้นหารายละเอียด” ฟังดูค่อนข้างแปลก
    ถ้ามีบั๊กในโค้ด มันดูเหมือนหมายความว่าต้องอ่านคู่มือ 700 หน้าของไลบรารีที่ใช้ทั้งหมดก่อน อ่านหนังสือที่เกี่ยวข้องอีก 7 เล่ม แล้วอีกหนึ่งหรือสองเดือนค่อยไปดูบั๊ก
    ผมสงสัยว่ามีโปรแกรมเมอร์สักคนไหมที่ทำตามคำแนะนำนี้จริง ๆ

    • บทความนี้เขียนขึ้นในปี 2004 ปีเดียวกับ Google IPO
      Atwood กับ Spolsky สร้าง Stack Overflow ในปี 2008 และเป็นยุคที่ผู้คนรู้จักหนังสือด้วยชื่ออย่าง “Camel book” และมีความรู้อยู่แล้ว
      0. https://stackoverflow.blog/2021/12/14/podcast-400-an-oral-hi...
      1. https://www.perl.com/article/extracting-the-list-of-o-reilly...
    • ตรงนี้ดูเหมือนควรตีความต่างออกไปเล็กน้อย
      “อ่านทุกอย่างอย่างลึกซึ้ง” ไม่ได้จำเป็นต้องหมายความว่า “อ่านคู่มือ 700 หน้าทั้งหมดของไลบรารีที่ใช้ก่อน”
      ถ้ามีปัญหากับ git bisect แทนที่จะเอาเศษคำตอบจาก Stack Overflow มาต่อกันสองสามชิ้น ก็สามารถทำความเข้าใจหัวข้อนั้นให้ลึกขึ้นอีกหน่อยได้ที่ https://git-scm.com/docs/git-bisect
    • โดยแก่นแล้วเป็นคำพูดที่ถูกต้อง
      เพียงแต่ความผิดพลาดคือการคิดว่าผลงานของการทำงานหลายเดือนคือการแก้บั๊กเดียวแบบคร่าว ๆ
      เป้าหมายคือการแก้บั๊กประเภทนั้นให้หมดเท่าที่ทำได้จริง ๆ และทำให้ไม่ต้องเขียนมันขึ้นมาตั้งแต่แรก
      ทางเลือกคือกระโดดร่มลงไปในระบบที่ไม่รู้จัก แตะนั่นแตะนี่โดยไม่เข้าใจ พอ test เป็นสีเขียวก็เปิด PR แล้วหวังว่าจะไม่ได้ทำให้พังยิ่งกว่าเดิม ซึ่งการต้องทำแบบนั้นเป็นกิจวัตรแทบจะเป็นฝันร้าย
      อีกอย่าง ถ้าคู่มือของไลบรารีที่ใช้อยู่มี 700 หน้า ก็มีความเป็นไปได้สูงว่าคุณอาจกำลังใช้ไลบรารีผิดตัว
  • ในฐานะขั้นตอนที่ 10 ไม่ควรเพิ่มบั๊กเข้าไปใน CI test เพื่อป้องกัน regression หรือ
    ต้องตรวจสอบว่าก่อนแก้ CI ล้มเหลว และหลังแก้แล้วผ่าน

    • โปรเจกต์ที่เป็น repository JavaScript ล้วนที่ใหญ่ที่สุดที่ผมเคยทำงานด้วย ขนาดประมาณ 150,000 บรรทัด มีกฎนี้อยู่ และมันช่วยชีวิตจริง ๆ
      โดยเฉพาะเพราะมี commit ที่เก่ากว่า 5 ปี และเพราะเป็น component/library จึงมี hack แปลก ๆ สำหรับ IE อยู่ไม่น้อย
    • ไม่ได้คิดว่าคุ้มค่าเสมอไป
      บาง test ใช้เวลานานหรือซับซ้อนในการเขียน และยังต้องดูแลรักษา อีกทั้งต้องยอมรับด้วยว่าชุด test ไม่สามารถตรวจสอบเงื่อนไขขอบเขตทั้งหมดได้
      นั่นอาจหมายความว่าบั๊กที่ไปถึง production อาจกลับมาเกิดอีก แต่ถ้าเป็นความผิดพลาดง่าย ๆ ก็อาจไม่ได้มีโอกาสเกิดซ้ำสูงกว่าความผิดพลาดที่อาจเกิดขึ้นอีกเป็นร้อยแบบ
      สุดท้ายก็ขึ้นอยู่กับสถานการณ์ และการเขียน test ไม่ได้ฟรี
    • โดยทั่วไปกว่านั้น ควรทำ documentation ไว้
      เห็นมานับครั้งไม่ถ้วนว่าต้นเหตุเชิงลึกถูกเปิดใช้งานอีกครั้งจนปัญหาเดิมกลับมา หรือไม่มีใครรู้ว่าผมแก้ไปแล้ว ทุกคนจึงยังใช้ workaround ต่อไปราวกับบั๊กยังอยู่
      แม้หลังจากไปถึงจุด “แก้แล้ว!” การทิ้งบันทึกสั้น ๆ และ root cause analysis ไว้ก็ช่วยคนอื่นได้
    • แล้วจะทำอย่างไรกับ test สำหรับการแก้บั๊กที่ผ่านมาหลายปีแล้ว
      หลังจาก test สะสมมานาน CI จะรันได้เร็วแค่ไหน และในระยะยาวการเก็บไว้ต่อไปยังมีความหมายอยู่หรือไม่
  • หากอยากปลูกฝังวิธีคิดแบบนี้ให้เด็ก ๆ ให้ตัวเอง หรือให้คนอื่น ๆ อย่างน้อยก็ขอแนะนำสิ่งต่อไปนี้
    The Martian by Andy Weir https://en.wikipedia.org/wiki/The_Martian_(Weir_novel)
    https://en.wikipedia.org/wiki/Zen_and_the_Art_of_Motorcycle_...
    https://en.wikipedia.org/wiki/The_Three-Body_Problem_(novel)
    To Engineer Is Human - The Role of Failure in Successful Design By Henry Petroski
    https://pressbooks.bccampus.ca/engineeringinsociety/front-ma...
    https://en.wikipedia.org/wiki/Surely_You%27re_Joking,_Mr._Fe...!

    • เห็นด้วย คิดว่า Zen and the Art of Motorcycle Maintenance ถ่ายทอดทักษะการแก้ปัญหาได้ดีที่สุด
      โดยเฉพาะแนวคิดเรื่อง “gumption traps” นั้นดีมาก
      ถ้าตกอยู่ในกับดักของความแข็งทื่อทางคุณค่า ยังไงก็ต้องช้าลงอยู่แล้ว จึงควรตั้งใจชะลอความเร็วลง ย้อนกลับไปดูจุดที่ผ่านมาว่าสิ่งที่เราเคยคิดว่าสำคัญนั้นสำคัญจริงหรือไม่
      การแค่มองเครื่องจักรอยู่สักพักก็ไม่ใช่เรื่องผิด และประโยคที่ว่า หากเฝ้าดูเหมือนมองสายเบ็ด ก็จะมีช่วงเวลาที่ข้อเท็จจริงเล็ก ๆ ข้อหนึ่งค่อย ๆ ถามว่าเราสนใจมันไหมนั้น แทบจะเป็นหลักในการใช้ชีวิตเลย
    • ไม่แน่ใจว่าส่วนไหนของ Three Body Problem ที่เกี่ยวข้องกับการดีบัก การแก้ปัญหา หรือการวางแผน
      มองว่าเหตุการณ์ต่าง ๆ แค่เกิดขึ้นจากการกระโดดทางตรรกะอย่างหยาบ ๆ และจริง ๆ แล้วใกล้เคียงกับแฟนตาซีที่คลุมทับด้วยการเล่นคำทางวิทยาศาสตร์แบบบางมาก ๆ
  • เมื่อหลายปีก่อนเคยเขียนบทความคล้าย ๆ กันไว้ ตอนนั้นยังไม่ได้อ่านหนังสือต้นฉบับที่กล่าวถึงในนี้
    https://explog.in/notes/debugging.html
    zine เรื่องการดีบักของ Julia Evans ก็ดีมากเช่นกัน: https://wizardzines.com/zines/debugging-guide/

  • แม้จะดีบักสำเร็จแล้ว งานก็ยังไม่จบ
    แก่นของ “Three Questions About Each Bug You Find” <http://www.multicians.org/thvv/threeq.html> มีอยู่สามข้อ
    ข้อผิดพลาดนี้มีอยู่ที่อื่นด้วยหรือไม่ บั๊กถัดไปที่ซ่อนอยู่เบื้องหลังบั๊กนี้คืออะไร และควรทำอะไรเพื่อป้องกันบั๊กแบบนี้