แชร์ความรู้ ที่ได้จากในงาน Mobile Code Fighting

Thongpak Pongsilathong
Nextzy
Published in
3 min readMay 4, 2017

ช่วงประมาณกลางเดือนมีนาคม รู้ว่าจะได้ไปพูดในงาน Mobile fighting ที่เชียงใหม่ เพราะฉะนั้นจะเหลือเวลาในการเตรียมตัวอยู่ไม่ถึง 1 เดือนนั่นเอง จากนั้นเราก็มาสุมหัวคิดว่าจะทำหัวข้อเรื่องอะไรทำไปจัดงานกันดี กว่าจะคิดหัวข้อได้และเริ่มทำก็คือประมาณต้นเดือน เมษายนแล้วทำให้เหลือเวลาไม่กี่สัปดาห์เราก็เลยเอาวันหยุดสงกรานต์ออกไปเพื่อมาทำการเตรียมตัวนั่นเอง หัวข้อที่จะไปพูดคือเรื่อง MVVM ทางฝั่ง iOS ซึ่งเป็น Design Pattern ที่เราใช้งานกันอยู่ในขณะนี้

ก่อนที่จะมารู้จักกับ MVVM เราจะมาทำความรู้จัก MVC กันก่อน

MVC

MVC Design Patterns

จากภาพเดิมที MVC นั้นเป็น Design Patterns ที่อยู่คู่กับการพัฒนาแอปของ iOS มาแต่เดิม มาอธิบายตัวย่อแต่ละตัวกันดังนี้

  • Model คือข้อมูลต่างๆ ต่อๆ เป็น Business Domain ของธุรกิจ ex ข้อมูลเบียร์ ข้อมูลผู้ใช้ ในรูปแบบของ object
  • View คือส่วนที่ใช้ในการแสดงผลบนหน้าจอ เช่น รูปภาพ หรือข้อความต่างๆที่ User เห็นจริงๆ
  • Controller จะเป็นส่วนของการควบคุมการทำงานต่างๆของแอปพลิเคชั่นที่ถูกทำหน้าที่อยู่ตรงกลางระหว่าง Model และ View นั่นเอง

หลายๆคนที่ทำการเขียน iOS มานั้นจะสังเกตเห็นได้ว่า View และ Controller มีความสัมพันธ์ไกล้ชิดกันมาก มีการทำอะไรหลายๆอย่างเข้าด้วยกันจึงเขียน Diagram ใหม่ได้แบบนี้

ถ้าเกิดมองง่ายๆ Model จะเป็นข้อมูลที่ต้องถูกส่งไปแสดงที่ View โดยมี Controller เป็นตัวกลางในการรับส่งข้อมูล และทำการปรับข้อมูลต่างๆก่อนที่จะถูกนำมาแสดงที่ View ซึ่งใน MVC เราจะสังเกตได้ว่ามี Logic ต่างๆอยู่มากมายใน Controller รวมถึง Logic บางส่วนที่ไม่มีส่วนเกี่ยวข้องกับ Controller ที่เรียกว่า View Logic ปัญหานี้จะทำให้ Code ที่อยู่ใน Controller รกเกินความจำเป็นทำให้อ่านยาก เราเลยได้แยกในส่วนของ View Logic มาเก็บไว้ในชื่อว่า ViewModel

MVVM

MVVM Design Patterns

เราจะมาอธิบายตัวย่อของ MVVM ของแต่ละตัวกันก่อน

  • Model
  • View
  • ViewModel

จากรูปข้างบนเราจะเห็นได้ว่ามี ViewModel ถูกเพิ่มขึ้นมาระหว่าง Controller และ Model ซึ่ง ViewModel จะคอยทำหน้าที่จัดการ View Logic ต่างๆที่เคยอยู่บน Controller นั่นเอง ในการติดต่อ Controller และ ViewModel นั้นทำได้หลายวิธี เช่น KVO, Notification Center, Delegate ซึ่งในโปรเจ็คเราใช้เทคนิค Delegate ในการเชื่อมต่อ เราจะมาดูกัน

Delegate Design Patterns

Delegate (n.) ตัวแทน

Delegate เป็นหนึ่งใน Design Pattern ซึ่งคำว่า Delegate เป็นคำนามมีความหมายก็คือตัวแทน ซึ่ง Delegate จะคอยทำหน้าที่แทน ที่เราสามารถมอบหมายให้ไปทำหน้าที่บางอย่างที่เรากำหนดไว้ได้ ในรูปภาพข้างบนเราจะสังเกตเห็นได้ว่า BaseViewController มอบหมายให้ BaseViewModel สามารถทำหน้าที่แทน BaseViewController แทนได้นั่นเอง โดยขอบเขตของการทำงานจะถูกจำกัดไว้ใน BaseViewModelDelegate

ในการขึ้นโครงของ MVVM นั้นจะเป็นการเพิ่มความยุ่งยากมากกว่าเดิม ถ้าเราต้องมา Implement Protocol และ Delegate ต่างๆ ให้กับ Model, ViewModel และ Controller ซึ่งมันจะเป็นการใส่ Code จำเจที่เราต้องใส่ทุกครั้ง เพราะฉะนั้นเราเลยต้องทำ Base Class ขึ้นมาเพื่อลดความจำเจของ Code นั่นเอง

Base Class

Base Class ที่จำเป็นและใช้งานบ่อยๆหลักๆจะมีอยู่สองตัวคือ BaseViewModel และ BaseViewController โดยทุก Class ที่เราสร้างขึ้นมาต้องทำการ Extend Base Class เสมอ และ Code ต่างๆที่จะมีในทุกๆ Controller หรือทุกๆ ViewModel ให้เรานำไปใส่ไว้ใน Base Class

