• Meta กำลังเปลี่ยนโค้ดเบส Android จาก Java ไปเป็น Kotlin ผ่านโครงการที่ดำเนินมาหลายปี
  • ปัจจุบันดูแลหนึ่งในโค้ดเบส Android ที่ใหญ่ที่สุดในโลก และแปลงเป็น Kotlin สำเร็จแล้วมากกว่าครึ่ง
    • Meta ใช้กลยุทธ์การพัฒนาแบบ Kotlin-first มาตั้งแต่ปี 2020
  • เหตุผลที่แปลงโค้ดทั้งหมด:
    • เพื่อใช้ประโยชน์จากข้อดีของ Kotlin ในด้าน "เพิ่มประสิทธิภาพการพัฒนา" และ "ความปลอดภัยของ Null" ให้ได้สูงสุด จึงตัดสินใจแปลงแม้กระทั่งโค้ด Java เดิมที่มีขนาดหลายสิบล้านบรรทัด
    • เสริมความแข็งแกร่งด้านความปลอดภัยของ Null และแก้ปัญหาจากโค้ดเบสแบบผสม
      • การคอมไพล์แบบผสม (คอมไพล์ Java และ Kotlin พร้อมกัน) ทำให้ความเร็วในการบิลด์ช้าที่สุด
      • โค้ด Java ที่ยังเหลืออยู่ก่อให้เกิดปัญหาด้านความปลอดภัยของ Null: โค้ด Java ที่ไม่ปลอดภัยต่อ Null อาจเป็นสาเหตุของ NullPointerException (NPE) ในกราฟการพึ่งพา
      • Kotlin รับประกันความปลอดภัยของ Null ผ่านการตรวจสอบขณะรันไทม์

กระบวนการอัตโนมัติ

  • ในช่วงแรกใช้เครื่องมือแปลง J2K ของ Intellij IDE แบบทำซ้ำหลายรอบ
    • สำหรับโค้ดเบสขนาดใหญ่ของ Meta ต้อง คลิกมากกว่า 100,000 ครั้ง และแต่ละครั้งใช้เวลาหลายนาที
    • สุดท้ายวิธีนี้จึงไม่มีประสิทธิภาพเพราะ ขยายสเกลไม่ได้
  • ได้พัฒนา เครื่องมืออัตโนมัติ: Kotlinator ขึ้นมา
  • กระบวนการแปลง 6 ขั้นตอน
    1. Deep Build: บิลด์โค้ดที่จะถูกแปลง เพื่อให้ IDE สามารถ resolve สัญลักษณ์ทั้งหมดได้ รวมถึง dependency ของบุคคลที่สามและโค้ดที่ถูก generate
    2. Preprocessing: ใช้เครื่องมือเฉพาะของ Meta ที่ชื่อ Editus เป็นพื้นฐาน มีราว 50 ขั้นตอน เช่น การจัดการความปลอดภัยของ Null, dependency และการทำ workaround ให้ J2K
    3. Headless J2K: ปรับ J2K ให้สามารถรันในสภาพแวดล้อมเซิร์ฟเวอร์ได้
    4. Postprocessing: มีราว 150 ขั้นตอน เช่น การเปลี่ยนแปลงเฉพาะ Android, ความปลอดภัยของ Null และการปรับให้เป็นสไตล์ Kotlin
    5. Linters: ปรับปรุงคุณภาพการแปลงอย่างต่อเนื่องผ่านการแก้ไขอัตโนมัติ
    6. Build Error-based Fixes: วิเคราะห์ build error แล้วนำไปสู่การแก้ไขเพิ่มเติม

