Swinject Auto Dependency Injection Like a Boss

Narong K.
FLOWACCOUNT TECH BLOG
2 min readJun 20, 2022

Dependency Injection คืออะไร

ก่อนที่เราจะมาทำความรู้จักกับ Dependency #Injection เรามาลองแปลคำศัพย์เเต่ละตัวเพื่อความเข้าใจกันก่อนดีกว่า Dependency Injection ประกอบไปด้วย 2 ส่วนคือ “Dependency” และ “Injection”

คำว่า Dependency ความหมายก็ตรงตัวครับคือ สิ่งที่ขึ้นอยู่กับสิ่งอื่น พึ่งพาสิ่งอื่น โดยในทาง programming นั้นก็เหมือน object หนึ่งที่จะสามารถทำงานได้ต้องประกอบไปด้วย class อื่นที่ทำงานร่วมกันเพื่อให้ได้ผลลัพธ์ที่เราต้องการ เช่น ViewModel ต้องการ APIService ในการ ติดต่อกับ API.

ส่วนคำว่า Injection หรือ inject ก็คือการฉีด หรืออีกความหมายคือ การนำสิ่งหนึ่งเข้าไปในอีกสิ่งหนึ่ง โดยในทาง programming นั้นก็เหมือนการที่ส่ง object เข้าไปใน class แทนการที่เราสร้างมันขึ้นมา ข้างในดื้อๆนั้นเอง

สรุป Dependency Injection คือ Software Design Pattern รูปแบบหนึ่งที่จะให้เราส่ง dependency object ที่เราต้องการเข้ามา แทนการสร้าง dependency object ขึ้นมาใหม่ใน class ตรงๆ ซึ่งจะช่วยให้เรา reuse code, สร้าง mock object และเขียน Test ได้ง่ายขึ้น

หลังจากที่เราทำความรู้จักกับ Dependency Injection หรือเรียกสั้นๆว่า DI กันพอสมควรแล้วเรามา ทำความรู้จักกับ Swinject พระเอกของเรากันดีกว่า

Swinject คืออะไร?

Swinject ก็คือ `lightweight dependency injection framework` สำหรับภาษา Swift เค้าเคลมว่า แบบนั้น หรือง่ายๆก็คือ 3rd party dependency injection library ที่ช่วยให้เราสามารถเขียน code ได้ง่ายขึ้น สะอาดขึ้น นั้นเอง

แล้วทำไมเราต้องใช้ Swinject ในเมื่อ DI ปกติก็ใช้ได้อยู่แล้ว?

เป็นคำถามที่ต้องเกิดขึ้นมาในหัวแน่นอน งั้นเราลองมาดูตัวอย่างใน code ที่ใช้ DI ปกติกันครับ โดย code ตัวอย่างจะประกอบไปด้วย DocumentModel, CalculatorManager, DocumentCalculatorManager, DocumentAPI และ DocumentFormViewModel

พอเรานำ class พวกนี้มาประกอบกัน เราก็จะได้ code ออกมาหน้าตาประมาณนี้

จะเห็นได้ว่า line of code ค่อนข้างเยอะบวกกับเวลาที่เราจะใช้ ViewModel เราต้องสร้าง dependency object ขึ้นใหม่แล้ว Inject เข้าไปทุกครั้ง ยิ่งถ้าเรามี dependency object ใน class เยอะ เราก็ต้องสร้างเยอะขึ้นตามไปด้วย

ทีนี้เรามาลองใช้ Swinject + DI แล้วมาดูกันว่ามันแก้ปัญหานี้ยังไง

เพื่อไม่ให้บทความยาวเกินไปผมขอข้ามในส่วนของการ install ตัว Swinject ไปเลยนะครับ ผมคิดว่า เพื่อนๆ สามารถทำกันได้สบายอยู่แล้ว เรามาดูในส่วนของการ setup project กันดีกว่า

  1. สร้าง DIApiServiceExt.swift ขึ้นมาพร้อม import Swinject จากนั้นก็ register service ที่เรา ต้องการ จากตัวอย่างจะเห็นว่าเรา register DocumentAPI.self และ return object DocumentAPI() ออกมา เราจะเรียกส่วนนี้ว่า factory. ทำแบบเดียวกันกับทุก layer ครับ

2. หลังจากเรา register service กับ container เรียบร้อยแล้ว เราก็สร้าง extension ของ UIViewController โดยประกาศตัวแปร container เพื่อให้ง่ายต่อการเรียกใช้ จากนั้นก็เรียก function register ที่เราสร้างไว้เมื่อสักครู่

ข้อควรระวัง การ register service ต้องทำก่อนการเรียกใช้เสมอนะครับ ไม่งั้น code ของเราจะเกิด runtime error สังเกตจาก service ที่เรา resolve นั้นจะมีค่าเป็น optional

ทีนี้ได้เวลา refactor ViewController ของเรากันครับ

จากตัวอย่าง ViewControllerWithAutoDI.swift คือ code ที่เราใช้ Swinject + DI ส่วน ViewControllerWithNoneAutoDI.swift คือ code ที่เราใช้ DI ปกติ จะเห็นได้ว่า line of code น้อยลง code ของเราดูสะอาดขึ้น สามารถ reuse service ที่เราเคย register ไปแล้วได้ ลดการสร้าง object ขึ้นมาซ้ำๆ happy coding! ครับผม

จริงๆแล้ว Swinject ยังมีความสามารถ + extensions อีกเยอะมากครับ หากเพื่อนๆสนใจสามารถไป กด follow กด start ที่ repo Swinject กันได้นะครับของเค้าดีจริง

For more articles from FlowAccount Tech Blog, please visit https://medium.com/flowaccount-tech.

Open Positions jobs available on FlowAccount > https://flowaccount.com/en/jobs

--

--