Base Class Example
BeerViewModel: BaseViewModel {
var person = Person()
func getData() {
person = Person(name: "Thongpak Pongsilathong")
delegate.onDataDidload()
}
}

จะเห็นว่าเมื่อเราทำการ getData เรียบร้อยแล้ว viewModel จะทำการส่งสัญญาณไปบอก ViewController เพื่อให้ทำการ update UI

BeerViewController: BaseViewController {
var viewModel = BeerViewModel(delegate: self)
@IBOutlet weak var nameLabel: UILabel!

override func viewDidLoad() {
super.viewDidLoad()
viewModel.getData()
}
override func onDataDidLoad() {
nameLabel.text = viewModel.person.name
}
}

เท่านี้ก็จบกันแล้วสำหรับ MVVM เบื้องต้น ซึ่งในตอนที่ผมเริ่มศึกษา MVVM ก็ได้อ่าน บทความของหลายๆคน ก็ไปเจอกับบทความของ macbaszii ที่เขียนออกมาได้ดีเลยทีเดียวเลยนำมาทำเป็นแบบอย่าง

ในการจะเลือก Design Patterns ต่างๆที่จะเอาไว้ใช้ในโปรเจ็ค เราควรจะเลือกให้เหมาะสมกับขนาดความใหญ่ของ App ถ้าเกิดเป็นโปรเจ็คเล็กๆมีแค่ไม่กี่หน้าเราก็สามารถที่จะเลือก MVC ได้เช่นกัน แต่ถ้าเป็นโปรเจ็คขนาดใหญ่ และต้องมีการปรับเปลี่ยนหรือเพิ่มฟีเจอร์ต่างๆเข้ามาเรื่อยๆ เราควรจะเลือกใช้ Design Patterns ให้เหมาะสมเพื่อที่จะใช้ได้ในระยะยาว ถึงแม้ว่าตอนขึ้นโครงนั้นจะเป็นช่วงที่งานหนักพอสมควร

IGListKit

อาจจะไม่เกี่ยวกับ MVVM แต่อยากจะมาแชร์สักหน่อย ถ้าพูดถึงเรื่องที่ต้องแสดงหน้า List ต่างๆ คงไม่แพ้ TableView และ CollectionView นั่นเอง และจากเท่าที่ลองเล่นมาทำให้มีความรู้สึกชอบมากๆ เนื่องจากใช้งานได้ง่าย code มีความเป็นระเบียบมากขึ้น และยิ่งนำมาใช้คู่กับ MVVM จะทำให้ Code ในส่วนของ Controller นั้นหายไปได้พอสมควรเลยทีเดียว เลยได้นำ IGListKit มาใส่ไว้ในโปรเจ็คที่จะเอาไป Battle ด้วยเลย ก่อนอื่นเลย เรามาทำความรู้จักกับ TableView และ CollectionView กันเล็กน้อย

จากภาพข้างบนเราจะมาพูดถึงความแตกต่างระหว่าง TableView และ CollectionView ซึ่งเราจะสังเกตได้ว่า Concept ของ TableView จะแบ่งเป็น row และ 1 row จะมี 1 cell แต่ CollectionView ก็จะแบ่งเป็น row เหมือนกันแต่ว่าใน 1 row จะมีกี่ cell ก็ได้ ซึ่งในการใช้งานจริงนั้น TableView นั้นสามารถใช้งานได้ง่ายกว่า CollectionView พอสมควร เนื่องจาก CollectionView นั้นมีความ Dynamic สูงทำให้ต้องใช้การปรับแต่งต่างๆมากพอสมควร ทีนี้มาเข้าเรื่องกันเลย

IGListKit มันก็คือ open source library ที่ทาง Instragram พัฒนาขึ้นมา พูดง่ายๆมันก็คือ CollectionView ที่ทาง Instragam ได้นำไปปรับแต่งเพื่อให้สามารถใช้งานง่ายขึ้นนั่นเอง

ซึ่งในโปรเจ็คที่เราทำ demo ไว้ เราได้ใช้ IGListKit ทั้งแอปแทนการใช้ TableView

ด้านล่างนี้เป็น Link github ของ IGListKit เผื่อคนที่สนใจจะศึกษาต่อมาลองเล่นกันได้

เสริมเรื่องการออกแบบโปรเจ็คขนาดใหญ่ ปัญหาที่เกิดขึ้นเมื่อโปรเจ็คมีขนาดใหญ่มาก ทำให้เราเสียเวลาใน build app ใช้เวลานาน ซึ่งก็มีเทคนิคหลายแบบที่มาช่วยเรื่องนี้เช่นกัน เช่น git submodule หรือ private pods แต่ส่วนตัวนั้นผมชอบ private pods มาก ซึ่งตอนเราวางแผนที่จะทำโปรเจ็ค เราควรจะแบ่งออกเป็น module ต่างๆแยกออกมาทำเป็น private pods พูดง่ายๆก็คือเราสามารถใช้คำสั่ง pod install เพื่อ ดึง source code ในส่วนแต่ละ module เอามารวมกันได้นั่นเอง

Link ด้านล่างเป็นตัวอย่างการทำ public pods ซึ่งจะคล้ายๆกับการทำ private pods

ด้านล่างนี้เป็นโปรเจ็คที่ได้ทำขึ้นมาสำหรับคนที่สนใจใน MVVM และเทคโนโลยีต่างๆที่เราใช้กัน

--

--