35 คะแนน โดย GN⁺ 2024-12-23 | 4 ความคิดเห็น | แชร์ทาง WhatsApp
  • ซอฟต์แวร์สมัยใหม่มีการอัปเดตบ่อยผ่านการส่งมอบอย่างต่อเนื่อง (CD) และการทดสอบอัตโนมัติ (CI) แต่ "ซอฟต์แวร์ที่ใช้งานในระยะยาว" ต้องการแนวทางที่แตกต่างออกไป
    • ตัวอย่าง: โรงไฟฟ้านิวเคลียร์ เครื่องบิน เครื่องกระตุ้นหัวใจ ระบบการเลือกตั้ง เป็นต้น
      • ในงานที่ความน่าเชื่อถือและเสถียรภาพมีความสำคัญ มักให้ความสำคัญกับเสถียรภาพและการเปลี่ยนแปลงที่คาดการณ์ได้ มากกว่าการเปลี่ยนแปลงอย่างต่อเนื่อง

หลักการสำคัญของการพัฒนาซอฟต์แวร์ระยะยาว

การพึ่งพา (Dependencies)

  • การพึ่งพาของซอฟต์แวร์เป็นปัจจัยสำคัญต่อความสำเร็จในระยะยาว
  • ซอฟต์แวร์ต้องคำนึงถึงการโต้ตอบกับโลกภายนอก และการเลือกพื้นฐานอย่างภาษาการเขียนโปรแกรมก็มีความสำคัญ
  • ทำความเข้าใจลำดับชั้นของการพึ่งพาซอฟต์แวร์
    • โลกภายนอก: ซอฟต์แวร์ฝั่งไคลเอนต์ที่เราไม่สามารถควบคุมได้ (เช่น เบราว์เซอร์ เป็นต้น)
    • การเลือกพื้นฐาน: องค์ประกอบที่หากจะเปลี่ยนต้องเขียนใหม่ทั้งสแตก เช่น ภาษาการเขียนโปรแกรม
    • เฟรมเวิร์ก: เช่น Spring Framework, React ที่ผูกแน่นกับโค้ดเบส เปลี่ยนได้แต่มีต้นทุนสูงมาก
    • ฐานข้อมูล: ส่วนใหญ่เปลี่ยนได้ แต่ต้องมีการปรับจูนและทำงานในรายละเอียด
    • ไลบรารีช่วยงาน: ไลบรารีที่เปลี่ยนทดแทนได้และให้ความสามารถเฉพาะด้าน
  • เมื่อเวลาผ่านไป การพึ่งพาและโลกภายนอกย่อมเปลี่ยนแปลง:
    • การเปลี่ยนแปลงของการพึ่งพาอาจทำให้ต้องแก้โค้ด หรือเกิด การเปลี่ยนแปลงพฤติกรรม
    • การออกเวอร์ชันหลักใหม่อาจก่อให้เกิด ปัญหาความเข้ากันได้
    • มีความเสี่ยงที่โปรเจกต์จะ ยุติ หรือหายไป
    • ความเสี่ยงด้านความปลอดภัย: การพึ่งพาอาจถูกทำให้เสียหายโดยผู้ไม่หวังดี (เช่น npm, PyPI)
    • การทำเชิงพาณิชย์: เจ้าของรายใหม่จาก venture capital (VC) อาจเปลี่ยนเป็นโมเดลเสียเงิน
    • ปัญหา ความขัดแย้ง ระหว่างการพึ่งพา
  • สิ่งที่ควรตรวจสอบเมื่อเลือกการพึ่งพาสำหรับการใช้งานระยะยาว:
    • ระดับทางเทคนิค: สามารถดูซอร์สโค้ดแล้วประเมินคุณภาพได้หรือไม่
    • ฐานผู้ใช้: ตรวจสอบว่าใครกำลังใช้งานอยู่
    • วัตถุประสงค์ในการพัฒนา: ทำความเข้าใจว่าใครเป็นผู้พัฒนาและมีเป้าหมายอะไร
    • การสนับสนุนทางการเงิน: มีเงินสนับสนุนหรือไม่ และมาจากไหน
    • การบำรุงรักษา: ตรวจสอบว่ามี security release อย่างสม่ำเสมอหรือไม่
      • ชุมชนมีโอกาสรับช่วงการดูแลต่อหรือไม่
      • เราสามารถดูแลเองได้หรือไม่
      • หากจำเป็น ควรสนับสนุนทางการเงินเพื่อให้โปรเจกต์เดินหน้าต่อได้หรือไม่
    • การพึ่งพาของการพึ่งพา:
      • ควรตรวจสอบประวัติด้านความปลอดภัยของการพึ่งพาชั้นล่างด้วย
  • แนวทางที่เป็นจริง
    • จำกัดจำนวนการพึ่งพา:
      • โปรเจกต์ที่มีการพึ่งพามากกว่า 1600 รายการมีแนวโน้มสูงที่โค้ดจะเปลี่ยนเร็วและไม่เสถียร
      • ในโปรเจกต์ที่มีการพึ่งพาจำนวนมาก แทบยากจะรู้ด้วยซ้ำว่ากำลัง deploy โค้ดอะไรอยู่
    • เพิ่มอย่างรอบคอบ:
      • เมื่อเพิ่มการพึ่งพา ให้ตั้ง ระดับความยากทางเทคนิค เพื่อให้มีช่วงเวลาทบทวนตามธรรมชาติ
      • ในโปรเจกต์ระยะยาว ควรหลีกเลี่ยงการพึ่งพาที่ไม่จำเป็น

