ชุมชนนักพัฒนาปฏิเสธอย่างแรงต่อบทความที่อ้างว่า Type Checking เป็น "ความซับซ้อนที่ไม่จำเป็น"

ทีมชุมชน BigGo
ชุมชนนักพัฒนาปฏิเสธอย่างแรงต่อบทความที่อ้างว่า Type Checking เป็น "ความซับซ้อนที่ไม่จำเป็น"

บทความล่าสุดที่มีชื่อว่า Type Checking is a Symptom, Not a Solution ได้จุดประกายการถกเถียงอย่างรุนแรงในชุมชนโปรแกรมเมอร์ โดยนักพัฒนาส่วนใหญ่ปฏิเสธแนวคิดหลักที่ว่าระบบ type ทำให้เกิดความซับซ้อนที่ไม่จำเป็น บทความดังกล่าวโต้แย้งว่าระบบ type ที่ซับซ้อนอย่าง borrow checker ของ Rust และ type classes ของ Haskell เป็นเพียงวิธีแก้ปัญหาชั่วคราวสำหรับข้อผิดพลาดพื้นฐานในสถาปัตยกรรม มากกว่าที่จะเป็นเครื่องมือสำคัญในการจัดการความซับซ้อนของซอฟต์แวร์

การเปรียบเทียบกับวิศวกรรมฮาร์ดแวร์ล้มเหลวภายใต้การตรวจสอบ

ข้อโต้แย้งหลักของบทความอาศัยการเปรียบเทียบการพัฒนาซอฟต์แวร์กับวิศวกรรมอิเล็กทรอนิกส์เป็นหลัก โดยอ้างว่าวิศวกรฮาร์ดแวร์ออกแบบระบบที่ซับซ้อนโดยไม่ต้องใช้ type checker อย่างไรก็ตาม การเปรียบเทียบนี้ถูกหักล้างอย่างสิ้นเชิงโดยวิศวกรอิเล็กทรอนิกส์จริงในชุมชน วิศวกร EE มืออาชีพชี้ให้เห็นว่าการออกแบบฮาร์ดแวร์อาศัยเครื่องมือตรวจสอบ design rule checker และระบบ formal verification อย่างกว้างขวาง ซึ่งมีความคล้ายคลึงโดยตรงกับ type checking ในซอฟต์แวร์

เครื่องมือ electronic design automation (EDA) สมัยใหม่รวมถึงระบบตรวจสอบที่ครอบคลุมซึ่งตรวจสอบความถูกต้องของการออกแบบวงจรก่อนการผลิต เครื่องมือเหล่านี้จับข้อผิดพลาดได้ตั้งแต่เริ่มต้นในกระบวนการออกแบบ เช่นเดียวกับที่ type checker จับข้อผิดพลาดในการเขียนโปรแกรมก่อน runtime ข้อเสนอแนะที่ว่าวิศวกรฮาร์ดแวร์ทำงานโดยไม่มีเครื่องมือตรวจสอบดังกล่าวแสดงให้เห็นถึงความเข้าใจผิดพื้นฐานเกี่ยวกับแนวปฏิบัติวิศวกรรมอิเล็กทรอนิกส์สมัยใหม่

เครื่องมือทางเทคนิคที่กล่าวถึง:

  • EDA (Electronic Design Automation): เครื่องมือซอฟต์แวร์ที่วิศวกรอิเล็กทรอนิกส์ใช้สำหรับการออกแบบและตรวจสอบวงจร
  • SPICE: โปรแกรมจำลองวงจรยอดนิยมที่ใช้สำหรับการตรวจสอบฮาร์ดแวร์
  • Design Rule Checkers: เครื่องมืออัตโนมัติที่ตรวจสอบเลย์เอาต์ PCB เทียบกับข้อจำกัดในการผลิต
  • VHDL/Verilog: ภาษาอธิบายฮาร์ดแวร์ที่มีระบบประเภทสำหรับการออกแบบวงจร

ความเข้าใจผิดเกี่ยวกับ Function Call

บทความวิพากษ์วิจารณ์ function call ว่าสร้างการเชื่อมโยงที่แน่นแฟ้นระหว่างคอมโพเนนต์ต่างๆ โดยโต้แย้งว่าพฤติกรรม blocking ทำให้ไม่เหมาะสมสำหรับระบบกระจาย มุมมองนี้มองข้ามธรรมชาติพื้นฐานของ abstraction ในการเขียนโปรแกรมและวิธีที่มันช่วยเหลือมากกว่าขัดขวางสถาปัตยกรรมซอฟต์แวร์ที่ดี ชุมชนโปรแกรมเมอร์ชี้ให้เห็นว่า function interface ที่ออกแบบมาอย่างดีพร้อมกับ type annotation ที่เหมาะสมจริงๆ แล้วส่งเสริมการเชื่อมโยงแบบหลวมๆ โดยการกำหนด contract ระหว่างคอมโพเนนต์อย่างชัดเจน

การวิพากษ์วิจารณ์ Remote Procedure Call (RPC) ว่าเป็นปัญหาที่เป็นส่วนขยายของ function call ยังมองข้ามการออกแบบระบบกระจายที่ประสบความสำเร็จมาหลายทศวรรษ RPC framework สมัยใหม่ที่มี strong typing ได้พิสูจน์แล้วว่าเป็นสิ่งจำเป็นสำหรับการสร้างแอปพลิเคชันกระจายที่เชื่อถือได้และขยายได้