การทำให้ J2K ทำงานแบบเฮดเลส

  • ปรับ J2K ให้สามารถรันจากระยะไกลได้:
    • J2K ผูกติดกับ Intellij IDE อย่างแน่นแฟ้น จึงยากต่อการรันแบบแยกอิสระ
    • ตอนแรกพิจารณาการรันผ่านสภาพแวดล้อมทดสอบของ Intellij แต่หลังหารือกับผู้เชี่ยวชาญ J2K ของ JetBrains (Ilya Kirillov) ก็เปลี่ยนมาใช้ แนวทาง headless inspection
    • สร้างปลั๊กอิน Intellij โดยขยายคลาส ApplicationStarter และเรียกใช้คลาส JavaToKotlinConverter ของ J2K เพื่อทำงานนี้
  • ข้อดีของแนวทางแบบเฮดเลส
    • แก้ปัญหา IDE ฝั่งโลคัล: นักพัฒนาไม่ต้องคลิกปุ่มใน IDE ด้วยตนเอง
    • แปลงหลายไฟล์พร้อมกัน: จัดการไฟล์จำนวนมากได้
    • ลดเวลาที่ใช้: แม้เวลาแปลงจริงจะเพิ่มเป็นราว 30 นาที แต่เวลาที่นักพัฒนาต้องเสียไปลดลงมาก
    • รองรับการบิลด์และการแก้ error: ขั้นตอนที่ใช้เวลามากแต่มีประโยชน์ (การแก้หลังบิลด์) สามารถรันอัตโนมัติจากระยะไกลได้
  • ระบบอัตโนมัติและการรีวิวโค้ด
    • ใช้ระบบภายในของ Meta เพื่อสร้าง งานแบตช์รายวัน:
    • สร้าง diffs แบบแบตช์ตามเกณฑ์ที่กำหนดเอง (เวอร์ชัน pull request ของ Meta)
    • จัดสรรผู้รีวิวโดยอัตโนมัติ พร้อมรันทดสอบและตรวจสอบ ก่อนนำ diff ที่ได้รับอนุมัติไป deploy ในที่สุด
  • มีเว็บ UI ให้ใช้: นักพัฒนาสามารถสั่งแปลงไฟล์หรือโมดูลที่ต้องการจากระยะไกลได้
  • การกำหนดลำดับการแปลง
    • ไม่ได้บังคับลำดับตายตัว:
      • ให้ความสำคัญกับ ไฟล์ที่มีการพัฒนาอยู่เป็นอันดับแรก
      • Kotlinator จัดการกราฟการพึ่งพาโดยอัตโนมัติ เพื่อแก้ปัญหาความเข้ากันได้ของไฟล์ภายนอก
      • ตัวอย่าง: อัปเดต foo.getName() เป็น foo.name อัตโนมัติ

อื่น ๆ

  • เพิ่มขั้นตอน Preprocessing แบบกำหนดเอง (Java->Java) และ Postprocessing (Kotlin->Kotlin)
  • ใช้เครื่องมือภายในของ Meta อย่าง Editus และไลบรารี JetBrains PSI เพื่อยกระดับคุณภาพการแปลง
  • Nullsafe และ NullAway

สถานะปัจจุบันและอนาคตของการแปลงเป็น Kotlin

  • โค้ด Android Java ของ Meta มากกว่าครึ่งถูกแปลงเป็น Kotlin แล้ว (หรือบางส่วนถูกลบออกไปแล้ว)
  • แต่ ครึ่งที่ง่ายได้จบไปแล้ว:
    • งานที่เหลือมีความซับซ้อนและขนาดใหญ่
    • สำหรับการแปลงที่ อัตโนมัติได้ทั้งหมด จำเป็นต้องเพิ่มขั้นตอนเฉพาะทางหรือมีส่วนช่วยปรับปรุง J2K
    • สำหรับ การแปลงแบบกึ่งอัตโนมัติ เป้าหมายคือทำให้ Kotlinator ดีขึ้นเพื่อให้การ deploy ราบรื่นและปลอดภัย
  • Meta มองว่าบริษัทอื่น ๆ ก็น่าจะเผชิญปัญหาคล้ายกันในการแปลงโค้ด Android
  • Meta แบ่งปันแนวทางแก้ปัญหาที่ได้จากการปรับปรุงและเพิ่มประสิทธิภาพเครื่องมือแปลง
  • ข้อเสนอเพื่อความร่วมมือ:
    • พูดคุยกับนักพัฒนาคนอื่น ๆ ได้ใน #j2k channel ของ Kotlinlang Slack
    • การแบ่งปันกรณีศึกษาและโซลูชันระหว่างกันอาจช่วยสร้างประสบการณ์การแปลงที่ดียิ่งขึ้น

ยังไม่มีความคิดเห็น

ยังไม่มีความคิดเห็น