การพึ่งพาขณะรันไทม์ (Runtime Dependencies)

  • สิ่งที่พูดถึงก่อนหน้านี้จำกัดอยู่ที่ การพึ่งพาขณะ build/compile
  • แต่โปรเจกต์สมัยใหม่มักมี การพึ่งพาขณะรันไทม์ ด้วย:
    • ตัวอย่าง: Amazon S3, Google Firebase
    • บางอย่างแทบจะถูกมองว่าเป็นมาตรฐานโดยพฤตินัย (เช่น S3)
    • แต่การพึ่งพาขณะรันไทม์ส่วนใหญ่มีลักษณะของการ ผูกติด (Lock-in) กับบริการเฉพาะค่อนข้างมาก
  • แม้แต่ในอีก 10 ปีข้างหน้า การหาทางเลือกมาทดแทนบริการที่ใช้อยู่ในตอนนี้ก็อาจมีต้นทุนสูงมาก
  • จำเป็นต้อง ทำให้รายการการพึ่งพาบริการของบุคคลที่สามน้อยที่สุด หรือให้ไม่มีเลย:
    • โดยเฉพาะในการพัฒนาซอฟต์แวร์แบบ cloud native การใช้บริการของบุคคลที่สามระดับสูงจำนวนมากเป็นเรื่องปกติ
    • แต่สำหรับโปรเจกต์ระยะยาว การพึ่งพาแบบนี้มาพร้อมความเสี่ยงสูง
  • การพึ่งพาบริการในขั้น build time ก็เป็นปัจจัยสำคัญเช่นกัน:
    • ตัวอย่าง: หาก npm install ใช้งานไม่ได้อีกต่อไป ก็จะไม่สามารถ build ซอฟต์แวร์ได้เลย
    • สิ่งนี้อาจลดทอน ความสามารถในการนำกลับมาใช้ใหม่ ของโปรเจกต์อย่างรุนแรง
  • ตรวจสอบการพึ่งพาขณะรันไทม์อย่างเข้มงวด:
    • ตระหนักถึงปัญหา lock-in ที่อาจเกิดขึ้น และลดหรือตัดการพึ่งพาออก
  • ทำให้มั่นใจในความสามารถในการดูแลรักษาระยะยาว:
    • พิจารณาความเป็นไปได้ในการแทนที่ cloud หรือบริการของบุคคลที่สามไว้ล่วงหน้า

ทดสอบ ทดสอบ และทดสอบ

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

