เมื่อระบบงานมีจำนวน feature มากขึ้น
Developer ก็ยิ่งเขียน code มากขึ้นเท่านั้น
ส่งผลให้ code ในระบบมีความซับซ้อนขึ้นอย่างต่อเนื่อง
ดังนั้น เราควรหยุดคิด และ พิจารณา code กันหน่อยไหม
เนื่องจากยิ่งนับวันค่าใช้จ่ายสำหรับการดูแลจัดการ code ยิ่งสูงขึ้น
ทั้งจาก code ที่มันแย่ ๆ
ทั้งจาก code ที่มันดูสวยหรู หรือ เกินจริง
กรณีที่เราพบเห็นได้ทั่วไปก็คือ
การนำ design pattern มาใช้กันตั้งแต่เริ่มต้น
บ่อยครั้งมันคือ
การที่ออกแบบเกินกว่าความต้องการจริงหรือว่าการเผื่อนั่นเอง
ดังนั้น ย้อนกลับมาดูก่อนไหมว่า
ความเจ็บปวด และ ปัญหาที่แท้จริงมันคืออะไรกันแน่
จากนั้นจึงหาวิธีการแก้ไข
เพื่อให้ความเจ็บปวด และ ปัญหามันลดน้อยลงไป
คำถาม
แล้วเราจะกลับมาดู code และ แก้ไขเมื่อไรดีล่ะ ?
เป็นคำถามที่ตอบได้ยากมาก
แต่ว่ามีคำแนะนำดังนี้
อย่าละเลยการ refactor code ด้วยการผลัดวันประกันพรุ่ง
Developer มักจะเขียน code ให้มันทำงานได้ไปก่อน Developer มักจะบอกว่า code มันดีอยู่แล้ว อย่าไปยุ่งกับมันเลย Developer มักจะบอกว่าเดี๋ยวจะกลับมาแก้ไข Developer มักจะบอกว่า ... สุดท้าย code เหล่านั้นจะเป็นอย่างไร ? น่าคิดนะมาดูตัวอย่างจากหนังสือ Refactoring กันหน่อย
ต้องการสร้างระบบคำนวณเงินโบนัสของพนักงานแต่ละแผนก ซึ่งบริษัทนี้มีเพียง 2 แผนก คือ IT กับ Sales เท่านั้น โดยแต่ละแผนกก็มีการคำนวณที่แตกต่างกันไปตามจำนวนปีของการทำงาน ดังนั้นเมื่อเข้าใจความต้องการแล้ว Developer ก็จะลงมือเขียน code ทันที ดังนี้ [gist id="b84d756ac75738677dac" file="BonusCalculator.java"] แน่นอนว่า code ชุดนี้มันสามารถทำงานได้อย่างถูกต้องตามความต้องการ เพียงแค่โยน employee เข้ามาเท่านั้นเอง ดังนั้นงานเราเสร็จแล้ว !!แต่เดี๋ยวก่อนนะ !!
บางคนอาจจะบอกว่า ถ้ามีแผนกอื่นเพิ่มเข้ามา code ชุดนี้มันน่าจะเพิ่มยากนะ ดังนั้นลองปรับ code ให้มันอ่านง่าย ๆ สวย ๆ หน่อยไหม ? ด้วยการเปลี่ยนจาก if-else ไปเป็น switch-case ซึ่งเป็นการ refactoring แบบเล็ก ๆ เพื่อให้ developer คนอื่น ๆ อ่านง่าย เข้าใจง่าย เขียน code ได้ดังนี้ [gist id="b84d756ac75738677dac" file="BonusCalculator2.java"]แต่เดี๋ยวก่อนนะ !! ต่อมาบริษัทมีแผนกเพิ่มเข้ามาเป็น 10 แผนก จะทำอย่างไรดี ?
คำถาม Developer จะยังคงใช้ switch-case ต่อไปอีกไหม ? คำตอบ สำหรับ developer ส่วนใหญ่ก็จะบอกว่าใช่แล้ว ใช้ต่อไป เนื่องจาก code ก่อนหน้ามันเป็นแบบนี้ เนื่องจาก code มันเป็น standard ของเรา อย่าไปแก้ไข เนื่องจาก code มันยังทำงานได้ดีอยู่ ดังนั้น code ที่ได้ออกมาจึงเป็นดังนี้ [gist id="b84d756ac75738677dac" file="BonusCalculator3.java"] คำถาม Code ชุดนี้คุณคิดว่ามันดีแล้วหรือ ? คำตอบ ใช่แล้ว code ชุดนี้มันดี และ ทำงานได้อย่างถูกต้องด้วย แต่ Develoepr ลองมาดูกันหน่อยไหมว่า code ชุดนี้มันมีความซับซ้อนมากน้อยเพียงใด ? ตอบได้เลยว่า มาก แล้วยังจะทำกันแบบนี้อีกหรือไง ? ดังนั้น มันน่าจะได้เวลาของการ refactor code ก่อนที่จะเพิ่มการคำนวณ bonus ของแผนกอื่น ๆ ถ้าปล่อยไว้มันจะกลายเป็น Legacy code ที่ใคร ๆ ก็ไม่อยากแตะต้อง !! มันน่ากลัวมาก ๆ เลยนะ มันจะนำมาสู่ปัญหา มันจะนำมาสู่ความปวดหัว มันจะนำไปสู่หายนะ ในการดูแลรักษาต่อไป กลับมาที่ code กันหน่อย เราจะทำการ refactoring อย่างไรดีล่ะ ? มาถึงตรงนี้เราพบแล้วว่า code มันเกิดรูปแบบการทำงานซ้ำ ๆ แตกต่างเพียงแค่ logic ของการคำนวณโบนัสเท่านั้น นั่นคือ ความต้องการของเรา ตรงนี้แหละ เราสามารถนำเอาความรู้เกี่ยวกับ design pattern มาประยุกต์ใช้ได้ เพื่อนำมาแก้ไขปัญหาตามที่เราต้องการ มันน่าดูเข้าท่าเข้าทางกว่าเยอะนะ ซึ่งผมแนะนำให้อ่านหนังสือ Refactoring to Patterns เพื่อทำให้เข้าใจในการนำ design pattern มาประยุกต์เพื่อใช้งาน โดยตัวอย่างนี้เราสามารถนำเอา Design pattern มาใช้ได้ แต่ว่าทำอย่างไรล่ะ ? เช่น Strategy pattern, Template Method pattern เป็นต้น ตัวอย่างของ Strategy pattern เราจะทำการแยกส่วนการคำนวณโบนัสของแต่ละแผนกออกจากกัน รูปแบบการทำงานจะเหมือนกัน มาดู code ดีกว่า [gist id="b84d756ac75738677dac" file="CalculationStrategy.java"] จากนี้ต่อไป ก็ทำการสร้างการคำนวณของแต่ละแผนกต่อไป จะแยกออกจากกันอย่างชัดเจน ทำให้ง่าย และ สะดวกต่อการจัดการทั้ง การเปลี่ยนแปลงสูตรการคำนวณ การเพิ่ม และ ลบ แผนก รวมถึงอ่าน และ ทำความเข้าใจได้ง่ายกว่าเดิม และแน่นอนว่า ความซับซ้อนของระบบน้อยลงไป แต่ข้อเสียก็คือ จำนวนไฟล์ และ class เยอะขึ้น ซึ่ง developer หลาย ๆ คนกลัวจงกลัว code ที่หนึ่งไฟล์มี code หลายร้อย หลายพันบรรทัด !!
ข้อควรจำสำหรับการนำ design pattern มาใช้คือ
อย่าบังคับว่า จะต้องใช้ pattern นั้น pattern นี้เพียงอย่างเดียว นั่นคือ อย่าผูกมัดตัวเองด้วย design pattern มันคือการฆ่าตัวตายชัด ๆ แต่ให้มองไปที่ความต้องการ และ ปัญหาของระบบเป็นสำคัญ เนื่องจากการทำงานแต่ละส่วนมันแตกต่างกัน ดังนั้นอาจจะใช้แนวทางการแก้ไขที่ต่างกัน รวมทั้งแต่ละ pattern มันมีทั้งข้อดีและข้อเสีย ซึ่งคนนำมาใช้งานต้องเข้าใจอย่างดีด้วยถ้าคุณจะหา Best Practice สำหรับปัญหานั้นปัญหานี้ บอกได้เลยว่า มันไม่มีหรอกนะครับ มีแต่เหมาะสม และ ทำให้ code ดีขึ้นเท่านั้นเอง และที่สำคัญคือ คนในทีมเข้าใจไหม ?