ทำไม Test-Driven Development ล้มเหลวกับ Sudoku: ข้อจำกัดของระเบียบวิธีการเขียนโปรแกรม

ทีมบรรณาธิการ BigGo
ทำไม Test-Driven Development ล้มเหลวกับ Sudoku: ข้อจำกัดของระเบียบวิธีการเขียนโปรแกรม

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

เรื่องเล่าของตัวแก้ปัญหา Sudoku สองแบบ

Ron Jeffries ผู้สนับสนุน Test-Driven Development (TDD) อย่างเด่นชัด ได้พยายามสร้างตัวแก้ปัญหา Sudoku โดยใช้ระเบียบวิธีที่เขาชื่นชอบ แม้จะมีบล็อกโพสต์หลายเรื่องและความพยายามอย่างกว้างขวางเป็นเวลา 20 ปี แนวทางของเขาก็ยังดิ้นรนที่จะสร้างโซลูชันที่สวยงาม ในขณะเดียวกัน Peter Norvig หัวหน้าฝ่ายวิจัยของ Google และผู้เชี่ยวชาญด้าน AI ได้แก้ปัญหาเดียวกันด้วยโค้ดที่สะอาดและเป็นระบบประมาณ 20 บรรทัด

ความแตกต่างนั้นชัดเจนมาก Jeffries เข้าหาปัญหาแบบค่อยเป็นค่อยไป เขียนเทสต์ก่อนแล้วสร้างฟังก์ชันการทำงานทีละชิ้น อย่างไรก็ตาม วิธีการนี้นำเขาไปสู่เส้นทางที่ซับซ้อนโดยไม่มีความเข้าใจที่ชัดเจนเกี่ยวกับโครงสร้างของปัญหาพื้นฐาน ในทางกลับกัน Norvig วิเคราะห์ปัญหาระดับสูงก่อน ระบุว่าเป็นปัญหา constraint satisfaction problem และใช้เครื่องมืออัลกอริทึมที่เหมาะสม

Constraint Satisfaction Problem (CSP): ปัญหาทางคณิตศาสตร์ที่คุณต้องหาค่าสำหรับตัวแปรที่ตอบสนองกฎหรือข้อจำกัดบางอย่าง

การเปรียบเทียบแนวทางการเขียนโปรแกรม:

  • Ron Jeffries (TDD): โพสต์บล็อกหลายโพสต์ การทำซ้ำมากกว่า 20 ปี แนวทางแบบเพิ่มทีละน้อยที่ซับซ้อน ดิ้นรนเพื่อเข้าถึงโซลูชันที่สง่างาม
  • Peter Norvig (ความรู้เฉพาะด้าน): โค้ดประมาณ 20 บรรทัด การวิเคราะห์อย่างเป็นระบบ แนวทางการแก้ปัญหาด้วยข้อจำกัด โซลูชันที่สะอาดและมีประสิทธิภาพ

ปัญหาพื้นฐานของแนวทางเป็นระบบ

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

หากคุณไม่รู้วิธีเข้าหาปัญหา คุณจะไม่ได้รับโซลูชัน

ข้อมูลเชิงลึกนี้สัมผัสกับความจริงพื้นฐานในการเขียนโปรแกรม: ระเบียบวิธีเป็นเครื่องมือ ไม่ใช่โซลูชันวิเศษ พวกมันทำงานได้ดีที่สุดเมื่อคุณเข้าใจโดเมนของปัญหาแล้วและสามารถใช้เทคนิคที่เหมาะสม เมื่อ Jeffries ดิ้นรนกับ Sudoku ไม่ใช่เพราะ TDD ล้มเหลวในฐานะแนวคิด แต่เพราะเขาขาดความรู้เฉพาะเกี่ยวกับอัลกอริทึมการค้นหาและ constraint satisfaction ที่ปัญหาต้องการ

ความเป็นไปไม่ได้ของการแก้ปัญหาแบบสากล

การอภิปรายเชื่อมโยงตัวอย่างปฏิบัติจริงนี้กับแนวคิดเชิงทฤษฎีที่ลึกซึ้งกว่าจากวิทยาการคอมพิวเตอร์ Entscheidungsproblem หรือปัญหาการตัดสินใจ ได้พิสูจน์ทางคณิตศาสตร์ว่าไม่มีอัลกอริทึมสากลสำหรับการกำหนดว่าข้อความใดๆ ที่กำหนดให้สามารถพิสูจน์ได้จากชุดกฎหรือไม่ สิ่งนี้มีผลกระทบอย่างลึกซึ้งต่อระเบียบวิธีการเขียนโปรแกรม