ความซับซ้อน: บอสสุดท้ายของการพัฒนาซอฟต์แวร์

  • ความซับซ้อนคือศัตรูตัวฉกาจสูงสุดของการพัฒนาซอฟต์แวร์:
    • แม้แต่นักพัฒนาหรือทีมที่เก่งที่สุดก็อาจพังทลายเพราะความซับซ้อน
    • ด้วยอิทธิพลของเอนโทรปีและพฤติกรรมมนุษย์ ความซับซ้อนจะเพิ่มขึ้นเสมอ
    • หากไม่จัดการความซับซ้อนอย่างมีสติ โปรเจกต์อาจตกสู่สภาพ บำรุงรักษาต่อไม่ได้
  • ความสัมพันธ์ระหว่างความซับซ้อนกับปริมาณโค้ด
    • ปริมาณโค้ดและความซับซ้อน:
      • เมื่อโค้ดยังน้อย แม้จะซับซ้อนบ้างก็ยังพอจัดการได้
      • ยิ่งโค้ดเพิ่มขึ้น ก็ยิ่งต้องรักษาความเรียบง่ายไว้จึงจะควบคุมได้
      • ความซับซ้อนที่จัดการได้ต้องอยู่ภายในขีดความสามารถของทีมและภายใน "สามเหลี่ยมสีเขียว"
    • ขีดจำกัดของความซับซ้อน:
      • ต่อให้เพิ่มจำนวนคนในทีมหรือจ้างนักพัฒนาที่เก่งมาก ก็ยังมีขีดจำกัดในการรับมือความซับซ้อน
      • เมื่อเลยขีดจำกัดไป โปรเจกต์จะตกอยู่ในสภาพที่บำรุงรักษาไม่ได้
  • เหตุผลที่โค้ดมักเคลื่อนไปทาง 'ขวาบน' อยู่เสมอ: (ในกราฟ)
    • มีการร้องขอฟีเจอร์เพิ่มขึ้น
    • มีความพยายามทำ optimization ที่ไม่จำเป็น
    • เวลาแก้บั๊กมักเพิ่มโค้ดใหม่ แทนที่จะลดความซับซ้อนเดิม
  • ต้นทุนของการออกแบบ API ที่ไม่ดี:
    • ตัวอย่าง: ฟังก์ชัน CreateFile ในหลายกรณีกลับไม่ได้สร้างไฟล์จริง ๆ
    • ความสับสนแบบนี้เพิ่ม ภาระทางการรับรู้ และเพิ่มโอกาสผิดพลาด
  • กลยุทธ์การจัดการความซับซ้อน
    • รีแฟกเตอร์ให้เร็ว และทำบ่อย ๆ:
      • ลบโค้ดที่ไม่จำเป็น และลงทุนเวลากับการทำให้เรียบง่าย
    • ลงทุนกับการทดสอบ:
      • ยิ่งมีการทดสอบมาก การลดความซับซ้อนก็ยิ่งทำได้ง่าย
    • ความสำคัญของการจัดการความซับซ้อน:
      • หากไม่ พยายามล่วงหน้า เพื่อทำให้เรียบง่าย โปรเจกต์ระยะยาวก็เสี่ยงจะลงเอยในสภาพ "บำรุงรักษาไม่ได้"

เขียนโค้ดที่น่าเบื่อและเรียบง่าย ให้เรียบง่ายกว่านั้นอีก และให้น่าเบื่อกว่านั้นอีก

