Refactor เมื่อไหร่ดี?

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

ผมพบว่าข้อผิดพลาดในการ Refactor มักจะมี 2 แบบ

  1. Refactor เร็วไป
  2. Refactor ช้าไป

กำปั้นทุบดินน่าดูเลยแฮะ…. โอเคฮะ สรุปแล้วเราไม่ควร Refactor เร็วเกินไปและช้าเกินไปนี่เอง เออ เนอะ ง่ายจัง แหม่

โอเค มาว่ากันเรื่องหลักการนิดๆ ดีกว่า


Refactor too fast

หลักๆ Refactor เนี่ย เรามักจะทำเพื่อลด Duplication ซึ่ง Refactor เร็วเกินไปที่ผมเจอบ่อยมากคือ ไปเจอสิ่งที่ผมเรียกว่า “โค้ดที่เหมือนกันแต่ไม่ Duplicate กัน”

เหตุการณ์นี้จะเกิดตอนที่ Developer เข้าใจแต่โค้ดแต่ไม่ได้เข้าใจตัว Business ดังนั้น แค่เห็นโค้ดที่ซ้ำกันก็ตีความว่ามันเป็น Duplication แต่จริงๆ มันไม่ใช่ มันแค่ “บังเอิญ” เหมือนกันเท่านั้น พอปรับโปรแกรมไปแค่นิดเดียว มันก็ไม่เหมือนกันอีกต่อไปแล้ว

ผมยกตัวอย่าง ง่ายๆ โปรแกรมบันทึกผลการตรวจเช็ค Maintainance เครื่องจักรกลในโรงงาน มีเครื่องจักรประเภท กลึง หล่อ ตัด ซึ่งแต่ละเครื่องจักรลูกค้าบอกว่าใช้แบบฟอร์ม Checklist การตรวจเหมือนกัน มีฟิลด์ข้อมูลที่ต้องบันทึกหลังตรวจสอบเหมือนกันทุกประการ

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

ดังนั้นผมจะสร้าง Model 3 แบบ โดยทั้ง 3 Model จะมีชื่อฟิลด์เหมือนกัน เราจะมี 3 Model ที่ชื่อฟิลด์เหมือนกัน Duplicate กันแบบตัวอักษรต่อตัวอักษร เพราะในทางโค้ดดิ้ง ใช่ มันเหมือนกัน มันซ้ำกัน แต่ในมุม Business ไม่มี User คนไหนคิดหรอกว่า ผลการตรวจเครื่องกลึง มันเหมือนกับผลการตรวจเครื่องหล่อ (ดีไม่ดีแค่หัวกระดาษที่ไปตรวจหน้างานก่อนมาบันทึกลงระบบก็คนละหัวกันแล้ว)

เคสแบบนี้แหละที่ผมเรียกว่า “โค้ดเหมือนกันแต่ไม่ Duplicate กัน” ผมมั่นใจมากๆ ว่าอนาคตมันเวลามันปรับมันจะไม่มีทางเหมือนกันแน่ๆ ผู้ใช้เค้ามองว่าเอกสาร 2 ใบนี้มันเป็นคนละโมเดล เพียงแค่ฟลุ๊กว่าของที่ต้องกรอกดันเหมือนกันในตอนนี้ (ซึ่งอาจจะเป็น Sharing field หรืออาจจะเป็น Just a fluke ไปเลยก็ได้)

แล้วการ Refactor เร็วไปมักจะเกิดตอนนี้ คือ เกิดขึ้นตอนที่ Developer เห็นว่าโค้ดซ้ำกันก็รีบ Refactor เลยทันทีให้เป็นโมเดลเดียวกัน Refactor ตั้งแต่ตอนต้น Requirement ก็จะคล้ายๆ กับที่ผมเคยเขียนไว้ในเรื่อง Premature optimization


Refactor too slow

สัญญาณที่จะเห็นชัดว่าเรา Refactor ช้าไปคือเมื่อต้องการแก้ไขอะไรบางอย่างแล้วเราต้อง Find & Replace ทั้งโค้ดเบส แล้วก็ไม่มั่นใจว่า เห้ย แก้ครบหรือเปล่า นั่นแหละคือ Best signal ว่าคุณควรจะ Refactor ได้แล้ว


How to avoid it?

