ทำงานกับ Legacy Code ให้ Effective กันเถอะ !

Tae Keerati Jearjindarat
3 min readMay 30, 2021

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

สำหรับเด็กจบใหม่นี่ยิ่งยากเข้าไปใหญ่เมื่อเจอโค้ดแปลกๆ หรือ structure ที่ซับซ้อน เช่น บางคนอาจจะไม่เคยศึกษาเรื่อง Design Pattern แต่ต้องมาเจอโค้ดไม่รู้ว่ามันคือ Pattern อะไร ซึ่งมันอาจจะมีบาง Pattern ที่ถ้าไม่เคยเจอมาก่อน อาจจะหาโค้ดไม่เจอกันเลยทีเดียวว่าแก้จุดนี้จะกระทบอะไรบ้าง ทำให้ไม่สามารถแก้ไขได้ครบและครอบคลุม จนกว่าจะ Run Test และยิ่งแย่เข้าไปใหญ่ หากใช้ Pattern ที่ซับซ้อน และไม่มีการ Test เลยทั้ง Unit Test หรือ End to End จะยิ่งทำงานลำบากมาก เพราะสิ่งที่แก้ไปกว่าจะรู้ว่าบัคก็อาจจะหลุดเข้า Production ไปก็เป็นได้

ทำให้วันนี้อยากมาแชร์มุมมองหนึ่งที่เรามองว่ามันเป็นสิ่งที่ดีในฐานะของโปรแกรมเมอร์ ที่ต้องเจอกับ Legacy Code เป็นประจำกัน

Legacy Code คือ ?

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

ทำงานอย่าง Effective !

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

1. Legacy Code = Challenge

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

สิ่งที่เรา Challenge ได้คือเราต้องทำความเข้าใจให้ได้ การที่จะทำให้รู้ได้คือเราจะต้องไล่โดยมีสมมติฐานเบื้องต้น หรือก็คือการคาดเดาอย่างมีเหตุและผลนั่นเอง สิ่งที่พอจะทำได้ก็คือลองเดาว่ามันคือหน้า UI ไหน Flow ทั้งหมดเป็นยังไง เชื่อมกับระบบไหน หรือ Service ไหน ใช้ API เส้นไหน หรือ ใช้ Protocol อะไรบ้าง หลังจากนั้นเราค่อย ๆ ไล่ว่าโค้ดเป็นยังไง เขียน Logic อะไรไว้ ที่สำคัญคือ ต้องใจเย็น ๆ และคิดด้วยเหตุและผลดี ๆ เมื่อเราเข้าใจ Flow และ โค้ดแล้ว เราก็ค่อยคิดว่าเราจะทำยังไงให้มันดีขึ้น สุดท้ายเราก็จะสามารถเอาชนะและได้ความรู้ใหม่นั่นเอง !

2. เขียน Test !

หลังจากเราผ่านจุดที่ต้องพยายามเอาชนะด้วยการทำความเข้าใจได้แล้ว สิ่งแรกที่จะพอทำให้มันดีขึ้นได้มากที่สุดก็คือการเขียน Test ครับ เริ่มด้วยการคิด Testcase ก่อน โดยอาจจะคุยกับ Tester ว่ามันมีเคสอะไรบ้าง แล้วค่อยๆ มานั่งไล่เขียน Unit Tests ต่อ ซึ่งจริงๆแล้ว เราจะเขียนเทสแบบไหนก็พิจารณาตามความเหมาะสมโดยอิงจาก Test Pyramid ครับ ที่พูดถึง Unit Tests เพราะมันง่ายที่สุดและทำได้เร็วที่สุดนั่นเอง ถ้ามีชุด Tests เก่าอยู่แล้วก็ยิ่งดี เราสามารถเรียนรู้จาก Tests เก่าได้เลย และเราก็เพิ่มเคสใหม่ที่เราต้องการพัฒนาเข้าไปอีก ซึ่งเราสามารถทำ Step ของ TDD ได้เลย แต่ถ้าไม่มี Tests มาก่อนเลยอาจจะยากหน่อยโดยเราต้องดูว่า Logic มันมีกรณีไหนบ้างแล้วค่อย ๆ เขียนออกมาแบบ White box ซึ่งอาจจะใช้ Tools ให้เขียนง่ายขึ้นได้ด้วย Test Coverage นั่นเอง จะทำให้เรารู้ว่าเราเขียนเทสครอบคลุมบรรทัดไหนบ้าง แต่ก็อาจจะไม่ครบกรณีพิเศษต้องตรวจสอบดี ๆ ด้วยครับ

3. หา Documents อ่าน

โดย Documents ในที่นี้หมายถึงเอกสารของการออกแบบระบบที่เรากำลังจะเข้าไปแก้ ซึ่งกรณีนี้ต้องอาศัย Culture เดิมขององค์กรด้วย เพราะบริษัทอาจจะมีหรือไม่ก็ได้ หรือมีแค่บาง Feature ผมขอแนะนำว่า ถ้าไม่มีก็ทำให้มี เพราะจะเป็นประโยชน์กับตัวเราเองเวลาเราทำไป เราจะมีเอกสารที่เขียนไว้คอยตรวจสอบได้ รวมถึงสามารถนำไปแชร์กับคนอื่นได้ด้วย ตอนเริ่มต้นอาจจะยาก แต่เราสามารถใช้ template ของที่อื่นมาใช้ เป็นต้นแบบและปรับให้เหมาะกับระบบเราได้ ซึ่งจะเป็นประโยชน์คนที่จะมาทำต่อจากเราด้วย

