swift-callback-hell
วันนี้ทำการ review code ทั้งฝั่ง Android และ iOS(Swift)
พบว่า code มีสิ่งที่คล้ายกันมาก ๆ คือ
มีการเรียกใช้ REST API ผ่าน network library
ซึ่งทำงานแบบ Asynchronous

สิ่งที่เกิดขึ้นคือ
มี feature ที่ต้องเรียกใช้งาน REST API หลาย ๆ ตัวต่อเนื่องกัน
ทำให้เกิด code ในรูปแบบของ Callback ซ้อน Callback
หรือ Callback hell นั่นเอง
หรือดีขึ้นมาหน่อยคือ flow การทำงานของ code
กระโดดไปยัง method อื่น ๆ ต่อไปเป็นทอด ๆ หรือ Chain

ผลที่ตามมาก็คือ

  • Developer เองก็งงกับ flow การทำงาน
  • เมื่อต้องทำการเพิ่ม หรือ แก้ไข จะยากมาก ๆ ดังนั้นทำใหม่ดีกว่า !!
  • เรื่องทดสอบไม่ต้องพูดถึง ยากเอาเรื่อง

มาดูรูปแบบของปัญหากันว่าเป็นอย่างไร ?

รูปแบบที่ 1 เป็น Callback hell แบบสนุกสนานมาก ๆ

รูปแบบที่ 2 ดีขึ้นมาหน่อย เป็นการเรียก method จาก Callback ไปเรื่อย ๆ

ทั้ง ๆ ที่ความต้องการเป็นดังนี้

มาดูต้นเหตุของปัญหาสิ

เมื่อไปดู code ของ iOS ที่พัฒนาด้วยภาษา Swift 2.3
พบว่าในการเรียกข้อมูลผ่าน REST API นั้น
ใช้ Networking Library ซึ่งทำงานแบบ Asynchronous
ทั้ง NSURLSession และ Alamorfire

การแก้ไขปัญหามีหลายแนวทางทั้ง
เปลี่ยนให้เป็น Synchronous สิ !!
ใช้ library เพิ่มสิ เช่น Bolt, Promise และ Rx เป็นต้น
โดยสิ่งที่ผมเลือกคือ เปลี่ยนการทำงานให้เป็น Synchronous เลยสิ
และนำ Grand Central Dispatch (GCD) มาใช้งาน

วิธีการก็ไม่ยากและไม่ง่าย นั่นคือ

สร้าง method ใหม่ใน NSURLSession ผ่าน extension
โดย method ใหม่นี้จะทำงานแบบ Synchronous
ดังนี้

คำอธิบาย
จะทำการรอไปจนกว่าจะทำงานเสร็จสิ้นนั่นเอง
ซึ่งสามารถตอบโจทย์ที่เราต้องการ

จากนั้นในแต่ละ process การทำงานที่ไปดึงข้อมูลผ่าน REST API
ใช้งานผ่าน method ใหม่ดังนี้

เพียงเท่านี้ก็สามารถควบคุมการทำงานได้แล้ว
แถมได้ code ที่อ่านง่าย แก้ไขง่ายอีกด้วย

ปล. 1 ใน Swift 3.0 การใช้งาน GCD ก็จะเปลี่ยนไปโดยสิ้นเชิง
ปล. 2 ในการออกแบบ REST API นั้นควรคิดให้มาก ๆ
ถ้าต้องให้ client ต้องมาร้อยเรียง service เองมาก ๆ
ก็ไม่ใช้การออกแบบที่ดีเลยนะ
ที่สำคัญพัฒนายากทั้งฝั่ง API และ Mobile
ที่สำคัญยากต่อการ integrate และ ทดสอบอีกด้วย

ดังนั้นมาทำการปรับปรุง code ให้ดีขึ้นกว่าเดิมกันครับ

ตัวอย่าง source code อยู่ที่ Github::Up1::Swift Sync Call

Tags:,