77 คะแนน โดย GN⁺ 2024-11-18 | 9 ความคิดเห็น | แชร์ทาง WhatsApp
  • บทความนี้ไม่ใช่คำแนะนำ แต่เป็นการเขียนถึงนิสัยการพัฒนาที่ผู้เขียนกำลังนำมาใช้ในปัจจุบัน
  • เป็นบทความที่สรุปประสบการณ์จากการพยายามหลีกเลี่ยงนิสัยที่ไม่ดีและสร้างนิสัยที่ดีขึ้น โดยกล่าวถึงนิสัย 10 ข้อที่ช่วยเพิ่มประสิทธิภาพการทำงานและรักษาคุณภาพ

1. รักษาให้คอมมิตมีขนาดเล็ก

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

2. รีแฟกเตอร์อย่างต่อเนื่อง

  • คำแนะนำของ Kent Beck: "เมื่อคุณต้องการเปลี่ยนแปลงบางอย่าง จงทำให้การเปลี่ยนแปลงนั้นทำได้ง่ายก่อน แล้วค่อยทำการเปลี่ยนแปลงที่ง่ายนั้น"
  • อย่างน้อยครึ่งหนึ่งของคอมมิตควรมีการรีแฟกเตอร์รวมอยู่ด้วย รีแฟกเตอร์เล็กๆ ช่วยได้มากเมื่อมีความต้องการขนาดใหญ่เข้ามา
  • ควรหลีกเลี่ยงการรีแฟกเตอร์ครั้งใหญ่ แต่ให้ทำการปรับปรุงเล็กๆ อย่างต่อเนื่องภายในเวลาไม่เกิน 10 นาที

3. ความสำคัญของการ deploy โค้ด

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

4. อย่าทดสอบความสามารถของเฟรมเวิร์ก

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

5. สร้างโมดูลใหม่

  • หากฟังก์ชันบางอย่างไม่เข้ากับโมดูลเดิม ก็ควรสร้างโมดูลใหม่จะดีกว่า
  • การปล่อยให้มันเป็นโมดูลอิสระย่อมดีกว่าการยัดฟังก์ชันเข้าไปในโมดูลเดิมแบบฝืนๆ

6. ใช้การพัฒนาแบบขับเคลื่อนด้วยการทดสอบ (TDD) อย่างยืดหยุ่น

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

7. อนุญาตให้คัดลอกวางได้แค่ครั้งเดียว

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

8. ยอมรับการเปลี่ยนแปลงของดีไซน์

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

9. หนี้ทางเทคนิค 3 ประเภท

  • หนี้ทางเทคนิคสามารถแบ่งได้เป็น 3 ประเภท:
    1. สิ่งที่ขัดขวางงานปัจจุบัน
    2. สิ่งที่อาจขัดขวางงานในอนาคต
    3. สิ่งที่อาจจะขัดขวางก็ได้
  • ควรลดหนี้ประเภทแรกให้เหลือน้อยที่สุด มุ่งเน้นที่ประเภทที่สอง และมองข้ามประเภทที่สาม

10. ความสัมพันธ์ระหว่างการทดสอบได้กับการออกแบบที่ดี

  • ถ้าทดสอบได้ยาก ก็มีความเป็นไปได้สูงว่าการออกแบบมีปัญหา
  • การออกแบบเทสต์เองก็อาจเป็นสิ่งที่ต้องปรับปรุงได้ เช่น หากรู้สึกว่ายากที่จะเขียน mock สำหรับ em.getRepository(User).findOneOrFail({id}) ก็ควรแยกออกเป็นฟังก์ชันต่างหาก หรือใช้ test utility
  • สาเหตุที่ไม่มีการเขียนเทสต์ มักเป็นเพราะมันทดสอบยาก และนั่นอาจเป็นปัญหาด้านการออกแบบ

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

 
yangeok 2024-11-25

ดูเหมือนว่าต้องทำให้บรรลุ SRP มากกว่า DRY ถึงจะฝากให้ AI ทำแล้วไม่พูดเพ้อเจ้อ

 
progdesigner 2024-11-21

ผมคิดว่าสิ่งที่สำคัญที่สุดคือคุณสร้างโค้ดและสภาพแวดล้อมที่สามารถปรับตัวต่อการเปลี่ยนแปลงได้รวดเร็วแค่ไหน

และด้วยการทำ abstraction ที่เหมาะสม ก็สามารถเพิ่มการนำโค้ดกลับมาใช้ซ้ำและความสามารถในการขยายต่อได้ พร้อมทั้งใช้เครื่องมือ AI เพื่อเร่งความเร็วในการพัฒนาให้สูงสุดได้

 
pcj9024 2024-11-20

เป็นบทความที่ดีมากจริง ๆ อยากแนะนำต่อไปทั่วเลย

 
tsboard 2024-11-20

