ในการจัดงาน iOS meetup ครั้งนี้ ทีมงานผู้เชี่ยวชาญของ Seven Peaks Software จะแนะนำให้คุณรู้จักกับภาษา Swift พร้อมด้วยเคล็ดลับในการใช้งานที่ทันสมัยที่สุดเพื่อการพัฒนาแอปฯ บน iOS ให้ประสบความสำเร็จ
วิทยากรคนแรกคือคุณ Rupendra Limbore เขาเป็น Tech Lead ผู้มีประสบการณ์กว่า 12 ปี ในการพัฒนาแอปฯ มากมายบน iOS ไม่ว่าจะเป็นแอปฯ เกี่ยวกับการเงิน การแพทย์ และอีคอมเมิร์ซ โดยเขาได้เริ่มงาน meetup ครั้งนี้ด้วยการพูดถึงการใช้งาน concurrency ใน Swift
Concurrency คือสิ่งที่ทำให้โปรแกรมสามารถรองรับ task จำนวนมากในเวลาพร้อมๆ กันได้ อย่างไรก็ตาม การเขียนโปรแกรมให้ทำงานหลายอย่างได้พร้อมกันเหมือนจะดูเป็นเรื่องง่าย แต่ก็ไม่ได้ง่ายอย่างที่คิด เพราะอาจต้องเสียเวลานานในการจัดการกับ thread และ lock ซึ่งทำให้การเขียนโปรแกรมแบบนี้เป็นเรื่องยาก
หัวข้อที่เขาพูดจะเน้นเรื่องของการอธิบาย concurrency ให้เข้าใจง่ายมากที่สุดเท่าที่จะเป็นไปได้ เพื่อให้นักพัฒนา Swift ตั้งแต่ระดับกลางขึ้นไปถึงระดับสูงสามารถนำแนวคิดดังกล่าวไปปรับใช้กับโปรเจกต์ของพวกเขาได้
วิทยากรคนที่สองคือ คุณศราวุธ สินสมรส ซึ่งเป็น Senior iOS Developer ผู้มีแนวคิดทางด้านเทคโนโลยีที่สร้างสรรค์ พร้อมประสบการณ์ในการพัฒนาแอปฯ ด้านการเงินและอีคอมเมิร์ซบน iOS มานานกว่า 10 ปี
นอกจากนี้ เขายังมีประสบการณ์ในตำแหน่ง backend developer รวมถึงสามารถจัดการฐานข้อมูลและระบบเน็ตเวิร์กได้อีกด้วย
คุณศราวุธจะมาเจาะลึกเกี่ยวกับ subject และ operator ใน RxSwift ด้วย ซึ่ง RxSwift คือ ไลบรารีสำหรับสร้างโปรแกรมแบบ asynchronous และ event-driven พร้อมด้วย observable sequence ดังนั้น subject และ operator จึงเป็นพื้นฐานสำคัญของ RxSwift เลยทีเดียว
หัวข้อของเขาจะช่วยให้คุณเข้าใจกลไกการทำงานและคุณสมบัติของ subject รวมถึงองค์ประกอบหลักๆ ของ operator ใน RxSwift ได้เป็นอย่างดี ซึ่งหากเข้าใจหลักการเบื้องต้นเหล่านี้ได้จะมีประโยชน์มาก
วิทยากรคนสุดท้าย คุณรัตนชัย อุ่ยตระกูล ผู้มีตำแหน่ง Senior iOS Developer ที่มีประสบการณ์ 8 ปีในการพัฒนาแอปพลิเคชันด้านอีคอมเมิร์ซ, video streaming, บันเทิง, และการใช้งานในองค์กรขนาดใหญ่ จะมาสาธิตวิธีการปรับปรุงประสิทธิภาพแอปฯ ของคุณ
เขามีความหลงใหลในการลดความซับซ้อนของโค้ดและกระบวนการทำงาน รวมถึงการมอบประสบการณ์ในการใช้งานอันยอดเยี่ยมให้กับผู้ใช้
คุณจะเข้าใจเครื่องมือ ตัวชี้วัด และแนวคิดที่จะช่วยให้กระบวนการพัฒนามีความราบรื่นและส่งผลให้ผู้ใช้ได้รับประสบการณ์ในการใช้งานแอปฯ ดียิ่งขึ้นได้ เพราะประสิทธิภาพของแอปฯ คือสิ่งสำคัญอย่างยิ่งในการสร้าง engagement กับผู้ใช้ และดึงดูดให้พวกเขากลับมาหาคุณอีกเรื่อยๆ
เมื่อแอปฯ มีขนาดใหญ่ขึ้น มีฟีเจอร์เยอะขึ้น และมี dependencies ภายนอกเพิ่มขึ้น จึงจำเป็นอย่างยิ่งที่จะต้องประเมินผลกระทบจากการเปลี่ยนแปลงเหล่านี้และปรับปรุงแอปฯ ให้มีประสิทธิภาพดีขึ้นอย่างต่อเนื่อง
ในที่นี้เราจะใช้ลูกอมในกล่องเป็นตัวอย่าง โดยสาธิตว่ามี 2 วิธีที่จะใส่ลูกอมลงในถ้วยให้ครบ 6 เม็ด วิธีแรกนั้นง่ายที่สุด คือหยิบลูกอมจากกล่องทีละเม็ดแล้วใส่ลงไปในถ้วย ซึ่งต้องทำทั้งหมด 6 ครั้ง
วิธีที่สองคือ หยิบลูกอมทีละ 2 เม็ดด้วยมือทั้ง 2 ข้าง ข้างละ 1 เม็ด แล้วใส่ลงในถ้วย ซึ่งจะต้องหยิบเพียง 3 ครั้ง เท่านั้น
Concurrency มีข้อดีบางอย่างที่ทำให้เราจำเป็นต้องใช้มัน ได้แก่
Thread คือ base class ที่ทำให้เราสามารถจัดการกับ thread ที่มีอยู่ในระบบปฏิบัติการและ manipulate มันได้ ซึ่ง thread เป็นคลาสที่กำหนดและประกาศใน foundation framework
ดังนั้น ในระหว่างที่ใช้งาน เราจำเป็นต้อง import ตัว foundation framework มา ซึ่ง thread จะมีให้ใช้ตั้งแต่ iOS 2.0 เป็นต้นไป
นี่เป็นคลาสพื้นฐานและสามารถนำมาใช้ด้วย initializer ที่จะทำการส่ง prop ไปหามัน หรืออาจใช้วิธี subclass thread แล้วทำการ implement main method เข้าไปแทน
มันคือการกำหนดค่าเพื่อกลยุทธ์การ execution ที่ตรงเวลา
thread priority จะมีค่าระหว่าง 0 ถึง 1 โดยมี default value เป็นเศษ 0.5 ซึ่ง Apple ได้จัดทำเอกสารข้อมูลเอาไว้ชัดเจนว่าค่าเหล่านี้เป็นเพียงแนวทางคร่าวๆ เท่านั้น
ค่าดังกล่าวไม่สามารถยืนยันได้ว่าระบบปฏิบัติการจะทำตามลำดับความสำคัญที่เรากำหนดไว้หรือไม่ เนื่องจากลำดับความสำคัญในการ execute thread นั้นจะถูกเลือกโดยระบบปฏิบัติการในระดับ kernel
ดังนั้น ค่าที่เราพูดถึงนี้จึงเป็นแนวทางเบื้องต้นที่ระบบปฏิบัติการจะถามเกี่ยวกับลำดับความสำคัญในการจัดการกับ thread นั่นเอง
เราจะ implement thread demo ง่ายๆ สักชุดหนึ่งอย่างไร
ในสถานการณ์ที่เราจำเป็นต้องอัปโหลดรูปภาพขึ้นไปบนเซิร์ฟเวอร์นั้น โดยมี 4 ขั้นตอนที่คุณต้องทำให้สำเร็จ ดังต่อไปนี้
ในการทำเช่นนี้ คุณจำเป็นต้องกำหนดคลาสที่แตกต่างกัน 4 คลาส ที่มีหน้าที่รับผิดชอบในแต่ละขั้นตอน ซึ่งในคอร์สนี้ เราไม่ได้สอนวิธีการสร้างให้มันทำงานได้เต็มรูปแบบ แต่แค่มีไว้เพื่อใช้งานทั่วไปเท่านั้น ซึ่งคลาสเหล่านี้จะนำฟังก์ชันที่เรากำหนดให้ไป implement แต่มันจะไม่สนใจ thread, concurrency, หรือการประมวลผลใดๆ ที่ทำงานอยู่เบื้องหลัง
ปัญหาก็คือ เมื่อใดก็ตามที่เราเรียกใช้ฟังก์ชันเหล่านี้โดยตรงมาจาก view controller หรือ view model มันจะเริ่มการทำงานที่ main thread ซึ่ง main thread นั้นมีการใช้งานสำหรับอัปเดต UI อยู่เสมอ
เมื่อเราเริ่มเรียกใช้ method เหล่านี้ UI ก็จะโดนบล็อก นั่นคือสาเหตุว่าทำไมทุกวันนี้เราถึงจำเป็นต้องเรียกใช้ method ให้ทำงานอยู่เบื้องหลัง เนื่องจากตัวต้นเหตุเหล่านี้ถูก implement โดยไม่คำนึงถึง concurrency ที่กำลังทำงานอยู่
เราสามารถแก้ปัญหาได้ด้วยการบริหารจัดการและ implement คลาสที่แตกต่างกันเพื่อจัดการกับ concurrency ทีนี้ลองดูจากแผนภูมินี้ว่ามีการ implement อย่างไรบ้าง โดยมันจะจัดการกับ process ที่กำลังดำเนินการอยู่ รวมถึงส่ง callback จากฟังก์ชันที่เรียกมันมาให้เรา
callback คือโค้ดชุดหนึ่งที่จะถูกบันทึกลงไปเมื่อฟีเจอร์, ฟังก์ชัน, หรือโค้ดบล็อกหนึ่งถูก execute ดังนั้น เมื่อ asynchronous task ของคุณทำงานเสร็จแล้ว คุณก็มีหน้าที่เรียก callback และให้ข้อมูลกับฟังก์ชันที่เรียกมันมาว่า task ดังกล่าวทำงานเสร็จเรียบร้อยแล้ว
ทีนี้ callback อาจจะ void ซึ่งหมายความว่ามันจะไม่มีรายละเอียดอะไรเลย และยังแสดงผลลัพธ์ที่เราสามารถนำไปใช้ในฟังก์ชันได้ ซึ่งในกรณีนี้เราใช้อีเมลในการทดสอบ
คุณอาจจะสงสัยว่ามันมีหน้าที่อะไร ซึ่งถ้าเราดึงไฟล์รูปมา ผลลัพธ์ที่คาดหวังก็ควรจะเป็นไฟล์รูป หากมีข้อผิดพลาดใดๆ เกิดขึ้น อีเมลจะคอยบอกว่าเกิดอะไรขึ้นบ้าง
มันคือ indentation ซึ่งเป็นอันที่ซับซ้อนมาก หรือที่เรียกกันว่า callback hell
ถ้าหากเรามีการทำงานของโค้ดหลายขั้นตอน เราจะต้องมี indentation และสร้างบล็อกข้างในบล็อกเป็นชั้นๆ ซึ่งเรียกกันว่า callback hell
ขั้นตอนต่อไปมีความสำคัญมาก นั่นคือ color thread ซึ่งเป็นที่ที่ฟังก์ชันจะโดนเรียก ซึ่งมีคนมากมายทำผิดพลาดด้วยการเรียก callback จาก queue หรือ thread ที่กำลังถูก execute อยู่
จะเกิดอะไรขึ้นหากคุณรันบางอย่างไว้เบื้องหลังแล้วเรียก callback ใน background thread ในตอนนั้นฟังก์ชันที่เรียกใช้งานอาจจะอยู่ใน view controller ซึ่งยังมีโอกาสที่จะถูกเรียกใน background thread ได้เช่นกัน
แล้วถ้าคุณกำลังอัปเดต UI ในส่วนนี้ แอปพลิเคชันของคุณก็จะล่ม เพราะว่าคุณกำลังอัปเดต UI จาก background thread นั่นเอง ซึ่งเป็นสิ่งที่ไม่ควรทำ
คือ base class ที่ทำให้เราสามารถจัดการและ manipulate thread ที่มีอยู่ในระบบปฏิบัติการได้ โดยคลาส thread นี้จะถูกกำหนดใน foundation framework
ซึ่งมีอยู่ 3 ประเภทด้วยกัน แบ่งตามการสร้าง ดังนี้
และสามารถแบ่งตามประเภทของ execution ได้ 2 ประเภท ดังนี้
Quality of Service (QoS)
เราจำเป็นต้องคำนึงถึงลำดับความสำคัญของสิ่งที่รันอยู่เบื้องหลัง ไม่อย่างนั้น background QoS จะทำงานเมื่อมี task ที่อาจจะรันไม่กี่นาที ไปจนถึงหลายชั่วโมง เช่น indexing ที่เราต้องรวบรวมข้อมูลสำคัญจากพื้นที่เก็บข้อมูลของระบบ
สิ่งที่น่าสนใจเกี่ยวกับ GCD และ operation queue คือมันจะมี callback เสมอ
มันเป็นสิ่งที่เหนือกว่า thread และ GCD
เนื่องจากว่ามันทำให้คุณมีฟังก์ชันมากมายอย่าง cancelling, มีตัวจัดการ dependency, และสามารถ implement ได้ง่ายกว่าและมีความ object-oriented มากกว่า
สำหรับ operation queue เรามี operation class ซึ่ง Apple มี 2 คลาสให้เราใช้ในการ implement ได้แก่ block operation และ invocation operation และเรายังสามารถ subclass operation class ได้ด้วยตัวเอง แล้วทำการ implement main method เข้าไป
เมื่อ operation มี dependencies ครบถ้วนแล้ว ก็จะสามารถเริ่ม execute ได้ นี่คือโค้ดง่ายๆ สำหรับการ implement operation ดังกล่าว
block operation ใช้ block ในส่วนของ initializer และคลาสอื่นที่เราสามารถ implement เมื่อเราจำเป็นต้อง override main method ได้ เริ่มจากการ initialize operation class ใส่มันลงไปใน operation tube เท่านี้ก็เรียบร้อย สำหรับ operation queue นั้น มีให้ใช้ตั้งแต่ iOS 2.0 เป็นต้นมา
เมื่อเราเริ่มการทำงานของ operation จะมีสิ่งที่เรียกว่า state ของ operation อยู่ ซึ่งจะถูกกำหนดและมีให้ใช้สำหรับเป็น seat เพื่อการแก้ไข operation โดยแบ่งออกเป็น 4 state ดังต่อไปนี้
และนี่คือ 4 ขั้นตอนสำคัญในการทำงานของ operation queue
Async-Await มีการนำมาใช้ใน Swift ตั้งแต่เวอร์ชัน 5.5 และ iOS 13 เป็นต้นไป โดยฟีเจอร์ของมันคือการทำให้เราสามารถ implement structural concurrency ได้ โดยสามารถนำไป implement ได้ด้วย cache ขนาดใหญ่ ส่วน return parameter ก็มีให้ใช้สำหรับ method ทุกรูปแบบเช่นเคย
ข้อดี
RxSwift: subjects และ operators
RxSwift คือไลบรารีสำหรับจัดการ asynchronous task โดยแบ่งออกเป็น 3 องค์ประกอบหลักๆ ต่อไปนี้
เป็น observable ที่สามารถเพิ่ม item ได้ตอน runtime
Operator ที่ทำงานร่วมกับ observable จากหลากหลายแหล่ง เพื่อสร้าง single output observable ได้แก่
แนวทางการปรับปรุงประสิทธิภาพในการทำงานของแอปพลิเคชัน คือ การรู้ว่าควรจะตรวจสอบประสิทธิภาพที่ตรงไหน ปรับปรุงอย่างไร และมีขั้นตอนใดบ้างที่ต้องทำก่อนเป็นอันดับแรก
แอปพลิเคชันยุคใหม่มีความซับซ้อน มากขึ้นเรื่อยๆ และบรรจุข้อมูลขนาดมหึมา เอาไว้ ซึ่งเราต้องนำไปสื่อสารกับระบบภายนอก และอาจกลายเป็นฝันร้ายทางวิศวกรรมซอฟต์แวร์ได้เลยทีเดียว
การสร้างแอปพลิเคชันใหม่ขึ้นมา สิ่งที่ไม่ควรมองข้ามคือเรื่องประสิทธิภาพ ยิ่งแอปพลิเคชันมีขนาดใหญ่ขึ้นและซับซ้อนขึ้นเท่าไร คุณก็ควรให้ความสำคัญกับการปรับปรุงให้แอปฯ มีประสิทธิภาพตั้งแต่เนิ่นๆ มากขึ้นเท่านั้น เพราะประสิทธิภาพของแอปฯ คือสิ่งสำคัญอย่างยิ่งต่อการสร้าง engagement กับผู้ใช้และทำให้พวกเขากลับมาใช้งานอีกเรื่อยๆ.
การปรับปรุงแอปฯ ของคุณให้มีประสิทธิภาพดีอย่างต่อเนื่องจะ ทำให้ผู้ใช้อยากใช้งานแอปฯ นั้นบ่อยขึ้น, และ engage กับแอปฯ ของคุณนานขึ้น.
คุณสามารถใช้งาน MetricKit สำหรับการปรับปรุงประสิทธิภาพแอปฯ ของคุณได้ ซึ่งเป็นเครื่องมือและ SDK ที่ Apple มีไว้ให้ใช้
มีตัวชี้วัด 8 อย่างเกี่ยวกับประสิทธิภาพ ได้แก่
Apple จะเชื่อมต่อกับตัวชี้วัดเหล่านี้โดยอัตโนมัติ ไม่จำเป็นต้องแก้ไขโค้ดใดๆ ในโปรเจกต์ของคุณ Apple จะเก็บข้อมูลของผู้ใช้จากอุปกรณ์ รวบรวมมันไว้ แล้วส่งไปยังเซิร์ฟเวอร์ของ Apple (iOS 13 และ iOS 14)
อย่างไรก็ตาม ในโมเดลรุ่นแรกๆ ของ iOS 15 มันจะส่งข้อมูลแทบจะทันทีเลย ซึ่งข้อมูลที่รวบรวมแล้วนี้จะแสดงอยู่ใน export
Xcode Organizer จะแสดงตัวชี้วัดที่สำคัญที่สุดจากแอปฯ ของคุณ
คุณสามารถใช้งาน MetricKit ได้ใน iOS 13 เป็นต้นไป และตอนนี้มี iOS 15 แล้ว ซึ่งมีการปรับปรุงหลายอย่างเพิ่มเติมขึ้นมา
เมื่อแอปฯ ไม่ตอบสนองต่อ input จากผู้ใช้ อาจทำให้ผู้ใช้ออกจากแอปฯ และทำให้พวกเขามีประสบการณ์ที่ไม่ดี การกำจัดอาการ hang จะทำให้แอปฯ ของคุณทำงานได้อย่างลื่นไหล รวดเร็ว และตอบสนองได้ดียิ่งขึ้น
คุณสามารถดูวิดีโอบันทึกการบรรยายสดจากงาน iOS meetup ของ Seven Peaks Software ได้ที่เพจ Facebook ของเรา.