![Dagger2]()
![Dagger2]()
จากบทความเรื่อง
Dependency Injection Made Simple
ทำการอธิบายเรื่อง Dependency Injection และ Dependency Inversion Principle (DIP)
ทำให้เข้าใจว่าวิธีการนี้มีความสำคัญอย่างไรต่อการพัฒนา software
สิ่งที่น่าสนใจคือ
การจัดการ Dependency Injection ในระบบงานด้วย Dagger
ซึ่งเป็น library ที่นักพัฒนาหลาย ๆ คนไม่น่าจะพลาด
โดยเฉพาะ Android Developer น่าจะรู้จักและใช้งานกันเกือบทุกคน !!
ในบทความข้างต้นใช้ Dagger 1
แต่ในบทความนี้ใช้ Dagger 2 นะครับ
ดังนั้นเรามาดูในรายละเอียดว่ามีอะไรที่น่าสนใจบ้าง
- Dagger 1 นั้นถูกพัฒนาและดูแลจาก Square
- Dagger 2 นั้นถูก fork มาจาก Dagger 1 ซึ่งดูแลโดย Google
สำหรับ Android app แนะนำให้ใช้ Dagger 2 นะ
เนื่องจาก Dagger 1 นั้นมีปัญหากับ proguard
เพราะว่าใน code มีการใช้ Reflection API จำนวนมาก
และ code จะ generate ออกมาดูยากมาก ๆ
ส่วน Dagger 2 นั้นทำการแก้ไขปัญหาข้างต้นให้เรียบร้อย
ส่วนการพัฒนาระบบด้วยภาษา Java ก็ใช้งานได้เช่นกัน
ซึ่งจะอยู่ในตัวอย่างด้านล่างต่อไป
คำแนะนำสำหรับการใช้งาน Dagger 2 นั้น
ควรทำความรู้จักและเข้าใจเกี่ยวกับ Dependency Injection ก่อนนะ
มิเช่นนั้นคุณจะรู้เพียงว่า ทำแบบนี้แล้วทำงานได้
แต่ไม่ได้เข้าใจเลยว่า การทำงานเป็นอย่างไร ?
ซึ่งเป็นปัญหาอย่างหนึ่งที่มักพบเจอในการพัฒนา software !! (รู้แต่ไม่เข้าใจ)
บทความเพิ่มเติมเกี่ยวกับ Depencey Injection
อธิบาย Dependency Injection ให้เข้าใจง่าย ๆ คือ
เราจะไม่ทำการสร้าง object ของ class ที่ต้องการใช้งานเอง
ตัวอย่างเช่น
[gist id="3013226898763fd6594382ae5a263d80" file="NormalDI.java"]
เมื่อ dependency class เริ่มมีเยอะ ๆ แล้ว
เราน่าจะมีการจัดกลุ่มและทำการสร้าง object เหล่านั้นให้เลย
ซึ่ง class นี้จะเรียกว่า
Factory หรือโรงงานผลิต object นั่นเอง
ตัวอย่างเช่น
[gist id="3013226898763fd6594382ae5a263d80" file="WorkWithFactory.java"]
เมื่อต้องการเรียกใช้งาน dependency ต่าง ๆ ก็เรียกใช้งาน
ผ่าน Factory กันไปเลย ดังตัวอย่าง
[gist id="3013226898763fd6594382ae5a263d80" file="Main.java"]
จะเห็นได้ว่าใน Factory ต้องเขียน code แบบเดิม ๆ สำหรับ dependency ทุกตัว
มันน่าเบื่อมาก ๆ
code ซ้ำ ๆ ซาก ๆ
ดังนั้นจึงมีคนคิด library ต่าง ๆ ขึ้นมา
เพื่อลดจำนวน code ลงไป
หนึ่งในนั้นคือ Dagger
แต่ในบทความนี้จะเน้นไปที่ Dagger 2
เริ่มด้วยการใช้งาน @Inject สำหรับ Dependency Injection กัน มีอยู่ 3 แบบ คือ
- Constructor Injection
- Field Injection
- Method Injection
ตัวอย่างเช่น
[gist id="3013226898763fd6594382ae5a263d80" file="DemoDI.java"]
ปัญหาต่อมาคือ แล้วจะไปเอา Object ของ Dependency มาจากไหนล่ะ ?
ในตัวอย่างแรกมี Factory class สำหรับเตรียมและสร้าง object ต่าง ๆ
เมื่อมาใช้ Dagger 2 แล้วก็ต้องจัดการเช่นกัน
ซึ่งจะใช้งานผ่าน
Module และ
Component
โดยโครงสร้างของ dependency ต่าง ๆ ถูกนำเสนอในรูปแบบของ graph
ที่เป็นแบบ
Directed Acyclic Graph (DAG)
มันคือ directed graph ที่ไม่เกิด cyclic นั่นเอง
ซึ่งเป็นที่มาของชื่อ Dagger นั่นเอง
แสดงดังรูป
![AcyclicDigraphs_800]()
มาดูรายละเอียดของทั้งคู่กันนิดหน่อย
Module คือ Factory นั่นเอง
สามารถแบ่ง dependency ต่าง ๆ ออกเป็นกลุ่ม
เพื่อให้ง่ายต่อการจัดการและใช้งาน
รวมทั้งเชื่อมโยง dependency ต่าง ๆ เข้าด้วยกัน
แถมสามารถอ้างอิงไปยัง Module อื่น ๆ ได้อีก
ตัวอย่างเช่น
[gist id="3013226898763fd6594382ae5a263d80" file="FirstModule.java"]
Component คือ ประตูหรือทางเข้าใช้งาน
สิ่งต่าง ๆ ที่กำหนดไว้ผ่าน annotation @Injection และ @Provides
เทียบง่าย ๆ ก็คือ interface นั่นเอง
ซึ่ง interface ไม่สามารถสร้าง object ได้
ดังนั้น Dagger 2 จึงทำการสร้าง class มาให้ใช้งาน
มีรูปแบบชื่อ class ดังนี้
DaggerComponentName
ตัวอย่างเช่น
[gist id="3013226898763fd6594382ae5a263d80" file="FirstComponent.java"]
จากนั้นให้ทำการ run ด้วยคำสั่ง
[code]
mvn clean install exec:java -Dexec.mainClass="demo.di.Main"
[/code]
จากตัวอย่างจะเห็นว่าเมื่อนำแนวคิด Dependency Injection มาใช้แล้ว
ทั้ง class MyClass, Dependency1 และ Dependency2 นั้น
แยกการทำงานออกจากกันชัดเจนมาก (Loose coupling)
ทำให้แต่ละส่วนทำงานเป็นอิสระมากขึ้น
ทำให้จัดการได้ง่ายและสะดวกขึ้น
ทำให้ทดสอบได้ง่ายขึ้น
แต่ปัญหาที่ตามมาและหลีกเลี่ยงไม่ได้คือ
ความซับซ้อนที่สูงขึ้น
จำนวน class/interface มากขึ้น
ระบบงานเริ่มมี magic มากขึ้น
ทำให้ learning curve สูงขึ้น
ดังนั้นก่อนจะเริ่มใช้งานอะไร
ขอแนะนำให้ศึกษาเรื่องพื้นฐานก่อนเสมอ
อย่าใช้เพียงเพราะว่าเขาบอกว่า ฟังมาว่า มันดี !!
สามารถดู source code ของตัวอย่างได้จาก
Github::MyDagger2
และสามารถดูตัวอย่าง code เพิ่มเติมเรื่องการชงกาแฟ
เป็นตัวอย่างจาก
Dagger 2 :: Coffee
อธิบายได้ชัดเจนมาก
โดยแสดงการทำงานดังรูป
ในบทความต่อไปจะเป็นตัวอย่างในการพัฒนา Android app
มีส่วนการทำงานหรือ dependency ต่าง ๆ เยอะมาก
ทั้ง Activity, Fragment, Service รวมทั้ง 3-parties library ต่าง ๆ อีก
มาดูกันว่าสามารถจัดการด้วย Dagger 2 กันอย่างไร