"การดีบักยากกว่าการเขียนโปรแกรมสองเท่า ดังนั้นถ้าคุณเขียนโค้ดให้ฉลาดที่สุดเท่าที่ทำได้ตอนเขียน แล้วคุณจะดีบักมันได้อย่างไร?" - Brian Kernighan

  • เขียนโค้ดที่น่าเบื่อสุด ๆ และชัดเจน:
    • ให้ความสำคัญกับโค้ดแบบ naïve แต่ เข้าใจได้อย่างเป็นสัญชาตญาณ
    • "optimization ระดับพรีเมียมคือรากเหง้าของความชั่วร้ายทั้งปวง"
  • ทำ optimization เท่าที่จำเป็นจริง ๆ เท่านั้น:
    • ถ้ามันเรียบง่ายเกินไปจนกลายเป็นปัญหา การเพิ่มความซับซ้อนทีหลังไม่ใช่เรื่องยาก
    • และช่วงเวลานั้นอาจไม่มาถึงเลยก็ได้
  • หลีกเลี่ยงการเขียนโค้ดซับซ้อน:
    • รอจนกว่าจะถึงเวลาที่จำเป็นจริง ๆ
    • โอกาสที่จะเสียใจเพราะเขียนโค้ดเรียบง่ายนั้นต่ำมาก
  • โค้ดหรือฟังก์ชันที่มีประสิทธิภาพสูงอาจทำงานได้เฉพาะในบางสภาพแวดล้อมเท่านั้น
    • ตัวอย่าง:
      • LMDB: กว่า PowerDNS จะใช้งานได้อย่างเสถียรก็ผ่านความยากลำบากมามาก
      • RapidJSON: ไลบรารี JSON ที่เร่งด้วย SIMD ประสิทธิภาพสูงมาก แต่เงื่อนไขในการใช้งานค่อนข้างเข้มงวด
  • ต่อให้คุณมั่นใจว่า "ฉันเอาชนะข้อจำกัดนี้ได้":
    • ปีนี้อาจทำได้ แต่ในอีก 5 ปีข้างหน้า ตัวคุณเองหรือผู้พัฒนาคนถัดไปอาจเจอความยากลำบาก
    • หลักการเดียวกันนี้ใช้กับ ภาษาการเขียนโปรแกรมที่ซับซ้อน เช่นกัน
  • สรุป:
    • ทำให้โค้ดเรียบง่าย:
      • เรียบง่ายจริง ๆ และให้เรียบง่ายกว่านั้นอีก
    • เลื่อน optimization ไปทีหลัง:
      • ความซับซ้อนสามารถเพิ่มภายหลังได้เมื่อจำเป็น แต่ถ้าทำให้ซับซ้อนตั้งแต่ต้น การบำรุงรักษาจะยากขึ้น

การพัฒนาซอฟต์แวร์แบบอิง LinkedIn

  • ความจริง vs. อุดมคติ
    • แนวทางในอุดมคติ: เมื่อต้องเลือกการพึ่งพา ควรมีการประเมินและทบทวนอย่างละเอียด (ใช้เช็กลิสต์ที่เสนอไว้ข้างต้น)
    • แนวทางในโลกจริง: บางครั้งก็มักจะลองเทคโนโลยีที่ดูน่าสนใจ และถ้ามันใช้ได้ก็ใช้ต่อไปเลย
  • เหตุผลที่มันดึงดูดใจ
    • เป็นเทคโนโลยีที่คนดังหรืออินฟลูเอนเซอร์บน LinkedIn แนะนำ
    • เป็น "เฟรมเวิร์กล่าสุด" ที่ได้รับคำชมล้นหลามในชุมชนอย่าง Hacker News
  • เทคโนโลยีกระแสนิยมขาดการพิสูจน์ในระยะยาว:
    • อาจไม่เหมาะกับ "โครงการซอฟต์แวร์ที่จะต้องอยู่เกิน 10 ปี"
    • เทคโนโลยีใหม่มีโอกาสสูงที่จะเกิดปัญหาในด้านเสถียรภาพและการบำรุงรักษาในช่วงแรก
  • ข้อแนะนำ
    • ใช้เฉพาะในพื้นที่เชิงทดลอง:
      • ควรทดลองเทคโนโลยีใหม่กับโปรเจกต์เล็กหรือส่วนที่ไม่ใช่แกนหลักก่อน
    • คำนึงถึง Lindy effect:
      • อายุขัยของเทคโนโลยีมักมีแนวโน้มเป็นสัดส่วนกับระยะเวลาที่มันถูกใช้งานมาแล้ว
      • ยิ่งเป็นเทคโนโลยีเก่า ก็ยิ่งคาดหวังเสถียรภาพระยะยาวได้มากขึ้น
  • เทคโนโลยีใหม่อาจน่าดึงดูด แต่สำหรับโปรเจกต์ระยะยาว เทคโนโลยีที่ผ่านการพิสูจน์แล้วและมั่นคงย่อมเหมาะสมกว่า

