1 คะแนน โดย GN⁺ 2024-03-01 | 1 ความคิดเห็น | แชร์ทาง WhatsApp

หากคุณได้รับช่วงต่อโค้ดเบส C++ เดิม ควรทำอย่างไร?

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

ขั้นตอนแรก: ทำให้โค้ดรันบนเครื่องโลคัลได้

  • ปรับเปลี่ยนโค้ดและระบบบิลด์ให้น้อยที่สุดเท่าที่จำเป็นเพื่อให้มันทำงานบนเครื่องโลคัลได้ ยังไม่ต้องรีแฟกเตอร์ครั้งใหญ่ในตอนนี้

เอาสิ่งที่ไม่จำเป็นออก

  • ลบทุกอย่างที่ไม่จำเป็นอย่างแท้จริงต่อการมอบความสามารถที่บริษัทหรือโปรเจกต์โอเพนซอร์สโฆษณาและจำหน่าย

ยกระดับโปรเจกต์ให้เข้าสู่ศตวรรษที่ 21

  • เพิ่ม CI (การทำงานร่วมกันอย่างต่อเนื่อง), linter, fuzzing, การจัดรูปแบบอัตโนมัติ เป็นต้น

ปรับปรุงโค้ดแบบค่อยเป็นค่อยไป

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

พิจารณาเขียนบางส่วนใหม่ด้วยภาษาที่ปลอดภัยด้านหน่วยความจำ

  • หากเป็นไปได้ ให้พิจารณาเขียนโค้ดบางส่วนใหม่ด้วยภาษาที่มีความปลอดภัยด้านหน่วยความจำ

ระบุแพลตฟอร์มที่รองรับ

  • ระบุคู่ <สถาปัตยกรรม>-<ระบบปฏิบัติการ> ที่รองรับอย่างเป็นทางการไว้ใน README เช่น x86_64-linux หรือ aarch64-darwin

ทำให้บิลด์ทำงานได้บนเครื่อง

  • ทำให้สามารถบิลด์ได้อย่างน่าเชื่อถือและสม่ำเสมอบนทุกแพลตฟอร์มที่รองรับ

ทำให้การทดสอบผ่านบนเครื่อง

  • หากยังไม่มีการทดสอบ ให้เขียนการทดสอบก่อนเปลี่ยนโค้ด จากนั้นทำให้มันผ่าน แล้วค่อยย้อนกลับมาดำเนินการต่อ

อธิบายใน README ว่าจะบิลด์และทดสอบแอปพลิเคชันอย่างไร

  • ทำให้คำสั่งสำหรับการบิลด์และทดสอบเรียบง่าย เพื่อให้แม้แต่คนที่ไม่ใช่ผู้เชี่ยวชาญก็ทำตามได้ง่าย

มองหาผลลัพธ์ง่าย ๆ เพื่อเร่งความเร็วในการบิลด์และทดสอบ

  • มองหาวิธีง่าย ๆ ที่ช่วยเพิ่มความเร็วในการบิลด์และทดสอบได้โดยไม่ต้องเปลี่ยนระบบบิลด์

ลบโค้ดที่ไม่จำเป็น

  • ใช้คำเตือนจากคอมไพเลอร์และ linter เพื่อค้นหาและลบโค้ดที่ไม่ได้ใช้งาน

Linter

  • ไม่ต้องหมกมุ่นกับกฎของ linter มากเกินไป เพียงเพิ่มกฎพื้นฐานบางข้อและผสานเข้ากับวงจรการพัฒนา

การจัดรูปแบบโค้ด

  • ในจังหวะที่เหมาะสม ให้บังคับใช้สไตล์โค้ดกับทั้งโค้ดเบสในครั้งเดียว และ commit การตั้งค่าไว้

Sanitizer

  • ใช้ sanitizer เพื่อตรวจจับและแก้ไขบั๊กจริงและการรั่วไหลของหน่วยความจำ

เพิ่ม CI pipeline

  • ทำให้สิ่งดี ๆ ที่ตั้งค่าไว้ทั้งหมดเป็นอัตโนมัติ (เช่น linter, การจัดรูปแบบโค้ด, การทดสอบ ฯลฯ) และสร้างไบนารีสำหรับสภาพแวดล้อมจริงกับทุกการเปลี่ยนแปลง

ปรับปรุงโค้ดแบบค่อยเป็นค่อยไป

  • มุ่งเน้นไปที่เป้าหมายที่เฉพาะเจาะจง เช่น ความปลอดภัย ความถูกต้อง และประสิทธิภาพ และหลีกเลี่ยงเกณฑ์เชิงอัตวิสัยอย่าง "โค้ดสะอาด"

เขียนใหม่ด้วยภาษาที่ปลอดภัยด้านหน่วยความจำ?

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

บทสรุป

  • นำเสนอแผนที่เป็นรูปธรรมและเป็นขั้นตอนสำหรับการหลุดพ้นจากโค้ดเบส C++ แบบเลกาซีที่ซับซ้อน

ภาคผนวก: การจัดการ dependency

  • ในโลก C++ ไม่มีการจัดการ dependency ที่ดีนัก และส่วนใหญ่ใช้ system package manager กัน แต่ผู้เขียนมองว่านี่ไม่ใช่ความคิดที่ดี
  • ความเห็นของผู้เขียนต่อการจัดการ dependency คือการใช้ git submodule และแนวทางคอมไพล์จากซอร์ส

