เราได้อะไรจากโค้ดเก่า ๆ บ้าง ?

Tae Keerati Jearjindarat
2 min readAug 1, 2020

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

Technical Debt

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

มีปัญหาเพราะอะไรล่ะ ?

แน่นอนว่าเวลาเราเจอสิ่งเหล่านี้ เราจะต้องแลก “เวลา” ไปเพื่อจัดการ ซึ่งจากภาพอธิบายได้ดีอยู่ เพราะเวลาก็คือ Cost แบบหนึ่งที่เราต้องจ่ายเมื่อพัฒนาซอฟต์แวร์ที่ซับซ้อน และยิ่งเราจบใหม่ เราไม่สามารถประเมินเวลาได้เลยว่าเราต้องใช้เวลาเท่าไรในการทำงานที่เรารับมา เพราะเราไม่มี Domain Knowledge ในงานของเราเลย มันทำให้ยิ่งสับสนเข้าไปใหญ่ ซึ่งจะเกิดความคิดประมาณว่า “เขียนอะไรไว้นะ” “อันนี้เอาไว้ทำอะไรนะ” หรือ “ทำแบบนี้ทำไม ทำไมไม่ทำแบบอื่น”

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

ก่อนจะนอกเรื่องไปมากกว่านี้ สิ่งที่อยากจะบอกคือ Technical Debt จะส่งผลต่อความเร็วในการพัฒนาทั้งหมด ซึ่ง Technical Debt เป็นสิ่งที่จะเราจะต้องเสียเวลาไปจัดการ เมื่อต้องทำเพิ่มหรือปรับแก้ Software ให้ดีกว่าเดิม ยิ่งมีปัญหาเยอะ จะยิ่งเพิ่ม Features หรือแก้งานเก่าช้า ซึ่งจะใช้เวลาในการแก้ปัญหากับ Design ที่มีอยู่ อยากให้ใส่ใจและให้ความสำคัญให้ดี เพราะการออกแบบเป็นเรื่องสำคัญเป็นฐานของการพัฒนาทั้งหมด และผมขอยืมคำจากที่ปรึกษามาเล่าให้ฟังครับ “การพัฒนาซอฟต์แวร์เป็นเหมือนการสร้างตึก ยิ่งเราสร้างฐานให้แข็งแรงเท่าใด เราก็จะพัฒนาตึกได้สูงมากขึ้นเท่านั้น”

