Refactoring จากมุมของ Kevlin Henney
เป็นตัวอย่างที่ชอบ จากที่ Kenvlin Henney พูดไว้ใน งาน NDC oslo 2022 ในห้วข้อที่ว่า Refactor is not just clickbait ครับ
Refactoring คือการเปลี่ยนแปลงโค้ดของโปรแกรมซึ่งจะมีคุณลักษณะที่สำคัญ 2 อย่าง
- เปลี่ยนแปลงโครงสร้างระบบเพื่อ ให้เข้าใจง่ายขึ้น นำมาสู่การปรับปรุงโปรแกรมเมื่อเวลาต้องการเปลี่ยนแปลง ได้ง่าย เบา และไม่เปลืองแรง
- การเปลี่ยนแปลง ต้องไม่ทำให้ พฤติกรรมเดิมที่สังเกตได้จากมุมมองผู้ใช้ ไม่เปลี่ยนแปลง ยกตัวอย่างเชิงเปรียบเทียบเหมือนในวิชาคณิตศาสตร์ เช่น
2 x 2 x 2 x 2 = 16
4 x 4 = 16
อย่างในตัวอย่าง เราจะเห็นว่า เราเปลี่ยนโครงสร้างวิธีการคูณ จาก 4 ตัว เหลือ 2 ตัว แต่ output สุดท้าย ยังคงเท่าเดิม
ในทาง Programming ถ้าเราลองเขียน Code Stack ขึ้นมา ซึ่งจะประกอบด้วย Function Push / Pop แล้วเราเก็บข้อมูลใน array การเปลี่ยนแปลงโครงสร้างว่า จะดึงที่หัว(index 0) หรือ ตำแหน่งท้าย (length-1) ก็จะไม่ทำให้ผลลัพธ์ ของ Function Push Pop เปลี่ยนไป เช่นเดียวกัน
ถ้าเรื่องของ Code Quality ประกอบด้วย 3 เสา คือ
- Functional ได้ Function ตามที่ต้องการ และทำงานถูกต้อง
- Operational มีประสิทธิภาพ
- Developmental ดูแลจัดการ ตรวจสอบแก้ไข เพิ่มเติม ได้ง่าย
Refactor เป็นงานๆ หนึ่งที่ ถือว่า undervalue มาก แต่ก็เป็นงานเดียวที่สามารถ improve ในเรื่องของ Developmental Result ได้
ตัวอย่างโค้ดชุดนึงที่เขา ยกมาแล้วส่วนตัวชอบมาก แล้วมักจะใช้ Reference บ่อยๆ คือโค้ดชุดนี้
if (portfolioIdsByTraderId.get(trader.getId()).containKey(portfolio.getId()) {
...
}
ถ้ามองเผินๆ ก็จะเห็นว่า ไปอ่านรายการ port ของ trader แล้วมาเทียบว่ามี key portfolio ตั้วนั้นตัวนี้หรือเปล่า ซึ่ง Technically ก็เข้าใจ
แต่ถ้าปรับโค้ดให้เป็นแบบนี้จะเข้าใจได้อย่างไม่ต้องคิดอะไรเยอะ
if trader.canView(portfolio) {
...
}
อันนี้คือการ refactor โดยการเพิ่ม Abstraction Layer เข้าไป ซึ่ง หลายคนมักจะเข้าใจผิดเพิ่มคำนัวๆ กว้างๆ ไป แต่ คำแนะนำคือ ควรใช้คำที่มีรายละเอียดมากพอ ใน Layer นั้นๆ เช่น ส่วนใหญ่ Layer ด้านบนอาจจะเป็น Biz Layer เราก็เอา Word ของ Biz มาใช้ ให้เข้าใจมากขึ้น
ตัวอย่างที่น่าสนใจ อีกเรื่อง จะเป็นเรื่องของการ Refactoring Code ยาวๆ แล้ว พอเราไม่ได้ทำความเข้าใจมันดีๆ อาจจะสร้างงานด้วย การ ทำ Premature Refactor ได้
เช่น โค้ดชุดนี้ มี while กับ if รัวๆ ถ้าอยู่ๆ ไปทำ Extract method เราอาจจะได้ การทำ sub function ที่เป็น ทำตามหลักไปเรื่อยๆ
แต่ถ้าเราเข้าใจ control flow แล้ว พอเข้าใจว่า if กับ while มันแทนกันได้ในบางกรณี เราสามารถจะ ปรับได้เป็นแบบนี้
จากนั้นเราจะเริ่มเห็น pattern ที่แท้จริงของ มัน ว่า clause เดียวกัน ต่างกันแค่ value เท่านั้นเอง
พอเราเข้าใจ Control Flow ของมัน จะทำให้ การ Refactor มัน Precise มากขึ้น ไม่ใช่แค่ ทำตาม Refactoring Checklist แล้วดูว่า มี Smell อะไรเกิดขึ้นบ้าง
อีกตัวอย่างหนึ่ง คือ เป็นคำสั่ง อะไรสักอย่าง
ซึ่งเมื่อพออ่านไปคร่าวๆ พบว่า มันคือ การ remove duplicate เราก็พอจะสามารถใช้ extract method ได้
อย่างไรก็ตาม ถ้าสังเกตในรายละเอียดของคำสั่งนี้จริงๆ จะพบว่า การ remove duplicate มันมีข้อจำกัด คือ เป็นการ remove ที่ตำแหน่งติดกันเท่านั้น ถ้าเราใช้ remove duplicate ไปเลย มันจะกว้างเกินไป และจะทำให้คนอื่นเข้าใจรายละเอียดของโปรแกรมผิดได้ จึงควรจะปรับให้ มีรายละเอียดตามที่เขียนจริงๆ
อย่างไรก็ตาม ในระบบของภาษามันก็อาจจะมี function ที่ช่วยงานเราในเรื่องนี้อยู่แล้ว แต่เราอาจจะคาดไม่ถึง หรือ คิดชื่อมันตรงๆ ไม่ออกในตอนแรก แต่เมื่อทุกอย่างเคลียร์ก็จะเริ่ม เห็นรูปร่างว่า เราต้องการ function อะไร
จบอย่างนี้ได้เลย…
แต่ยังไม่พอ ถ้าเรารู้อยู่แล้วว่า เราไม่ต้องการ ของซ้ำ และเราต้องการการเรียงลำดับ ในภาษาอาจจะมี Data Structure ที่เหมาะสมอยู่แล้ว รองรับอยู่ และจำช่วยให้เราเข้าใจง่ายขึ้นและมีประสิทธิภาพได้ เช่น
Refactoring หลายคนมักจะงบง่ายๆ แค่ จัดหน้าจัดตา ชื่อ ไฟล์ if else แต่มันมีหลายมิติมากกว่านั้น
จุดสำคัญที่ Kevlin เน้นในการทำพวกนี้คือ พฤติกรรมต้องเหมือนเดิม นั่นทำให้ การค่อยๆ ปรับค่อยๆ แก้ไข เป็นอะไรที่แนะนำมากกว่า refactor แบบ Big Bang เพราะถ้ามีปัญหา จะได้ ย้อนกลับมาดูได้ง่ายๆ
และก่อนที่จะดูให้ พิจารณาภาพรวม ก่อน เช่น control flow , data flow ต่างๆ อย่า หลับหูหลับตาม refactor เลย เพราะอาจจะเกิดผลเสียมากกว่าได้
อีกจุดคือ เมื่อเราค่อยๆ ปรับไปเรื่อยๆ เราจะเพิ่มพัฒนาแนวคิด และ เห็นภาพรวม รูปแบบต่างๆ มันจึงนำมาสู่ท่าที่ Simplified ขึ้น ได้
เปรียบเทียบเหมือน งาน Creative ใหญ่ๆ มันไม่เคยเกิดมาจาก Big Bang แค่ครั้งเดียว แต่เกิดจาก การลองผิดลองถูกเคส ย่อยๆ หลายๆ ครั้ง จับรูปแบบ การตอบรับ แล้วมาสรุปเป็นองค์ความรู้ เรื่อยๆ จน ปล่อยงานที่เป็น Final ได้
ถ้าใครสนใจ ฟังเต็มได้ที่ข้างล่างต่อครับ