นักพัฒนาคนหนึ่งได้ทำการแปลง terminal multiplexer tmux ทั้งหมดจาก C เป็น Rust ด้วยตนเองสำเร็จแล้วภายในระยะเวลาสามเดือน โปรเจกต์นี้ชื่อว่า tmux-rs ซึ่งถือเป็นงานที่ท้าทายอย่างมาก โดยสามารถลดจำนวนโค้ดจากประมาณ 65,000 บรรทัดใน C ลงเหลือ 40,000 บรรทัดใน Rust พร้อมทั้งรักษาฟังก์ชันการทำงานไว้ครบถ้วน
การเปรียบเทียบการลดจำนวนโค้ด
- โค้ดเบส C เดิม: ประมาณ 65,000 บรรทัด
- การแปลงเป็น Rust: ประมาณ 40,000 บรรทัด
- การลดลง: น้อยลงประมาณ 38% ของจำนวนบรรทัดโค้ด
- เวลาในการแปลง: 3 เดือน (กระบวนการแปลงด้วยมือ)
ความท้าทายของเครื่องมือแปลงโค้ดอัตโนมัติ
นักพัฒนาได้ลองใช้ C2Rust ซึ่งเป็น transpiler อัตโนมัติที่แปลงโค้ด C เป็น Rust ในตอนแรก แต่วิธีการนี้กลับมีปัญหา โค้ด Rust ที่ได้จากการแปลงมีความยาวเกินจำเป็น ยากต่อการดูแลรักษา และเต็มไปด้วยการตรวจสอบความปลอดภัยที่ไม่จำเป็นและการใช้งาน raw pointer ที่ทำให้ยากต่อการทำงานมากกว่าโค้ด C ต้นฉบับ หลังจากพยายาม refactor ผลลัพธ์ที่ได้จากการแปลงด้วยตนเองแล้ว นักพัฒนาจึงตัดสินใจยกเลิกวิธีการนี้และเลือกที่จะแปลงแต่ละไฟล์ด้วยตนเองตั้งแต่เริ่มต้น
C2Rust เป็นเครื่องมือที่แปลงโค้ด C เป็น Rust อัตโนมัติ แต่มักจะสร้างโค้ดที่ยากต่อการดูแลรักษา
เครื่องมือแปลงภาษาที่ได้ทดลองใช้
- C2Rust: เครื่องมือแปลงอัตโนมัติ - ถูกยกเลิกเนื่องจากผลลัพธ์ที่ได้ไม่สามารถบำรุงรักษาได้
- Cursor AI: ทดลองใช้ระหว่างการพัฒนา - หยุดใช้เนื่องจากใช้เวลามากในการตรวจสอบโค้ดที่สร้างขึ้น
- การแปลงด้วยตนเอง: วิธีการสุดท้ายที่ใช้ - กระบวนการทำทีละฟังก์ชัน
กระบวนการแปลงทีละฟังก์ชัน
แทนที่จะแปลงทั้งไฟล์ในครั้งเดียว นักพัฒนาได้ปรับปรุงวิธีการให้ทำงานกับฟังก์ชันแต่ละตัว วิธีการนี้เกี่ยวข้องกับการคัดลอก header ของฟังก์ชัน C แล้วทำการ comment การใช้งาน C ต้นฉบับ จากนั้นเขียนส่วนที่เทียบเท่าใน Rust โค้ด C จะทำการ link กับการใช้งาน Rust โดยใช้ compiler attributes เฉพาะ วิธีการแบบค่อยเป็นค่อยไปนี้ช่วยให้สามารถตรวจสอบและแก้ไขข้อผิดพลาดได้ดีขึ้นตลอดกระบวนการ
การแก้ไขปัญหาการรวมระบบที่ซับซ้อน
กระบวนการแปลงเผยให้เห็นข้อผิดพลาดที่น่าสนใจหลายอย่างที่แสดงให้เห็นถึงความท้าทายของการรวมระบบข้ามภาษา ปัญหาที่น่าสังเกตอย่างหนึ่งเกี่ยวข้องกับการประกาศฟังก์ชันแบบ implicit ใน C ซึ่ง compiler สันนิษฐานประเภทการคืนค่าที่ไม่ถูกต้องสำหรับฟังก์ชัน Rust ข้อผิดพลาดอีกอย่างหนึ่งเกิดจากการไม่ตรงกันของคำจำกัดความ struct field ระหว่าง C และ Rust ซึ่งทำให้เกิดการละเมิดการเข้าถึงหน่วยความจำเมื่อทั้งสองภาษามีมุมมองที่แตกต่างกันของโครงสร้างข้อมูลเดียวกัน
ความท้าทายทางเทคนิคที่พบ
- การประกาศฟังก์ชันแบบ implicit ที่ทำให้เกิดประเภทการคืนค่าที่ไม่ถูกต้อง
- ความไม่ตรงกันของฟิลด์ struct ระหว่างคำจำกัดความใน C และ Rust
- การจัดการ raw pointer และบล็อกโค้ด unsafe
- การรวม intrusive data structures และ macros
- การใช้งาน parser โดยใช้ Lalrpop crate
การตอบรับจากชุมชนและแผนการในอนาคต
ชุมชนโปรแกรมเมอร์มีปฏิกิริยาที่หลากหลายต่อโปรเจกต์นี้ แม้ว่าหลายคนจะชื่นชมคุณค่าทางการศึกษาและการบันทึกกระบวนการอย่างโปร่งใสของนักพัฒนา แต่ก็มีคนอื่นตั้งคำถามเกี่ยวกับประโยชน์ในทางปฏิบัติของการเขียนซอฟต์แวร์ที่เสถียรและได้รับการดูแลรักษาอย่างดีใหม่ นักพัฒนาบางคนแสดงความกังวลเกี่ยวกับการนำข้อผิดพลาดใหม่เข้าสู่โค้ดที่ผ่านการทดสอบมาแล้ว ในขณะที่คนอื่นเห็นศักยภาพสำหรับการปรับปรุงในอนาคต
ความเข้าใจของฉันคือ แม้ว่า tmux-rs จะเขียนด้วยภาษาที่ปลอดภัยกว่า แต่ก็ยังไม่สามารถเอาชนะความเสถียรของโปรเจกต์เก่าที่ผ่านการทดสอบมาอย่างดีและได้รับการดูแลรักษาอย่างดีที่เขียนโดยกลุ่มนักพัฒนาที่มีความสามารถสูงได้
นักพัฒนายอมรับว่าเวอร์ชัน Rust ปัจจุบันยังคงใช้ unsafe code blocks อย่างมาก ทำให้ไม่ปลอดภัยกว่าการใช้งาน C ต้นฉบับอย่างมีนัยสำคัญ ระยะต่อไปของโปรเจกต์มีเป้าหมายที่จะแปลงโค้ดเบสให้เป็น safe Rust ซึ่งจะให้ประโยชน์ด้านความปลอดภัยของหน่วยความจำที่ Rust เป็นที่รู้จัก
มองไปข้างหน้า
แม้จะมีความท้าทายและความสงสัยจากชุมชน tmux-rs ก็ยังคงเป็นกรณีศึกษาที่น่าสนใจในการแปลงโค้ดขนาดใหญ่ โปรเจกต์นี้แสดงให้เห็นทั้งความเป็นไปได้และข้อจำกัดของเครื่องมือและเทคนิคการแปลงในปัจจุบัน สำหรับผู้ใช้ที่สนใจ terminal multiplexers โปรเจกต์นี้เสนอทางเลือกที่ใช้งานได้แทน tmux แบบดั้งเดิม แม้ว่าอาจใช้เวลาในการบรรลุความเสถียรและความน่าเชื่อถือของโค้ดเบสต้นฉบับ
โปรเจกต์ทั้งหมดมีให้บน GitHub และนักพัฒนาสนับสนุนให้ชุมชนมีส่วนร่วมผ่านการอภิปรายและการมีส่วนร่วม ว่าโปรเจกต์งานอดิเรกนี้จะได้รับการยอมรับในวงกว้างหรือไม่ยังคงต้องติดตามดู แต่แน่นอนว่าให้ข้อมูลเชิงลึกที่มีค่าเกี่ยวกับความซับซ้อนของการทำให้โค้ดเบส C แบบเก่าทันสมัย
อ้างอิง: Introducing tmux-rs