32 คะแนน โดย xguru 2024-09-02 | 6 ความคิดเห็น | แชร์ทาง WhatsApp
  • การรีแฟกเตอร์โค้ดมีบทบาทสำคัญในการรักษาสุขภาพของโค้ดเบส
  • อย่างไรก็ตาม การรีแฟกเตอร์ที่ผิดพลาดอาจทำให้โค้ดยิ่งซับซ้อนและดูแลรักษายากขึ้น
  • ควรรู้วิธีแยกแยะระหว่างการรีแฟกเตอร์ที่ดีกับที่แย่ และวิธีหลีกเลี่ยงกับดักของการรีแฟกเตอร์ที่ไม่ดี

ข้อดี ข้อเสีย และด้านที่เลวร้ายของการรีแฟกเตอร์

  • abstraction อาจเป็นได้ทั้งเรื่องดีและเรื่องแย่ หัวใจสำคัญคือการรู้ว่าควรใช้เมื่อไรและใช้อย่างไร
  • อธิบายกับดักที่พบบ่อยบางอย่างและวิธีหลีกเลี่ยง (ละโค้ดต้นฉบับ)

1. เปลี่ยนสไตล์การเขียนโค้ดมากเกินไป

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

2. abstraction ที่ไม่จำเป็น

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

3. เพิ่มความไม่สอดคล้องกัน (Inconsistency)

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

4. ไม่เข้าใจโค้ดก่อนรีแฟกเตอร์

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

5. เข้าใจบริบทธุรกิจ

  • การเลือกเทคโนโลยีโดยไม่เข้าใจธุรกิจอาจกลายเป็นหายนะได้
  • สำหรับเว็บไซต์อีคอมเมิร์ซที่พึ่งพา SEO อย่างมาก การเรนเดอร์ฝั่งไคลเอนต์อาจเป็นตัวเลือกที่ไม่ดี
  • แนวทาง server-side rendering อย่าง Next.js หรือ Remix อาจเป็นทางเลือกที่ดีกว่าในแง่ SEO และประสิทธิภาพ

6. รวมโค้ดมากเกินไป

  • การรวมโค้ดเพื่อให้ดู "สะอาด" โดยต้องแลกกับความยืดหยุ่นไม่ใช่เรื่องที่ดี
  • เวลาทำ abstraction ควรคำนึงถึง use case ที่มันรองรับเสมอ
  • ควรทำให้ abstraction รองรับความสามารถทั้งหมดที่ implementation เดิมเคยมี

รีแฟกเตอร์อย่างถูกวิธี

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

เครื่องมือและเทคนิคเพื่อการรีแฟกเตอร์ที่ดีขึ้น

  • ลองพิจารณาใช้เทคนิคและเครื่องมือต่อไปนี้เพื่อช่วยให้การรีแฟกเตอร์ดีขึ้น:

เครื่องมือ linting

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

การรีวิวโค้ด

  • ทำ code review อย่างรอบคอบเพื่อรับฟีดแบ็กจากเพื่อนร่วมงานก่อน merge โค้ดที่รีแฟกเตอร์แล้ว
  • ช่วยค้นพบปัญหาที่อาจเกิดขึ้นได้ตั้งแต่เนิ่น ๆ และทำให้มั่นใจว่าโค้ดที่รีแฟกเตอร์สอดคล้องกับมาตรฐานและความคาดหวังของทีม

การทดสอบ

  • เขียนและรันเทสต์เพื่อให้แน่ใจว่าโค้ดที่รีแฟกเตอร์จะไม่ทำให้ความสามารถเดิมเสียหาย
  • Vitest เป็น test runner ที่เร็ว แข็งแรง และใช้งานง่าย โดยแทบไม่ต้องตั้งค่าเริ่มต้น
  • สำหรับ visual testing อาจพิจารณาใช้ Storybook
  • React Testing Library เป็นชุดยูทิลิตีที่ดีสำหรับทดสอบคอมโพเนนต์ React (และยังมีเวอร์ชันดัดแปลงสำหรับ Angular เป็นต้น)