UNIX Pipeline: เรียบง่ายบนผิวหน้า ซับซ้อนข้างใน

บทความยกย่อง UNIX pipeline เป็นตัวอย่างของสถาปัตยกรรมที่เรียบง่ายและปราศจาก type ที่ทำงานได้ในระดับใหญ่ อย่างไรก็ตาม นักพัฒนาที่มีประสบการณ์สังเกตว่าความเรียบง่ายนี้เป็นการหลอกลวง แม้ว่า transport layer จะใช้ text stream ที่เรียบง่าย แต่โปรแกรมแต่ละตัวใน pipeline ยังคงต้อง parse และตรวจสอบความถูกต้องของ input ซึ่งเป็นการทำ runtime type checking โดยพื้นฐาน

UNIX pipeline มีความเปราะบาง! การเปลี่ยนแปลงเล็กน้อยใน text output ของโปรแกรมจะทำให้ pipeline ที่ใช้งานมันเสียหายโดยสิ้นเชิง

ความเปราะบางนี้เกิดจากการขาด formal interface contract ระหว่างคอมโพเนนต์ของ pipeline เมื่อรูปแบบ output ของโปรแกรมเปลี่ยนแปลงโดยไม่คาดคิด คอมโพเนนต์ downstream จะล้มเหลวในรูปแบบที่คาดเดาไม่ได้ Static typing จะทำให้ระบบดังกล่าวแข็งแรงขึ้นจริงๆ โดยการจับ interface mismatch ได้ตั้งแต่เริ่มต้น

ประสบการณ์ในโลกจริงขัดแย้งกับทฤษฎี

นักพัฒนาที่มีประสบการณ์อย่างกว้างขวางทั้งใน typed และ untyped language รายงานอย่างสม่ำเสมอว่าระบบ type ลด cognitive load มากกว่าเพิ่ม Type annotation ทำหน้าที่เป็นเอกสารที่มีชีวิตซึ่งช่วยให้นักพัฒนาเข้าใจพฤติกรรมของโค้ดโดยไม่ต้องติดตาม execution path ที่ซับซ้อน IDE สมัยใหม่ใช้ประโยชน์จากข้อมูล type เพื่อให้ autocomplete ที่ชาญฉลาด การสนับสนุน refactoring และการตรวจจับข้อผิดพลาดตั้งแต่เริ่มต้น

การเปลี่ยนจาก JavaScript เป็น TypeScript ใน codebase ขนาดใหญ่หลายแห่งแสดงให้เห็นถึงคุณค่าในทางปฏิบัติของการเพิ่มข้อมูล type เข้าไปในระบบที่มีอยู่ ทีมต่างๆ รายงานการปรับปรุงอย่างมีนัยสำคัญในการบำรุงรักษาโค้ด ประสิทธิภาพของนักพัฒนา และการลดบั๊กเมื่อนำ static typing มาใช้

ความเป็นจริงของขนาดและความซับซ้อน

ข้อเสนอแนะของบทความที่ว่า type checking จำเป็นเฉพาะเพราะเราสร้างระบบที่ซับซ้อนโดยไม่จำเป็นนั้นมองข้ามความซับซ้อนโดยธรรมชาติของข้อกำหนดซอฟต์แวร์สมัยใหม่ การสร้าง web browser ระบบปฏิบัติการ หรือฐานข้อมูลกระจายเกี่ยวข้องกับการจัดการโค้ดหลายล้านบรรทัดที่มีการพึ่งพาซึ่งกันและกันอย่างซับซ้อน ระบบ type ให้ guardrail ที่จำเป็นซึ่งทำให้ความซับซ้อนดังกล่าวจัดการได้

แม้แต่โปรแกรมเล็กๆ ก็ได้รับประโยชน์จาก type checking เนื่องจากมันจับข้อผิดพลาดทั่วไปได้ เช่น การส่ง data type ที่ผิดไปยัง function หรือการเข้าถึง object property ที่ไม่มีอยู่ แนวคิดที่ว่าความซับซ้อนสามารถกำจัดได้เสมอผ่านสถาปัตยกรรมที่ดีกว่า แม้จะน่าสนใจ แต่ไม่สอดคล้องกับความเป็นจริงของการแก้ปัญหาที่ซับซ้อนในโลกจริง

ข้อโต้แย้งหลักจากชุมชน:

  • วิศวกรฮาร์ดแวร์ใช้เครื่องมือตรวจสอบที่คล้ายคลึงกับ type checker อย่างแพร่หลาย
  • UNIX pipelines จริงๆ แล้วเปราะบางเนื่องจากขาดสัญญาอินเทอร์เฟซที่เป็นทางการ
  • ระบบ type ช่วยลดภาระทางปัญญาของนักพัฒนาแทนที่จะเพิ่ม
  • เครื่องมือ EDA สมัยใหม่รวมระบบตรวจสอบกฎการออกแบบที่ครอบคลุม
  • การนำ TypeScript มาใช้แสดงให้เห็นประโยชน์ในทางปฏิบัติของการเพิ่ม type ให้กับโค้ดเบสที่มีอยู่

บทสรุป

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

อ้างอิง: Type Checking is a Symptom, Not a Solution