ความเห็นของ GN⁺

  • บทความนี้เป็นคู่มือแบบเป็นขั้นตอนที่มีประโยชน์สำหรับวิศวกรซอฟต์แวร์ระดับเริ่มต้นที่ได้รับช่วงต่อโค้ดเบส C++
  • การรับมือกับโค้ดเลกาซีเป็นความท้าทายร่วมกันของนักพัฒนาจำนวนมาก และบทความนี้ให้คำแนะนำเชิงปฏิบัติสำหรับสถานการณ์เช่นนั้น
  • การเน้นย้ำความสำคัญของการทดสอบระหว่างกระบวนการปรับปรุงโค้ดเบสสะท้อนแนวปฏิบัติที่ดีในการพัฒนาซอฟต์แวร์
  • ความเห็นของผู้เขียนเกี่ยวกับการจัดการ dependency อาจเป็นประเด็นถกเถียง และในโปรเจกต์จริงก็มีหลายกรณีที่ใช้ package manager สมัยใหม่อย่าง Conan หรือ vcpkg ได้อย่างประสบความสำเร็จ
  • เมื่อนำเทคโนโลยีมาใช้ ควรพิจารณาลักษณะของโปรเจกต์และระดับทักษะของทีมด้วย และบทความนี้อาจเป็นจุดเริ่มต้นที่ดีในการช่วยตัดสินใจดังกล่าว

1 ความคิดเห็น

 
GN⁺ 2024-03-01
ความคิดเห็นจาก Hacker News
  • ความคิดเห็นบางส่วนบน Hacker News ได้เสนอคำแนะนำเมื่อได้รับช่วงต่อโปรเจ็กต์ C++:

    • บิลด์ที่ทำซ้ำได้: แนะนำให้ใช้เครื่องมืออย่าง Docker ครอบสภาพแวดล้อมการบิลด์ เพื่อให้เครื่องมือและ dependencies ชัดเจนและทำซ้ำได้
    • บิลด์ให้ผ่านอย่างสะอาดด้วยตัวเลือก -Wall: แก้คำเตือนเพื่อแก้ปัญหาในโค้ด และในบางกรณีที่พบไม่บ่อยก็อาจละเลยคำเตือนได้หลังจากทำความเข้าใจแล้ว
    • เสนอให้ทดสอบตั้งแต่ช่วงต้นด้วยเครื่องมืออย่าง Valgrind เพื่อตรวจสอบข้อผิดพลาดในการอ่าน/เขียน
    • แนะนำให้จำกัดการรีแฟกเตอร์ไว้ในขอบเขตเฉพาะส่วนในช่วงแรก และหลีกเลี่ยงการออกแบบใหม่ครั้งใหญ่ก่อนจะเข้าใจโครงสร้างทั้งหมด
  • ความคิดเห็นอื่น ๆ ระบุว่าการนำ CI, linting, auto-formatting เป็นต้น มาใช้ก่อนเป็นสิ่งสำคัญ:

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

  • ยังมีความคิดเห็นที่กล่าวถึงความสำคัญของเครื่องมือและเทคนิคในการทำความเข้าใจโค้ด:

    • การใช้เครื่องมือที่ทำดัชนี codebase การเขียน UML sequence diagram และการจดบันทึกราวกับกำลังสอนให้คนอื่นเข้าใจ เป็นสิ่งสำคัญ
  • ความคิดเห็นหนึ่งเสนอคำแนะนำเกี่ยวกับการเพิ่ม CI, linters, fuzzing, auto-formatting เป็นต้น เพื่อปรับโครงการให้ทันสมัย:

    • ใช้ CI เพื่อให้สามารถบิลด์ได้ในที่อื่นด้วย และใช้คำเตือนจากคอมไพเลอร์รวมถึงตัววิเคราะห์แบบสถิติเพื่อระบุปัญหาในโค้ด
    • ตั้งค่า unit test สำหรับส่วนสำคัญของโค้ดเพื่อยืนยันว่าโค้ดทำงานได้ถูกต้องตามที่ควร
    • การจัดรูปแบบอัตโนมัติมีลำดับความสำคัญต่ำกว่า และแนะนำให้ยึดตามสไตล์ของผู้ดูแลเดิม
  • อีกความคิดเห็นหนึ่งวิจารณ์คำแนะนำให้เขียนบางส่วนใหม่ด้วยภาษาแบบ memory-safe:

    • เป็นเรื่องยากที่จะหาทรัพยากรเพิ่มเติมสำหรับงานส่วนนี้ ต้องมีความรู้ภาษาอื่นเพิ่มนอกเหนือจาก C++ และการทดสอบก็อาจซับซ้อนขึ้น
  • ยังมีความคิดเห็นที่อ้างว่าการใช้ git submodule และแนวทางคอมไพล์จากซอร์สดีกว่าตัวจัดการแพ็กเกจ:

    • พร้อมชี้ว่าการวิจารณ์เช่นนี้ก่อนจะลองใช้เครื่องมืออย่าง vcpkg ดูก่อนนั้นเป็นเรื่องแปลก

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