บล็อกนี้ขอเริ่มต้นด้วยคำถามสักข้อนึงก่อน
เคยไหม ที่จะต้องอ่านโค้ดหน้านึงยาวเป็นร้อยๆบรรทัด?
แล้วแฮปปี้ไหม กับการอ่านโค้ดแบบนั้น?
ถ้าคำตอบในใจคือไม่แฮปปี้ … วันนี้คุณเปิดมาถูกที่แล้ว
เราอาจเคยได้ยินคำว่า Separation of Concerns ในวงการโปรแกรมมิ่ง
มันคือการหั่นโค้ดออกมาเป็นชิ้นย่อยๆเล็กๆ ให้ต่างโค้ดต่างทำงานตามหน้าที่ของมัน เพื่อให้ดูแลโค้ดได้ง่ายขึ้น แก้ง่ายขึ้น และเพิ่มโค้ดได้ง่ายขึ้น
พออะไรๆก็ง่าย เราก็เขียนโค้ดได้อย่างมีความสุข ไม่ต้องมานั่งหงุดหงิด เวลานั่งทำงานหรือแก้บั้ค แล้วจะต้องวิ่งไล่โค้ดที่ยาวววววเป็นหางว่าว
ยิ่งโค้ดยาว ยิ่งอ่านยาก
ยิ่งโค้ดเยอะ ยิ่งเข้าใจยาก
ทั้งนี้โค้ดสั้น ≠ โค้ดเข้าใจง่าย
โค้ดสั้น ที่ยาก ก็มี แต่โค้ดยาก ที่มารวมกันเยอะๆ ยิ่งยากกว่า
จะดีกว่าไหม ถ้าเราตัดแบ่งโค้ดยาวๆ ให้มันสั้นลง จนมันเล็กพอที่จะอ่านและทำความเข้าใจได้ง่าย
ไม่ว่าจะเป็นโปรเจ็คทำคนเดียวหรือโปรเจ็คที่ทำกับทีม ยิ่งโค้ดเข้าใจง่าย ก็ยิ่งทำงานเสร็จได้ไว
ถ้าเราซอยโค้ดยิบย่อยจนเกินไป พยายามแยกทุกอย่างออกจากกัน อาจจะทำให้โค้ดเข้าใจยาก ทำงานยากขึ้นไปอีก
แล้วเมื่อไหร่ถึงนับว่า เราหั่นโค้ดยิบย่อยจนเกินไป?
เอาง่ายๆ … ก็ถ้าต้องแก้โค้ดจากไฟล์นึง แล้วต้องไปเปิดอีกไฟล์นึง แล้วไปเปิดเพิ่มอีกไฟล์นึง แล้ววนกลับมาไฟล์นึง เพื่อที่จะเข้าใจโค้ดแค่ก้อนเดียว
แบบเนี้ย … หั่นโค้ดเยอะเกินไป เยอะจนจนมานั่งเสียเวลาทำความเข้าใจโค้ดทีหลัง มากกว่าตอนที่โค้ดอยู่รวมกันที่เดียวซะอีก
การหั่น A กับ B ออกจากกัน ควรเกิดขึ้นเมื่อ การเปลี่ยนโค้ดใดๆใน A จะไม่เอฟเฟ็กต์ B
ในทางกลับกัน การเปลี่ยนโค้ดใดๆใน B จะไม่เอฟเฟ็กต์ A
ถ้าโค้ดของ A กับ B ยังมีความเกี่ยวเนื่องซึ่งกันและกันอยู่ (หรือเรียกว่า coupling)
การแยก A กับ B ออกจากกัน มีแต่เพิ่มความเสี่ยงในการเกิดบั้คได้ง่ายขึ้น
ก่อนจะหั่นโค้ด ลองชั่งน้ำหนักดีๆ ถามตัวเองว่า..
- ถ้าแยกโค้ดออกไปแล้ว จะช่วยประหยัดเวลาในการทำความเข้าใจโค้ดรึเปล่า
- ถ้าแยกโค้ดออกไปแล้ว คนที่เข้ามาเพิ่มโค้ด ลบโค้ด หรือแก้ไขโค้ด จะยังแฮปปี้อยู่รึเปล่า (หรือต้องมานั่งระแวงว่าเพิ่ม ลด แก้จะทำให้โค้ดที่ไหนสักที่พัง)
- ถ้าแยกโค้ดออกไปแล้ว จะช่วยทำให้หาบั้คง่ายรึเปล่า จะใช้เวลาในการแก้บั้คน้อยลงไหม (เพราะรู้เลยว่าโค้ดอยู่ไฟล์ไหน ตรงไหน รับค่าจากที่อื่นมาไหม รับค่าอะไร แล้วเอาไปใช้ที่ไหน)
ถ้าคำตอบเป็น positive ทั้ง 3 ข้อ ก็มีเปอร์เซ็นสูงที่การตัดสินใจหั่นโค้ดครั้งนี้ อาจจะเป็นเรื่องที่ถูกต้อง
เพราะถึงจะตอบเป็น positive ทั้ง 3 ข้อ พอถึงจุดนึง โค้ดที่เคยหั่นออกมา อาจจะถูกแก้จนกลายเป็นโค้ดที่ยุ่งยากในภายหลังได้เหมือนกัน ถึงเวลานั้นก็ต้องมา refactor และหั่นโค้ดกันใหม่
แต่ถ้าคำตอบเป็น negative แม้แต่ข้อเดียว ลองคิดดูอีกที
เพราะบางทีแค่การหั่นโค้ดอาจจะไม่เพียงพอและไม่ได้ช่วยลดเวลาในการทำความเข้าใจโค้ดหรือช่วยให้ดูแลโค้ดได้ง่ายขึ้นสักเท่าไหร่
การหั่นโค้ดและแยกโค้ดออกมาให้สั้น อาจจะดูเหมือนช่วยให้ maintain โค้ดได้ง่ายขึ้นจริง แต่ …
ถ้าโค้ดมันมีกลิ่นตุๆอยู่แล้ว การหั่นโค้ดจะยิ่งเหมือนเปลี่ยนจากขยะชิ้นๆให้กลายเป็นขยะมูลฝอย กลิ่นตุๆก็ยังคงอยู่ ลอยคลุ้งไปมา แถมจัดการยากกว่าเดิม
แต่ถ้าโค้ดกลิ่นหอมเหมือนสเต็กชั้นดี การแบ่งชิ้นในขนาดที่พอเหมาะ ก็เหมือนกับการเสิร์ฟสเต็กลงบนจานพร้อมเสิร์ฟในร้านอาหารชั้นเยี่ยม
ดังนั้น ก่อนจะหั่นโค้ดออกไป อย่าลืมดูว่า โค้ดที่มีอยู่คือสเต็กชั้นดีรึยัง
ถ้ายัง การหั่นครั้งนี้ จะต้องทำไปพร้อมๆกับการปรุงโค้ดใหม่ ให้หอมอร่อยกว่าโค้ดจานเก่า
ถ้าเรารู้อยู่แก่ใจ ว่าโค้ดที่เคยเขียนไว้ มีกลิ่นตุๆ
แต่ยังฝืนหั่น ไม่ปรุงโค้ดใหม่ ยิ่งหั่น จะยิ่งทำให้โค้ดที่กลิ่นแย่อยู่แล้ว มีกลิ่นที่แย่ขึ้นไปอีก
“มีสติทุกครั้งเวลาเขียนโค้ด” และ “มีสติทุกครั้งเวลาหั่นโค้ด”
ท่อง 3 คาถานี้ไว้ในใจเสมอเมื่อจับคีย์บอร์ด
ที่เหลือคือ ฝึก ฝึก ฝึก
แล้วเราจะสามารถเขียนโค้ดและหั่นโค้ดได้หอมและอร่อยขึ้นอย่างแน่นอน
Nobody is perfect, but my code will always be my best.
May the </code> be with you
หนึ่งตัวอย่างในการแบ่งโค้ดแบบ Separation of Concerns จิ้มจ้า