สวัสดีครับ สำหรับวันนี้เราได้มาถึง Part ที่ 2 กันแล้ว โดย Part นี้ เราจะเข้าสู่กระบวนการปรับปรุง Code ให้ดีขึ้นกันครับ ส่วนใครที่ยังไม่ได้อ่าน Part แรก สามารถอ่านได้ที่นี่เลยครับ เขียน Code ที่เหมือนกันแต่ไม่เหมือนกัน! ให้อ่านและ Maintenance ได้ง่ายด้วย Strategy Design Pattern [Part 1 เกริ่นนำ]
Strategy Design Pattern คืออะไร ก่อนอื่นคงต้องพูดถึงคำว่า Design Pattern กันสั้นๆก่อนครับ Design Pattern ก็คือ วิธีการออกแบบ และเขียน Code ที่มีรูปแบบเฉพาะ โดย Design Pattern แต่ละตัวก็จะเหมาะกับปัญหาที่แตกต่างกันออกไปครับ แล้วเจ้า Strategy นี้ เอาไว้แก้ปัญหาแบบไหนหล่ะ เรามาลองดูไปพร้อมกันเลยครับ
เริ่มแรกเราจะต้องแยก การทำงาน High Level กับ Implementation Detail ออกจากกันก่อน ลองดู Class OrdersService ที่เราเขียนขึ้นมากันครับ
ใน Function ship เราจะเห็นว่า Code มีขั้นตอนการทำงานภาพใหญ่ที่เหมือนกันก็คือ ส่งข้อมูล Order ไป booking การ ship ผ่าน API และได้ Tracking Number กลับมา ตรงนี้แหละครับก็คือ การทำงาน High Level
จริงๆ แอบต้องใช้การสังเกตุ, ความเข้าใจ Business และประสบการณ์ในการทำงานอยู่สูงเหมือนกันนะครับ สำหรับผม จะมี Trick ในการสังเกตุอยู่นิดหน่อยก็คือ จุดที่เป็น การทำงาน High Level มันจะสอดคล้องกับ Requirement ที่ได้มาจากฝั่ง Business (หรือ Product Owner) ครับ เพราะในมุม Business มักจะให้โจทย์ที่เป็น High Level อยู่แล้ว แต่ก็ไม่ได้การันตีนะครับ
ต่อไปคือส่วน Implementation Detail ก็คือ Code ที่ต้องเขียนขึ้นมาเฉพาะเจาะจงกับการทำงานนั้นๆ ซึ่งในที่นี้ก็คือ การเรียก API ของแต่ละขนส่ง และ Code ส่วนที่เราต้องปรับ Parameters เพื่อส่งไปยัง API นั้นๆครับ
หลังจากที่เราได้แยก การทำงาน High Level กับ Implementation Detail ออกจากกันได้แล้ว เราจะมาเริ่มกระบวนการ Refactor หรือ การปรับปรุง Code ให้ดีขึ้นกันครับ
ขั้นตอนแรกให้สร้าง Interface ขึ้นมา และนำขั้นตอนการทำงาน High Level มาเขียนเป็น Function ครับ
ตรงนี้เป็นการที่เราบอกว่า การ Shipping นั้น จะมีขั้นตอน booking ที่ส่งข้อมูล Order เข้าไป และได้ Tracking Number กลับมา
ต่อไปให้เราสร้าง Class ที่ Implement Interface ตัวนี้ขึ้นมา เพื่อเป็นการเขียน Implementation Detail ของแต่ละขนส่งกันครับ โดยเราจะเริ่มจากขนส่ง Slowly Express นะครับ
และทำการ Copy code ส่วนของขนส่ง Slowly Express ใน Class OrdersService มาใส่ใน Function นี้ แล้วปรับในส่วนของการ Return นิดหน่อยครับ
ถัดไปให้เราทำ Strategy ของขนส่งที่เหลือต่อตามขั้นตอนเดิมครับ
โอเคครับ ตอนนี้เราได้ทำการแยกการทำงานของขนส่งแต่ละเจ้ามาอยู่ใน Strategy ของตัวเองเรียบร้อยแล้ว
ต่อไปเราจะทำการ Refactor ในส่วนของ Class OrdersService เพื่อทำการเรียกใช้ Strategy เหล่านี้กันครับ โดยวิธีการคือ ให้เราสร้างตัวแปรเพื่อเก็บ Strategy ขึ้นมา และทำการ Instantiate Strategy ที่เราต้องการใช้ใน if-else ที่เป็นตัวแบ่งขนส่งแต่ละเจ้าครับ ถ้าอ่านแล้วงงๆ ลองมาดู Code กันครับ
เราจะเห็นได้ว่า Code นั้นอ่านง่าย และเป็นระเบียบขึ้นมากครับ โดย Code จะถูกแบ่งออกเป็น 2 ส่วนอย่างชัดเจน นั่นคือส่วนการเลือก Strategy ของแต่ละขนส่ง และอีกส่วนคือการ Run Strategy นั้นๆ ตรงนี้เรายัง Refactor ให้ Code อ่านง่ายขึ้นได้อีกหน่อย โดยการแยกส่วน if-else ไปเป็น Function ที่ Return Strategy ครับ
ทีนี้ไม่ว่าเราจะมีการเชื่อมต่อ API กับขนส่งเจ้าใหม่ๆเพิ่มมากขึ้นอีกเท่าไหร่ก็แทบจะไม่กระทบกับความซับซ้อนของ Code ชุดนี้เลยครับ เมื่อทำการ Run ทดสอบดู ก็จะได้ผลลัพธ์ตามเดิมครับ แปลว่า Code เรายังทำงานถูกต้องเหมือนเดิมทุกประการ
สุดท้ายเมื่อเราต้องการที่จะเพิ่มการเชื่อมต่อ API กับขนส่งเจ้าใหม่ๆ ก็เพียงแค่สร้าง Class Strategy อันใหม่ขึ้นมา เขียน Implementation Detail เข้าไป และเพิ่ม if-else ส่วนการเลือก Strategy สำหรับขนส่งนั้นๆ ที่ Function getShippingStrategy ก็เป็นอันเสร็จสิ้น จะเห็นได้ว่า Code ที่เฉพาะเจาะจงของแต่ละขนส่งนั้นจะอยู่ภายใต้ Strategy ของตัวเองเท่านั้น ทำให้ Code แก้ไข และ Maintenance ได้ง่ายครับ
และนี่ก็เป็นตัวอย่างการนำ Strategy Design Pattern มาใช้ครับ เพียงเท่านี้เราก็จะได้ Code ที่อ่าน และ Maintenance ได้ง่ายกันแล้ว ผมหวังว่าเพื่อนๆจะได้รับประโยชน์ และสามารถนำไปประยุกต์ใช้กับงานของเพื่อนๆ กันได้นะครับ วันนี้ขอลาไปก่อนครับ ขอบคุณครับ
0 Comment