Logging, telemetry, ประสิทธิภาพ

  • หากซอฟต์แวร์ไม่ได้รับการอัปเดตหรือ deploy อย่างต่อเนื่อง:
    • เมื่อเว็บไซต์พัง อาจไม่ได้รับ feedback ทันที
    • หลัง deploy แล้วอาจใช้เวลานานกว่าจะไปถึงการแก้ปัญหาจริง
  • ตั้งแต่รีลีสแรก ควรทำ logging และ telemetry อย่างรัดกุม:
    • บันทึก ประสิทธิภาพ, ความล้มเหลว, และ กิจกรรมการทำงาน ของซอฟต์แวร์
    • เมื่อเวลาผ่านไป ข้อมูลที่สะสมจะมีประโยชน์มากต่อการแก้บั๊กที่เกิดขึ้นไม่บ่อย
  • ปัญหาจาก logging ที่ไม่เพียงพอ:
    • มีการ deploy UI ให้ผู้ใช้ แต่มีผู้ใช้รายหนึ่งที่สร้าง 3000 โฟลเดอร์ แล้วรายงานปัญหา
    • ผู้ใช้บอกเพียงว่า "มันไม่ทำงาน" ทำให้ใช้เวลาหลายเดือนกว่าจะระบุสาเหตุที่แท้จริงได้
    • หากมี performance logging และ telemetry ก็อาจแก้ปัญหาได้เร็วกว่าเดิมมาก
  • logging และ telemetry เป็นสิ่งจำเป็น:
    • ควรออกแบบให้สามารถเฝ้าติดตามกิจกรรมของซอฟต์แวร์ได้อย่างละเอียด
    • ช่วยอย่างมากในการแก้ปัญหาที่ไม่คาดคิดระหว่างการ deploy และบำรุงรักษาในระยะยาว

เอกสาร

  • ความสำคัญของเอกสาร:
    • ไม่ใช่แค่เขียนเอกสาร API ให้ดี แต่ต้องอธิบายด้วยว่า "ทำไมจึงออกแบบแบบนี้"
    • บันทึกแนวคิดและปรัชญาเกี่ยวกับการทำงานของระบบ
    • ควรทิ้งเหตุผลไว้ว่า ทำไมจึงแยกวิธีแก้ออกมา และเหตุใดจึงตัดสินใจเชิงออกแบบที่ไม่ชวนให้เข้าใจทันที
  • สื่อที่มีประโยชน์นอกเหนือจากเอกสารสถาปัตยกรรม:
    • บล็อกโพสต์ภายใน: ให้นักพัฒนาแบ่งปันการอภิปรายอย่างอิสระเกี่ยวกับการออกแบบระบบ
    • การสัมภาษณ์ทีม: บันทึกบทสนทนาที่บอกภูมิหลังของการตัดสินใจด้านการออกแบบ
    • เอกสารเหล่านี้ช่วยถ่ายทอดความรู้ภายในทีมได้แม้เวลาจะผ่านไป
  • ใส่คอมเมนต์ไว้ในโค้ด:
    • แม้จะมีแนวโน้มที่ว่า "โค้ดที่ดีไม่ต้องมีคอมเมนต์" แต่ คอมเมนต์ที่อธิบาย 'ทำไม' ของโค้ดนั้นจำเป็นอย่างยิ่ง
    • สิ่งสำคัญคือการอธิบายเหตุผลว่าทำไมฟังก์ชันนั้นจึงมีอยู่
  • เขียน commit message:
    • commit message คือแกนหลักของบันทึกการทำงาน ซึ่งช่วยให้ติดตามเหตุผลของการเปลี่ยนแปลงโค้ดได้
    • ควรจัดสภาพแวดล้อมให้ผู้ใช้สามารถเปิดดู commit message ได้ง่าย
  • จัดสรรเวลาสำหรับการทำเอกสาร:
    • ในวันที่การพัฒนาไม่ค่อยราบรื่น ควรใช้เวลาไปกับการเขียนคอมเมนต์และบันทึกที่มีประโยชน์
    • ในระดับทีม ควรจัดเวลาให้การทำเอกสารอย่างสม่ำเสมอ
  • บันทึกว่าเหตุใดจึงออกแบบเช่นนั้น:
    • อีก 7 ปีข้างหน้า เอกสารที่ส่งต่อปรัชญาและภูมิหลังให้ทีมใหม่ได้จะมีค่ามากที่สุด
  • เก็บประวัติผ่านคอมเมนต์และ commit message:
    • เป็นองค์ประกอบสำคัญ ไม่ใช่แค่ระหว่างการพัฒนา แต่รวมถึงการบำรุงรักษาในระยะยาวด้วย