เครื่องมือ AI (ที่เหมาะสม)

  • สนับสนุนความพยายามในการรีแฟกเตอร์ด้วยเครื่องมือ AI ที่สามารถปรับให้เข้ากับสไตล์และกฎการเขียนโค้ดเดิมได้
  • Visual Copilot เป็นเครื่องมือที่มีประโยชน์อย่างยิ่งในการรักษาความสอดคล้องระหว่างการเขียนโค้ดฝั่งฟรอนต์เอนด์
    • ช่วยแปลงดีไซน์เป็นโค้ดโดยให้สอดคล้องกับสไตล์การเขียนโค้ดเดิม และใช้คอมโพเนนต์กับโทเคนของ design system ได้อย่างถูกต้อง

บทสรุป

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

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

 
toaonly 2024-09-04

บางคนก็เริ่มรีแฟกเตอร์กันพรวดพราดทั้งที่ยังไม่มีโค้ดทดสอบด้วยซ้ำ
พอมองไปเรื่อย ๆ ก็เหมือนกำลังไต่เส้นบาง ๆ แบบเสี่ยงอันตรายสุด ๆ เลย ตื่นเต้นดีเหมือนกัน 555

 
ahwjdekf 2024-09-03

ข้อ 4, "ไม่ทำความเข้าใจโค้ดก่อนรีแฟกเตอร์" เป็นประเด็นที่โดนใจมากจริง ๆ ครับ

 
bichi 2024-09-02

เป็นคำพูดที่ชัดเจนมากและเหมือนเป็นพื้นฐานอยู่แล้วนะ 555 แต่การที่สรุปออกมาให้แบบนี้ก็ดูดีมากเลย พอนึกถึงการรีแฟกเตอร์ ผมมองว่าสุดท้ายมันควรจะได้โค้ดที่ดีขึ้น 100% ถ้าไม่ใช่ แบบนั้นก็แปลว่าฝีมือผมถอยหลังลงจากเมื่อวานไม่ใช่เหรอ?

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

 
kandk 2024-09-02

แทนที่จะเป็นวิธีรีแฟกเตอร์ให้เก่งกว่า มันใกล้เคียงกับวิธีเขียนโค้ดให้เก่งในงานจริงมากกว่า..
(เหมือนเป็นโพสต์ที่เขียนด้วยความหัวร้อนเพราะมีจูเนียร์เข้ามาบอกว่าจะรีแฟกเตอร์โปรเจ็กต์เลกาซี แล้วทำให้มันซับซ้อนไปทั่วและสร้างบั๊กขึ้นมา...)

 
savvykang 2024-09-02

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

 
savvykang 2024-09-02

ผมเคยเจอกรณีหนึ่งที่เป็นสัญญาณของการทำ abstraction มากเกินไปใน React คือทั้งที่ table component ถูก abstract ไว้แล้วโดย UI framework แต่แค่เพราะ schema ของตารางสองตัวดูคล้ายกัน ก็ไปใช้ inversion of control เพื่อสร้างคอมโพเนนต์ใหม่ที่ไม่ได้มีบทบาทอะไรเลย ซึ่งผมคิดว่าควรหลีกเลี่ยงครับ พอเห็นกรณีที่บอกว่าจะใช้ atomic design แล้วสร้างคอมโพเนนต์เปลือก ๆ ยาวสิบกว่าบรรทัดแบบพร่ำเพรื่อ มันทำให้ต้องไล่ดูหลายส่วนเกินไปจนใช้งานลำบากมาก

เดิมทีหลักการ DRY มีเจตนาแค่ว่าอย่าก๊อปปี้โค้ดที่หน้าตาเหมือนกันและทำหน้าที่เดียวกันแบบตรง ๆ แต่ดูเหมือนว่าจะต้องมีคนที่เข้าใจมันผิดอยู่เสมอ หรือว่าคำเตือนที่ว่าอย่าเชื่อ design pattern แบบงมงาย ก็มาจากบริบทแบบนี้หรือเปล่าครับ