หากเราไม่สามารถกำหนดได้ว่าโปรแกรมแก้งานเฉพาะในทุกกรณีหรือไม่ เราก็ไม่สามารถสร้างวิธีการสากลสำหรับการเขียนโปรแกรมที่แก้งานใดๆ ที่กำหนดให้ได้แน่นอน นี่หมายความว่าความฝันของระเบียบวิธีการพัฒนาแบบเดียวเหมาะกับทุกสถานการณ์นั้นเป็นไปไม่ได้ทางคณิตศาสตร์

Entscheidungsproblem: ปัญหาที่มีชื่อเสียงในตรรกศาสตร์คณิตศาสตร์ที่ถามว่ามีอัลกอริทึมที่สามารถกำหนดได้หรือไม่ว่าข้อความทางคณิตศาสตร์ใดๆ สามารถพิสูจน์ได้

แนวคิดทางเทคนิคหลัก:

  • ปัญหาการหาคำตอบที่ต้องเป็นไปตามข้อจำกัด (CSP): กรอบการทำงานทางคณิตศาสตร์สำหรับปัญหาที่มีตัวแปรซึ่งต้องเป็นไปตามกฎเกณฑ์เฉพาะเจาะจง
  • Entscheidungsproblem: การพิสูจน์ทางทฤษฎีที่แสดงให้เห็นว่าไม่มีอัลกอริทึมสากลที่สามารถกำหนดความสามารถในการพิสูจน์ทางคณิตศาสตร์ได้
  • การพัฒนาโดยใช้การทดสอบเป็นหลัก (TDD): วิธีการที่เขียนการทดสอบก่อนการเขียนโค้ดสำหรับการใช้งานจริง

สิ่งที่ใช้ได้จริงในทางปฏิบัติ

แทนที่จะพึ่งพาระเบียบวิธีเดียว โปรแกรมเมอร์ที่ประสบความสำเร็จจะสร้างชุดเครื่องมือที่หลากหลาย พวกเขาเรียนรู้แนวทางที่แตกต่างกันสำหรับปัญหาประเภทต่างๆ และพัฒนาสัญชาตญาณเกี่ยวกับเวลาที่จะใช้เครื่องมือแต่ละอย่าง สำหรับปัญหาอัลกอริทึมเช่น Sudoku การเข้าใจเทคนิคการค้นหาและ constraint satisfaction เป็นสิ่งสำคัญ สำหรับแอปพลิเคชันธุรกิจ TDD อาจมีค่ามากกว่าเพราะความต้องการมักไม่ชัดเจนและเปลี่ยนแปลงบ่อย

ชุมชนได้ระบุแนวทางปฏิบัติหลายอย่างที่มีแนวโน้มจะใช้ได้ผลในโดเมนปัญหาต่างๆ: ใช้เวลากับนักพัฒนาที่มีประสบการณ์ คิดอย่างเป็นวิทยาศาสตร์โดยการตั้งสมมติฐานและทดสอบ ถอยหลังเพื่อได้มุมมองใหม่ และเขียนโค้ดจำนวนมากเพื่อสร้างการรู้จำรูปแบบเมื่อเวลาผ่านไป

เครื่องมือแก้ปัญหาที่ชุมชนแนะนำ:

  • ใช้เวลากับผู้ปฏิบัติงานที่มีประสบการณ์
  • ประยุกต์ใช้การคิดเชิงวิทยาศาสตร์ (สมมติฐาน → ทดสอบ → ปรับปรุง)
  • ถอยออกมาเพื่อมองมุมมองใหม่
  • เขียนโค้ดเพื่อสร้างการรู้จำรูปแบบ
  • พูดคุยแลกเปลี่ยนความคิดกับผู้อื่น
  • ใช้เครื่องมือที่เหมาะสม เช่น LLMs เมื่อมีประโยชน์

ภาพใหญ่

กรณีศึกษานี้เป็นการเตือนใจว่าการเขียนโปรแกรมยังคงเป็นศิลปะมากเท่ากับวิทยาศาสตร์ แม้ว่าเราจะมีเครื่องมือและระเบียบวิธีที่ทรงพลัง แต่พวกมันต้องการการตัดสินใจของมนุษย์เพื่อใช้อย่างมีประสิทธิภาพ นักพัฒนาที่ประสบความสำเร็จมากที่สุดไม่ใช่คนที่ปฏิบัติตามกระบวนการที่เข้มงวด แต่เป็นคนที่เข้าใจว่าเมื่อไหร่และอย่างไรจึงจะใช้แนวทางที่แตกต่างกัน

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

อ้างอิง: Reflections on Sudoku, Or the Impossibility of Systematizing Thought