การจัดทีม

  • ความต่อเนื่องของทีมกับความสำเร็จระยะยาวของซอฟต์แวร์:
    • ซอฟต์แวร์บางประเภทถูกออกแบบมาให้รองรับนานถึง 80 ปี ในโปรเจกต์ระยะยาวเช่นนี้ การรักษาทีมไว้คือหัวใจสำคัญ
    • ในสภาพแวดล้อมการพัฒนาสมัยใหม่ การทำงานอยู่ราว 3 ปีมักถูกมองว่านานแล้ว
    • เอกสารและการทดสอบที่ดีช่วยบรรเทาปัญหาการเปลี่ยนทีมได้ในระดับหนึ่ง แต่ก็มีขีดจำกัด
  • ข้อดีของการทำงานระยะยาว:
    • รักษาสมาชิกทีมให้อยู่เกิน 10 ปี:
      • การจ้างเป็นพนักงานจริงและดูแลนักพัฒนาอย่างเหมาะสมเป็นสิ่งสำคัญ
      • ถือเป็น "hack" สำคัญต่อความสำเร็จของโปรเจกต์ระยะยาว
  • ปัญหาของการพึ่งพางาน outsource:
    • นักพัฒนาภายนอกมักส่งมอบโค้ดให้ระบบแล้วก็จากไป
    • หากเป้าหมายคือคุณภาพซอฟต์แวร์ที่ยั่งยืนเกิน 10 ปี นี่เป็นวิธีที่ไม่มีประสิทธิภาพอย่างยิ่ง
  • สร้างสภาพแวดล้อมที่สมาชิกทีมสามารถทำงานร่วมกันได้ในระยะยาว
  • ต้องมีกลยุทธ์ลดการพึ่งพาที่ปรึกษาภายนอก และเพิ่มความยั่งยืนของทีมภายใน

พิจารณาโอเพนซอร์ส

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

การตรวจสุขภาพของการพึ่งพา

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

หนังสืออ้างอิงสำคัญ

สุดท้าย

คำแนะนำสำคัญสำหรับการพัฒนาซอฟต์แวร์ระยะยาว:

  • รักษาความเรียบง่าย:
    • ทำให้เรียบง่าย และเรียบง่ายกว่านั้นอีก! เพราะสามารถเพิ่มความซับซ้อนได้เมื่อจำเป็น ดังนั้นอย่าทำให้ซับซ้อนเกินไปตั้งแต่แรก
    • การรักษาความเรียบง่ายต้องอาศัย การรีแฟกเตอร์และการลบโค้ดเป็นประจำ
  • คิดเรื่องการพึ่งพาอย่างรอบคอบ:
    • ยิ่งมีการพึ่งพาน้อยยิ่งดี ควร ตรวจสอบอย่างละเอียด และทำ audit
    • หากคุณไม่สามารถ audit การพึ่งพา 1600 รายการได้ ก็ควรทบทวนแผนใหม่
    • หลีกเลี่ยงการเลือกตามเทรนด์หรือกระแส (เช่น การพัฒนาแบบอิง LinkedIn)
    • ตรวจสอบการพึ่งพาเป็นประจำ: ติดตามสถานะของการพึ่งพาอย่างต่อเนื่อง
  • ทดสอบ ทดสอบ และทดสอบ:
    • เพื่อให้ทันต่อการเปลี่ยนแปลงของการพึ่งพา
    • ช่วยเพิ่มความมั่นใจระหว่างการรีแฟกเตอร์ และช่วยรักษาความเรียบง่าย
  • เอกสาร:
    • ไม่ใช่แค่ตัวโค้ด แต่รวมถึงปรัชญา แนวคิด และภูมิหลังของ "ทำไมจึงทำแบบนี้" ด้วย
    • เป็นทรัพย์สินล้ำค่าสำหรับสมาชิกทีมในอนาคต
  • รักษาทีมที่มั่นคง:
    • สำหรับการลงทุนในโปรเจกต์ระยะยาว ควรพิจารณา การจ้างงานระยะยาว
    • สนับสนุนให้สมาชิกทีมทุ่มเทกับโปรเจกต์ได้ต่อเนื่องเป็นเวลานาน
  • พิจารณาโอเพนซอร์ส:
    • หากทำได้ โอเพนซอร์สช่วยรักษามาตรฐานโค้ดให้สูงขึ้น
  • ล็อกและ performance telemetry:
    • มีบทบาทสำคัญในการค้นหาและแก้ปัญหาได้ตั้งแต่เนิ่น ๆ
  • คำแนะนำเหล่านี้อาจไม่ใช่เรื่องใหม่ แต่เมื่อเป็นสิ่งที่นักพัฒนามากประสบการณ์ย้ำอยู่เสมอ ก็มีคุณค่ามากพอที่จะนำมาคิดอย่างจริงจัง

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

 
kandk 2024-12-30