หัวข้อว่าเมื่อไหร่ควรจะ Refactor มันเป็นหัวข้อที่เถียงกันตลอดกาลและไม่มีคำตอบสำเร็จรูปประเภทที่ว่า “นี่แหละดีที่สุด” แต่สำหรับผมจะมี Trick ง่ายๆ ที่ผมใช้ส่วนตัวดังนี้

  1. ถ้าได้รับ Requirement มา ทำฟีเจอร์เสร็จปุ๊ปแล้ว Refactor เลย นั่นแหละ โอกาสเร็วเกินไปมีเยอะมาก เพราะ Requirement เปลี่ยนได้เสมอ
  2. ถ้าทำแบบ Agile แล้ว Requirement คงที่เกิน 2 Sprint อันนั้นแหละคือสัญญาณที่ดีแล้วว่าไม่น่าจะเร็วเกินไป
  3. แต่ถ้าการแก้ไขโค้ด การเพิ่ม Feature ต้องเริ่มใช้ Find & Replace all เมื่อไหร่ อันนี้แหละคือสัญญาณว่าเราทำช้าไปแล้ว แสดงว่ามันมี Duplication ที่ควรจะ Abstract ออกมาจริงๆ

อันนี้เป็นหลักการง่ายๆ ที่พอจะใช้ได้บ้างครับสำหรับคนที่ยังไม่มีประสบการณ์ขนาดที่จะมอง Requirement หรือลงไป Business ปุ๊ปรู้เลยว่าอะไรเป็นอะไร (ถึงทุกวันนี้ผมก็ยังไม่รู้ขนาดนั้นครับ แต่การ “มองพลาด” เป็นเรื่องปกติที่เราต้องเจอ ให้เทพขนาดไหนก็ยังเกิดขึ้นได้)


ข้อสำคัญที่สุด คือ Refactor นั้นเป้าหมายคือทำให้โค้ดเปลี่ยนง่าย Developer มันใจว่าเปลี่ยนแล้วไม่พัง ดังนั้น ถ้าเริ่มมีความรู้สึกว่า “ไม่อยากเปลี่ยน กลัวพัง” นั่นแหละคือสัญญาณที่ดีที่สุดว่า ควรจะ Refactor แล้วมันช้าไปแล้ว

และตรงข้าม ถ้ามีความรู้สึกว่า “Refactor แบบนี้แล้วเปลี่ยนยาก ไม่อยากแก้โค้ด” นั่นคือสัญญาณที่ดีที่สุดว่าเราทำเร็วเกินไป

สัญญาณที่มาจากความรู้สึกของทีมนี่เป็นสิ่งที่ควรฟัง ควรฟังยิ่งกว่าหลักการใดๆ ทั้งสิ้น

เพราะอะไร? เพราะแต่ละทีมพัฒนาและโปรแกรมเมอร์แต่ละคนไม่ได้มีความสามารถเท่ากัน บางทีมบางคนอาจจะรู้สึกว่าโค้ดแบบนี้ยังไม่เละ ยังแก้ไขง่าย บางทีมบางคนอาจจะแค่นิดหน่อยก็ไม่อยากจะแตะโค้ดแล้ว กลัวพังแล้ว

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

ถ้าทันทีที่คนในทีมเริ่มไม่มั่นใจที่จะลงมือแก้ไขโค้ดที่มี ไม่ว่าจะด้วยเหตุผลใดก็ตาม ไม่ว่าจะมาจากโค้ดเละไม่เป็นระเบียบ หรือโค้ดเป็นระเบียบมากจนไม่อยากแก้ นั่นคือสัญญาณที่ดีที่สุดที่บอกว่า มีบางอย่างผิดพลาด (อาจจะไม่ใช่เรื่อง Refactor อย่างเดียว อาจจะเป็นเรื่องที่เราแชร์ความรู้กันน้อยไปก็ได้)

เพราะทันทีที่เราไม่มั่นใจ คิดแล้วคิดอีกก่อนจะลงมือโค้ด กลัวว่าอันนั้นจะพังมั้ย กลัวว่าอันนี้จะพังมั้ย นั่นแหละคือจุดที่ Productivity ของ Developer จะลดลงอย่างมหาศาล

และการป้องกันสิ่งนี้ไม่ให้เกิดขึ้นนั่นแหละคือที่มาและหลักการทั้งปวงที่ทำให้เกิด Refactoring, Design Pattern และ Code quality สุดท้ายจะอ้าง Paradigm หรือหลักการอะไร มันก็จบลงที่เป้าหมายง่ายๆ แค่นี้เองครับ

เพราะสุดท้าย เราไม่ได้อยากได้ Codebase ที่ Kent Beck หรือ Martin Fowler ลงมาอ่านแล้วทำงานได้ไว แก้ไขได้ไว แต่เราอยากได้โค้ดเบสที่คนในทีม เพื่อนในทีม ทำงานได้ไง แก้ไขได้ไว ใช่มั้ยล่ะครับ

Refactor for the sake of productivity, not for the sake of refactoring.
One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.