โดย Documents ส่วนใหญ่มักจะมีความคล้ายกันอยู่ก็คือ มีรายละเอียดเบื้องต้นว่าระบบเกี่ยวกับอะไร ทำเพื่ออะไร และ Flow ของระบบ อาจจะมีพวก API Specs และ Test Specs ติดมาด้วย หรือ รวมไปถึง Database Schema ต่าง ๆ ซึ่งสิ่งเหล่านี้จะช่วยให้เราเข้าใจได้ง่ายขึ้นว่าระบบนี้ทำไปทำไม กระทบระบบไหน หรือต้องแก้ Service ไหนเพิ่มเพื่อที่เราจะได้พัฒนา Feature ต่อได้ง่ายที่สุดเท่าที่เราจะทำได้

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

4. ลอง Refactoring ของเก่า

สิ่งที่น่าสนุกถัดไปคือการ Refactoring ครับ เราสามารถทำได้หลังจากที่เข้าใจระบบอย่างดีแล้ว และระบบนั้นต้องมี Tests เพราะการ Refactoring คือการแก้ไขโค้ดเดิมให้มี structure ที่ดีขึ้นหรือแก้ให้สามารถเข้าใจได้ง่ายมากขึ้น โดยการแก้เหล่านั้นต้องไม่กระทบการทำงานของ Logic ที่เขียนไว้ ดังนั้นหากไม่มี Tests เราไม่ควร Refactoring ครับ

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

5. ลองคุยกับคนอื่น หรือ คนที่เคยทำ

เวลาเราทำระบบ และต้องไป Investigate อยากให้เราลองสำรวจดูก่อนว่าคนที่ทำโค้ดบรรทัดนั้นไว้เป็นใคร ผมไม่ได้ให้ทำเพื่อไปด่านะครับ แต่เค้าอาจจะเป็นคนที่ช่วยเราได้ ซึ่งเราสามารถดูได้ถ้าใช้ Git เพราะเมื่อเรา commit โค้ดแต่ละบรรทัดจะมีชื่อคนๆนั้น ติดมาเสมอ เราสามารถใช้ Tools ช่วยดูได้เช่น Git Blame จะทำให้เราก็จะเห็นชื่อคน ๆ นั้น และถ้าโชคดีเค้าอาจจะยังไม่ลาออกจากบริษัทไปนั่นเอง

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

6. Research / หาความรู้เพิ่ม

เป็นสิ่งที่ควรจะทำหลังจากที่เราไล่โค้ดแล้ว คิดไม่ออกว่าควรจะแก้ไขยังไง เวลาเราเป็น Junior ก็มีได้หลายปัญหา เช่น อาจจะยังไม่เข้าใจโค้ดดีพอ ถ้ายังไม่เข้าใจก็ต้องไปไล่เพิ่ม เพราะ source ที่ดีที่สุดคือ source code ที่มี logic ทุกอย่าง หรือถ้าปัญหาคือรู้หมดแล้ว แต่ยังไม่มีไอเดียว่าควรจะแก้ยังไง

สิ่งที่เราทำได้คือหาความรู้เพิ่มเติม หรือ อาจจะไปหา Use case ของคนอื่นที่เขียนบล็อคไว้ หรือหาจากหนังสือของท่าน Martin Fowler ในหลายๆ เล่ม (หรือจะอ่านบล็อคที่ผมเขียนก็ได้ครับ 😅) ซึ่งการอ่านจะช่วยให้เรามีไอเดียเพื่อปรับแก้ไขมากขึ้น มีความรู้ที่กว้างขึ้นจะทำให้เราหยิบความรู้ที่เป็นเครื่องมือมาใช้ได้หลากหลายวิธีมากขึ้นนั่นเอง

สรุป

ถ้าเรามอง Legacy Code เป็นสิ่งที่ดี เรายอมรับและทำให้เป็นเรื่องที่ Challenge กับตัวเราเอง เราจะทำงานกับโค้ดเก่า ๆ ได้มีประสิทธิภาพดีขึ้น อาจจะเริ่มจากให้คำถามว่า เราได้อะไรจากโค้ดเก่าบ้าง? และหลังจากที่เราเปิดใจ พร้อมกับยอมรับว่า โค้ดเก่าก็ไม่ได้แย่เสมอไป หลังจากนั้นมันก็ถึงเวลาที่ต้อง จัดการกับโค้ดเก่าสักที ทำให้ดีกว่าเดิมและพัฒนาโค้ดไปพร้อม ๆ กับตัวเรา และต้องอย่าลืมว่า เราต้องเขียนโค้ดให้มีคุณภาพที่ดี หรือ Make it Great ! เพราะว่า เราจะเขียนโค้ดที่ต่อยอดยากๆไปทำไม จริงไหมครับ ?

ข้อมูลเพิ่มเติม

ขอบคุณทาง depa และ คณะเทคโนโลยีสารสนเทศ มจธ.
ที่มอบทุนการศึกษาเพชรพระจอมเกล้าเพื่อพัฒนาเทคโนโลยีและนวัตกรรมดิจิทัล และทำให้ได้ความรู้เพิ่มสำหรับใช้ทำงานจริงครับ

หวังว่าเรื่องนี้จะเป็นประโยชน์กับหลาย ๆ คนที่สับสน ขอบคุณที่อ่านจนจบครับ 🙏

--

--

Tae Keerati Jearjindarat

Hi, I'm Tae, Associate Engineering Manager at LINEMAN Wongnai. Thanks for following <3