ผมจะจำแนกสิ่งที่จะทำให้เกิด Technical Debt ให้เข้าใจง่าย ๆ ให้อ่านครับ ซึ่งที่มาคือ เกิดจากการตัดสินใจของนักพัฒนาที่ขึ้นอยู่กับ ความรอบคอบ ความเสี่ยง เจตนา และสิ่งที่ไม่คาดคิด ซึ่งอาจจะเกิดโดยที่ไม่รู้ตัว มีทั้งหมด 4 แบบ ดังนี้

  1. (สีเหลือง) กรณีที่เราวิเคราะห์ เราพิจารณาเบื้องต้นแล้ว รู้ว่ามีข้อเสียอะไรแต่ยอมรับความเสี่ยง อาจเป็นเพราะว่าเราไม่มีเวลาที่จะทำทั้งหมด แต่รู้ในเบื้องต้นว่าเมื่อพัฒนาแล้วเป็นยังไง อาจจะเกิดปัญหาอะไร แต่เราไม่รู้รายละเอียดมากพอ แต่ด้วยเวลาที่มีจำกัด เราจะยอมรับความเสี่ยงที่อาจเกิดขึ้นในอนาคต ส่งผลให้งานเราอาจจะไม่ทำตาม practices ที่ดี แต่ก็ลงมือทำมันให้เกิดขึ้นจริง และใช้งานได้ ซึ่งจะเกิดปัญหาในภายหลังได้ ในด้านการ Maintain ถ้าเราไม่มี Document หรือเอกสารอะไรก็ได้ที่บอกที่มาที่ไป รวมถึงข้อจำกัดของ Component นั้น ๆ ฉะนั้นเราควรใส่ใจที่จะบันทึกความรู้และสิ่งที่เกิดขึ้นเพื่อให้ส่งต่องานได้ง่ายมากขึ้นครับ
  2. (สีเขียว) กรณีที่เราวิเคราะห์ พิจารณา ใช้ความรอบคอบสูง คือเราพยายามออกแบบให้ดี คิดให้ครอบคลุมกับปัจจุบัน พยายามคิดข้อดีข้อเสียให้ครบ และแก้ปัญหาหลาย ๆ อย่าง ซึ่งบางปัญหาอาจจะไม่ต้องแก้ก็ได้ ส่งผลให้งานจะทำไปเรื่อย ๆ จนใกล้เดดไลน์ เสี่ยงที่จะไม่เสร็จ หรือใช้จริงไม่ได้ และทำมากเกินไปจนเกินความจำเป็น กรณีนี้ควรที่จะแบ่งงาน ให้ดี ทำให้สิ่งที่สามารถทำจริงได้เป็น Minimun Value เพื่อนำไป ทดลอง และปรับปรุงแก้ไขให้ดีในอนาคต ซึ่งอาจจะดูคล้าย ๆ กับกรณีแรก แต่จะต่างที่ เราจะต้องปูพื้นฐานให้พร้อมกับอนาคตโดยใช้หลักของการ Maintain เพื่อให้ปรับเปลี่ยน ต่อเติมได้ง่ายครับ
  3. (สีแดง) กรณีที่เราไม่ได้คิดมาก่อน และยอมรับความเสี่ยงว่าจะมีปัญหาในอนาคตแน่นอน เสมือนกับการทำ ๆ ไปก่อนทั้ง ๆ ที่ในใจก็รู้ว่าอาจจะต้องทำใหม่ ซึ่งอาจเกิดมาจากที่ความรู้เราน้อย ไม่รู้พื้นฐานที่ดีพอ เช่นคำถามว่า “การแบ่ง Layer คืออะไร” หรือ “OOP คืออะไร?” ทำได้เพียงหมั่นสั่งสมประสบการณ์เพิ่มเรื่องการออกแบบให้มากขึ้น หรือ หากเป็นงานที่สำคัญ เน้นความถูกต้อง และใช้ความเร็ว อาจต้องพึ่งบุคคลภายนอกที่มีประสบการณ์ทางด้าน Architect มาช่วยในการออกแบบ ซึ่งถ้าเราไม่มีความรู้ แต่ฝืนทำ อาจเป็นสิ่งที่แย่ที่สุดในที่กรณีเพราะอนาคตจะต้องมาเสีย Cost ในการพัฒนาใหม่ ทำให้เสียแรงเปล่าโดยใช่เหตุ ทำให้ซอฟต์แวร์ที่เราพัฒนาไม่เกิดการ Reuse มักจะเกิดในการทำงานด่วนงานเร่ง เช่น สั่งวันนี้ เอาสัปดาห์ถัดไป แต่ Requirement คือต้องทำ ERP อะไรทำนองนี้ครับ นอกจากเสี่ยงทำใหม่แล้วก็ยังเสี่ยงไม่เสร็จด้วย เพราะปริมาณงานสวนทางกับความเป็นจริง ดังนั้นเราควรพูดคุยสื่อสารและคิดให้ดีก่อนลงมือตัดสินใจครับ
  4. (สีฟ้า) กรณีที่ไม่ได้คิดมาก่อน แต่ใช้ความรอบคอบคิดมาเยอะแล้ว จะเกิดขึ้นก็ต่อเมื่อสิ่งที่เราทำไม่มีอะไรผิดเลย แต่จะมีปัญหาที่ Library หรือ 3rd Party มีการ Break Change ทำให้ของเก่าใช้งานไม่ได้ แต่หากมีการเปลี่ยนแปลงโดยที่ไม่เหลือของเก่าเลย สุดท้ายก็อาจจะต้องพัฒนาส่วนใช้งานร่วมกับ 3rd Party ใหม่ ซึ่งระบบเราควรนึกถึงกรณีนี้ไว้ด้วยเพื่อให้ออกแบบโปรแกรมรองรับการใช้ 3rd Party ได้อย่างราบรื่น หากมีการปรับเปลี่ยน ระบบเดิมที่ทำงานได้ ควรจะใช้งานได้ปกติ พร้อมกับปรับเปลี่ยนได้โดยง่ายผ่านการตั้งค่าบางอย่าง และเพิ่มโค้ดบางส่วน เพราะการที่เราใช้ 3rd Party นั้นมีความเสี่ยงที่จะเกิดการเปลี่ยนแปลง เนื่องจากไม่ใช่เราที่เป็นคน Maintain แต่เราเป็นคนใช้และเป็นคนที่ช่วยบอกปัญหากับผู้ดูแล 3rd Party ให้พัฒนาได้ดีขึ้น ซึ่งหากเป็น Open-source เราสามารถไป Contribute ได้ด้วยครับ

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

จากที่กล่าวมาทั้งหมดอยากให้เห็นว่า จริงๆ แล้ว Technical Debt ก็ไม่ได้แย่เสมอไป จริงๆ แล้วมันเป็นโอกาสสำคัญที่จะเพิ่มความรู้เราในหลาย ๆ ด้าน ทั้ง Domain Knowledge หรือ การแก้ปัญหา อีกทั้งได้ Challenge ตัวเองเนื่องจากมันเป็นการเปิดโอกาสให้เราได้ Refactoring ซึ่งเป็นการ Improve งานของเราให้ดีกว่าเดิมครับ

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

  • ขอบคุณข้อมูลความรู้จาก Course ใน Pluralsight
    ชื่อว่า Microsoft Azure Developer: Refactoring Code
    สามารถตามไปเรียนเพิ่มเติมกันได้ครับ
  • ขอขอบคุณอาจารย์ที่ให้คำปรึกษาจนเกิดเป็นบล็อคนี้ครับ
  • ขอบคุณทาง depa และ คณะเทคโนโลยีสารสนเทศ มจธ.
    ที่มอบทุนการศึกษาเพชรพระจอมเกล้าเพื่อพัฒนาเทคโนโลยีและนวัตกรรมดิจิทัล และทำให้ได้ความรู้เพิ่มสำหรับใช้ทำงานจริงครับ

เช่นเดิมหวังว่าบล็อคนี้จะเป็นประโยชน์และเปิด keywords ใหม่ ให้ผู้อ่านกันนะครับ

สุดท้าย ขอให้ผู้อ่านมีวันที่อ่อนโยนครับ และติดตามตอนต่อไป ขอบคุณครับ 🙏

--

--

Tae Keerati Jearjindarat

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