เมื่อวานนั่งดู Code การพัฒนา iOS ด้วยภาษา Swift
โจทย์เดียวกันจาก developer 4 คน
แต่โครงสร้างของ code ที่ออกมานั้นเหมือนกัน
นั่นคือเป็น MVC(Model View Controller) ในรูปแบบของ Apple
ซึ่งส่วนใหญ่จะนำไปสู่ MVC ที่ย่อมาจาก Massive ViewController มากกว่านะ !!
และนั่นคือความหายนะที่กำลังมาเยือนนักพัฒนาโดยทั้งรู้และไม่รู้ตัว
คำถามที่น่าสนใจคือ แล้ว MVC มันไม่ดีหรือไง ?
ตอบได้เลยว่าดีนะ ถ้าเข้าใจ และ ใช้งานได้อย่างถูกต้องคำถามต่อมา แล้วโครงสร้างแบบอื่นที่ดี ๆ ทำไมไม่ใช้กัน ?
ทั้ง MVP, MVVM และ VIPER เป็นต้น แต่ก่อนจะเลือกอะไรนั้น นักพัฒนาลองตอบคำถามเหล่านี้ก่อนสิ- เรื่องการการเรียกใช้งาน API ผ่านระบบ network ควรอยู่ตรงไหนดี Model หรือ Controller ?
- จะทำการส่ง Model ไปยัง View เพื่อแสดงผลอย่างไร ?
- ปัจจุบันเขียน code อย่างไร ?
- ทดสอบกันแบบไหน ?
คำถามต่อมา เราจะสนใจเรื่องโครงสร้างของระบบไปทำไม ?
ถ้านักพัฒนาไม่เลือกหรือกำหนดตั้งแต่แรก มันมักจะก่อให้เกิด class ขนาดใหญ่หรือ God class จำนวนมากมาย ยากต่อการค้นหาและแก้ไขอย่างมาก หรือแค่มานั่งไล่ code เพื่อทำความเข้าใจก็ยังยากเลย !! เรื่องของโครงสร้างมันก็สัมพันธ์กับความสามารถของทีมเช่นกันมาดูตัวอย่างจาก code ของ iOS app ที่พัฒนาด้วยภาษา Swift
จะมีลักษณะดังนี้- ทำการ extends มาจาก UIViewController
- ข้อมูลต่าง ๆ ที่จะทำการแสดงผลหรือดึงข้อมูลจากภายนอกก็อยู่ใน UIViewController นี่แหละ
- ส่วนของ UIViews ไม่ได้ทำอะไรเลย
- Model ก็เป็นเพียง class และ struct สำหรับกำหนดโครงสร้างของข้อมูลเท่านั้น
- UI testing อย่าคิด ส่วน Unit testing อย่าฝันว่าจะมี
แต่เมื่อนำมา implement จริง ๆ กลับได้แบบนี้ !!
นั่นคือ ViewController ผูกติดกลายเป็นตัวเดียวกันไปเลย ซึ่งเป็นโครงสร้างที่เอื้อต่อการสร้าง Massive ViewController อย่างมาก เนื่องจากทำการรวม View Life Cycle เข้ากับ Controller ทำให้พวก business logic ต่าง ๆ รวมอยู่ในนั้นด้วย ทำได้เพียงแยกส่วนของ data หรือ Model ออกมาเท่านั้น ทำให้ใน ViewController นั้นจะใช้งานพวก Delegate และ Datasource ของทุก ๆ อย่างเสมอ เช่น TableView และ SwipeView เป็นต้น ผลที่ตามมาคือ View คุยกับ Model โดยตรง หรือ ทำการส่ง Model ไปให้ View ซะงั้น !! นั่นคือ ข้อขัดแย้งอย่างรุนแรงต่อ MVC และเราพบเห็นได้บ่อยมาก ๆ ใน ViewController ของ iOS app และนักพัฒนาทุกคนก็มองว่า มันเป็นเรื่องปกติ ไม่ได้ผิดอะไร !! เมื่อเวลาผ่านไปนานขึ้น ขนาดของ ViewController ต่าง ๆ ก็ใหญ่โตขึ้นเรื่อย ๆ นี่แหละคือที่ไปที่มาของ Massive ViewController ยังไม่พอนะ เมื่อต้องเขียน Unit testing ด้วยแล้ว !! ปัญหามันหนักมาก ๆ เนื่องจาก ViewController มันเยอะไปหมด code ผูกติดกันอย่างแน่นหนา ทั้ง View ทั้ง Controller ทั้ง Business logic หวังว่าระบบที่พัฒนาหรือดูแลกันอยู่ ไม่น่าจะเป็นเช่นนี้นะครับดังนั้นสิ่งที่ควรทำก่อนเลยก็คือ
ทำความเข้าใจกับ code และลองเขียนออกมาหน่อยว่า ใน ViewController มีหน้าที่การทำงานอะไรบ้าง จากนั้นค่อย ๆ แยกส่วนการทำงานต่าง ๆ ออกมา โดยในแต่ละส่วนก็ช่วยเขียน Unit test ขึ้นมาคลุมหน่อยนะครับ ค่อย ๆ ถอด ค่อย ๆ แยก ค่อย ๆ ทดสอบ ค่อย ๆ integrate แล้ว code จะค่อย ๆ ดีขึ้นเองส่วน code ใหม่ ๆ ลองคิด วิเคราะห์ แยกแยะก่อนว่า
ในแต่ละ feature ต้องทำอะไร ต้องการอะไรบ้าง โดยแนะนำให้ทำดังนี้- แยกส่วนการทำงานของ Model, View ออกจากกันก่อน
- ส่วนของ Controller กับ View อาจจะยังติดกันนิดหน่อย
- แต่ละส่วนการทำงานต้องสามารถทดสอบได้ แต่ถ้าคุณแยกส่วนการทำงานไม่ดีจะทดสอบได้ยาก หรือ ทำได้เพียง Model เท่านั้น ซึ่งต้องระวังให้มาก ๆ
- Code แต่ละส่วนง่ายต่อการใช้งาน ง่ายต่อการดูแล แม้แต่นักพัฒนาที่มีประสบการณ์น้อยก็ตาม มิเช่นนั้นคุณจะเอาเทคนิคแปลก ๆ มาใช้จนคนในทีมงงไปเลย อย่าทำนะ !! มันจะเป็นการใช้งานที่มากเกินความจำเป็น
- ของดีแต่อาจจะยังไม่เหมาะสมกับทีมในเวลานี้ก็เป็นได้
ดังนั้นการจะเลือกวางโครงสร้างของระบบอย่างไรนั้น มันมีปัจจัยหลาย ๆ อย่าง แต่เหนือสิ่งอื่นใด สิ่งที่คุณเลือกมันทำให้คุณและทีมช้าลงหรือเร็วขึ้น