การแยกเลเยอร์ที่ความเสถียรมีความสำคัญออกจากเลเยอร์ที่ความเร็วมีความสำคัญ และการจัดการความสัมพันธ์ระหว่างสองส่วนนี้อย่างไร คือพลังทางวิศวกรรมที่สำคัญที่สุด
ถ้า Toss มุ่งแต่ความเสถียรอย่างเดียว ก็คงไม่ต่างอะไรจากธนาคารอื่น ๆ

 
kandk 2024-12-30

ที่เสี่ยงก็อย่าง SpaceX ด้วยครับ Tesla ก็เหมือนกัน..

 
aer0700 2024-12-25

หรือว่าปัญหาคือการพัฒนาที่ขับเคลื่อนด้วยเรซูเม่

 
GN⁺ 2024-12-23
ความเห็นจาก Hacker News
  • การอัปเดต toolchain อย่างจริงจังเป็นส่วนสำคัญของกระบวนการพัฒนา หลายบริษัทลดความสำคัญของการอัปเกรด toolchain จนก่อให้เกิดปัญหาอย่างช่องโหว่ด้านความปลอดภัย ทุกครั้งที่มีการออกคอมไพเลอร์หรือระบบบิลด์เวอร์ชันใหม่ จะสร้าง branch เพื่อตรวจสอบสถานะการบิลด์ และถ้ามีข้อผิดพลาดก็ถือว่าเป็นบั๊กและจัดการทันที สิ่งนี้ช่วยให้ค่อยๆ ปรับโค้ดเบสให้ทันสมัยและรีแฟกเตอร์ด้วยความสามารถใหม่ของภาษา

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

  • จำเป็นต้อง vendor dependency และจัดการผ่าน code review บ่อยครั้งที่คุณภาพของโค้ดจากภายนอกต่ำ จนการเขียนเองกลับเป็นทางเลือกที่ดีกว่า

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

  • การทำงานกับ Emacs Lisp เป็นประสบการณ์ที่สดใหม่ ข้อดีคือถึงไลบรารีจะไม่ได้อัปเดตก็ยังทำงานได้อย่างเสถียร ส่วนประสบการณ์กับ Gatsby และ Node นั้นลำบากเพราะปัญหาเรื่องการอัปเดต

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

  • การทำเอกสารของระบบและโค้ดเป็นสิ่งสำคัญ ยิ่งมีประสบการณ์พัฒนาซอฟต์แวร์มากเท่าไร ก็ยิ่งตระหนักถึงความสำคัญของเอกสารมากขึ้นเท่านั้น

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

  • วิธีที่ดีที่สุดในการเขียนซอฟต์แวร์ให้อยู่ได้นานคือการเขียนโค้ดที่ "น่าเบื่อ" ควรหลีกเลี่ยง dependency และยึดพื้นฐานให้มั่น

  • เคยมีประสบการณ์ลำบากกับปัญหา dependency ใน Python เรื่องนี้ถูกเรียกว่า "DLL Hell" และ COM ก็พยายามแก้ปัญหานี้แต่ไม่ประสบความสำเร็จนัก

  • แนวปฏิบัติที่ใช้กับซอฟต์แวร์ในภาคอุตสาหกรรมยังไม่แข็งแกร่งพอหากจะนำมาใช้กับซอฟต์แวร์ทั่วไป วิศวกรมักพยายามลดความเสี่ยง และเราก็มุ่งเน้นไปที่การลดความเสี่ยงเช่นกัน