นักพัฒนาซอฟต์แวร์ถกเถียงเรื่องการอ่านโค้ดเทียบกับการทดสอบอัตโนมัติสำหรับการป้องกันบั๊กในระบบขนาดใหญ่

ทีมชุมชน BigGo
นักพัฒนาซอฟต์แวร์ถกเถียงเรื่องการอ่านโค้ดเทียบกับการทดสอบอัตโนมัติสำหรับการป้องกันบั๊กในระบบขนาดใหญ่

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

การสนทนานี้มีจุดศูนย์กลางอยู่ที่ว่าการอ่านโค้ดด้วยตนเองสามารถเป็นวิธีการที่เชื่อถือได้ในการค้นพบบั๊กหรือไม่ หรือแนวทางอัตโนมัติเช่น type systems และ property testing จะเป็นประโยชน์มากกว่าสำหรับสถานการณ์การพัฒนาในโลกแห่งความเป็นจริง

ขนาดสร้างความต้องการที่แตกต่าง

ชุมชนนักพัฒนาแบ่งฝ่ายกันอย่างชัดเจนเกี่ยวกับว่าเทคนิคการอ่านโค้ดจะใช้ได้ผลเกินกว่าโปรเจกต์เล็กๆ หรือไม่ ในขณะที่นักพัฒนาบางคนรายงานความสำเร็จในการค้นหาบั๊กในการใช้งานที่มี 500 บรรทัด แต่คนอื่นๆ โต้แย้งว่าแนวทางนี้กลายเป็นเรื่องที่ไม่สามารถทำได้จริงกับระบบกระจายที่มีล้านบรรทัดซึ่งสะสม technical debt มา 15 ปี ความตึงเครียดหลักอยู่ที่ระหว่างวิสัยทัศน์ในอุดมคติของโค้ดที่สร้างขึ้นอย่างรอบคอบและอ่านได้ง่าย กับความเป็นจริงที่ยุ่งเหยิงของระบบเก่าที่มี abstraction หลายชั้น

นักพัฒนาที่มีประสบการณ์หลายคนชี้ให้เห็นว่า codebase ขนาดใหญ่ต้องการกลยุทธ์ที่แตกต่างไปโดยสิ้นเชิง พวกเขาเน้นย้ำว่า type systems, invariant checks และ automated property testing กลายเป็นเครื่องมือที่จำเป็นเมื่อถึงขีดจำกัดทางปัญญาของมนุษย์

เครื่องมือป้องกันบั๊กแบบอัตโนมัติ

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

Mental Models เทียบกับเครื่องมือ

ส่วนสำคัญของการอภิปรายมุ่งเน้นไปที่การสร้าง mental models ของการทำงานของโค้ดเทียบกับการพึ่งพาเครื่องมืออัตโนมัติ ผู้สนับสนุนการอ่านโค้ดโต้แย้งว่าการทำความเข้าใจพฤติกรรมของโปรแกรมผ่านการวิเคราะห์อย่างรอบคอบช่วยให้นักพัฒนาเขียนโค้ดที่ดีกว่าตั้งแต่เริ่มต้น พวกเขาแนะนำให้ติดตาม control flow จาก main functions และติดตามการเปลี่ยนแปลง state ข้าม data structures หลัก

อย่างไรก็ตาม ผู้ที่สงสัยตั้งคำถามว่าแนวทางนี้จะขยายขนาดได้เกินกว่าฟังก์ชันแต่ละตัวหรือโมดูลเล็กๆ หรือไม่ พวกเขาสังเกตว่าแม้จะอ่านอย่างรอบคอบแล้ว การโต้ตอบที่ซับซ้อนระหว่างคอมโพเนนต์ของระบบมักจะซ่อนบั๊กที่ร้ายแรงที่สุด

เทคนิคการอ่านโค้ด

  • ติดตามการไหลของการควบคุมเริ่มต้นจาก main() หรือจุดเริ่มต้นของระบบ
  • ติดตามการเปลี่ยนแปลงสถานะในโครงสร้างข้อมูลหลัก
  • มุ่งเน้นไปที่รูปแบบที่มักเกิดข้อผิดพลาด (เช่น allocators ที่มี try statements ใน Zig )
  • ใช้ git blame/log เพื่อทำความเข้าใจบริบททางประวัติศาสตร์
  • อ่านระบบย่อยทั้งหมดระหว่างการ code review ไม่ใช่แค่ diffs เท่านั้น

กลยุทธ์ Defensive Programming

ชุมชนยังได้เน้นแนวทางประนีประนอมที่ใช้ได้จริงซึ่งผสมผสานความเข้าใจของมนุษย์กับการป้องกันอัตโนมัติ นักพัฒนาบางคนสนับสนุนเทคนิค defensive programming เช่น การตรวจจับข้อผิดพลาดตั้งแต่เนื่องๆ พร้อมกับการ logging ที่เหมาะสม รวมกับนโยบายไม่ยอมรับ stack traces ใน production logs

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

คนอื่นๆ เน้นความสำคัญของการทำให้ invalid states เป็นไปไม่ได้ที่จะแสดงตั้งแต่แรก แทนที่จะพยายามจับข้อผิดพลาดหลังจากที่เกิดขึ้นแล้ว

การตรวจสอบความเป็นจริงในอุตสาหกรรม

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

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

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

อ้างอิง: Look Out For Bugs