ยอมรับการเปลี่ยนแปลง, คัดลอก-วางแค่ครั้งเดียว, ทำให้เทสต์ทำงานได้ดีขึ้น, คอมมิตให้เล็กลง...!

 
aer0700 2024-11-19

เป็นบทความที่ดีนะ

 
puersum 2024-11-19

บทความนี้น่าจะดีมากถ้าได้ไปดูต้นฉบับกันด้วยนะครับ
ปกติถ้าเป็นข่าวที่ผมสนใจก็มักจะไปดูต้นฉบับอยู่แล้ว แต่เรื่องนี้ยิ่งควรทำแบบนั้น โดยเฉพาะถ้าดูข้อ 1 ต้นฉบับเขียนไว้ว่า
Keep commits small enough that you wonder if you're taking this "keep commits small" thing a little too far. แต่ถูกย่อสรุปเป็นว่า "ควรรักษาให้คอมมิตเล็กที่สุดเท่าที่จะทำได้" เลยนะ..

 
ilbanin00 2024-11-19

เป็นบทความที่ดีมากจริง ๆ

 
joon14 2024-11-19

ข้อ 7 ดีมากจริง ๆ

 
GN⁺ 2024-11-18
ความคิดเห็นจาก Hacker News
  • ควรใช้พารามิเตอร์เพื่อหลีกเลี่ยงการทำหลาย implementation การปรับปรุงพารามิเตอร์ทำได้ง่ายกว่าการรวมหลาย implementation เข้าด้วยกัน

    • หากหลีกเลี่ยง "พารามิเตอร์ประหลาด" ไม่ได้ ก็ควรแยกโค้ดออกจากกัน ควรหลีกเลี่ยง boolean flag และพารามิเตอร์ enum หลายตัว
    • function signature ที่ซับซ้อนทำให้การบำรุงรักษายากขึ้น
  • การคัดลอกโค้ดครั้งเดียวอาจพอรับได้ แต่ตั้งแต่ครั้งที่สองเป็นต้นไปควรหลีกเลี่ยงความซ้ำซ้อน ควรสร้าง abstraction ที่ดีเมื่อมี data point มากพอ

    • แม้โค้ดจะเหมือนกันในตอนแรก แต่เมื่อจำเป็นต้องเปลี่ยนแปลง ควรโฟกัสว่ามันจำเป็นต้องเปลี่ยนไปพร้อมกันหรือไม่
    • เป้าหมายไม่ใช่การหลีกเลี่ยงโค้ดซ้ำ แต่คือการดูแลโค้ดที่ต้องพัฒนาไปด้วยกันให้อยู่ด้วยกัน
  • DRY (อย่าทำซ้ำ) หรือ WET (เขียนทุกอย่างสองครั้ง) ไม่ใช่กฎตายตัว ปัญหาที่ยากคือการเข้าใจเรื่องความซ้ำซ้อนของโค้ดและจังหวะที่ควรรวมมันเข้าด้วยกัน

  • แทนที่จะทำ commit เล็ก ๆ อย่างเดียว อีกทางเลือกหนึ่งคือสามารถเพิ่ม commit ใหม่เพื่อแก้บั๊กได้โดยไม่ต้อง revert commit ใหญ่

    • ยังไม่ชัดเจนว่าทำไมการ refactor ครั้งใหญ่ถึงเป็นสิ่งไม่ดี
    • การสร้างโครงสร้างที่เป็นอิสระดีกว่าการยัดมันเข้าไปในโมดูลเดิมแบบฝืน ๆ
    • ตอนออกแบบ API อาจใช้ design session แทน unit test ได้
  • ความสามารถในการทดสอบเกี่ยวข้องกับการออกแบบที่ดี สิ่งที่ทดสอบได้ไม่ง่ายอาจเป็นสัญญาณว่าจำเป็นต้องเปลี่ยนการออกแบบ

    • โค้ดทดสอบก็ควรได้รับการทบทวนด้วยวิธีอื่นเช่นกัน
  • ควรระวังเมื่อทดสอบความสามารถของ framework เพราะ framework อาจเปลี่ยนไปตามเวลา

    • บทบาทสำคัญของการทดสอบคือช่วยยืนยันว่าปลอดภัยเมื่ออัปเกรด dependency
  • สำหรับขนาดของ commit ควรมุ่งไปที่ commit ที่ revert ได้ง่าย เผื่อกรณีที่ต้องย้อนการเปลี่ยนแปลงบางอย่าง

  • บริษัทต่าง ๆ ต้องการ codebase ที่เสถียร แต่ก็ยังต้องมีการ refactor อย่างต่อเนื่อง ซึ่งอาจขัดแย้งกับความเสถียรได้