จากบทความเรื่อง Dependency Injection Made Simple
ทำการอธิบายเรื่อง Dependency Injection และ Dependency Inversion Principle (DIP)
ทำให้เข้าใจว่าวิธีการนี้มีความสำคัญอย่างไรต่อการพัฒนา software
สิ่งที่น่าสนใจคือ
การจัดการ Dependency Injection ในระบบงานด้วย Dagger
ซึ่งเป็น library ที่นักพัฒนาหลาย ๆ คนไม่น่าจะพลาด
โดยเฉพาะ Android Developer น่าจะรู้จักและใช้งานกันเกือบทุกคน !!
ในบทความข้างต้นใช้ Dagger 1 แต่ในบทความนี้ใช้ Dagger 2 นะครับดังนั้นเรามาดูในรายละเอียดว่ามีอะไรที่น่าสนใจบ้าง
สำหรับ Android app แนะนำให้ใช้ Dagger 2 นะ
เนื่องจาก Dagger 1 นั้นมีปัญหากับ proguard เพราะว่าใน code มีการใช้ Reflection API จำนวนมาก และ code จะ generate ออกมาดูยากมาก ๆ ส่วน Dagger 2 นั้นทำการแก้ไขปัญหาข้างต้นให้เรียบร้อย ส่วนการพัฒนาระบบด้วยภาษา Java ก็ใช้งานได้เช่นกัน ซึ่งจะอยู่ในตัวอย่างด้านล่างต่อไปคำแนะนำสำหรับการใช้งาน Dagger 2 นั้น
ควรทำความรู้จักและเข้าใจเกี่ยวกับ Dependency Injection ก่อนนะ มิเช่นนั้นคุณจะรู้เพียงว่า ทำแบบนี้แล้วทำงานได้ แต่ไม่ได้เข้าใจเลยว่า การทำงานเป็นอย่างไร ? ซึ่งเป็นปัญหาอย่างหนึ่งที่มักพบเจอในการพัฒนา software !! (รู้แต่ไม่เข้าใจ) บทความเพิ่มเติมเกี่ยวกับ Depencey Injection- http://www.somkiat.cc/dependency-injection-vs-dependency-inversion/
- http://www.somkiat.cc/let-start-with-dependency-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
ปัญหาต่อมาคือ แล้วจะไปเอา Object ของ Dependency มาจากไหนล่ะ ?
ในตัวอย่างแรกมี Factory class สำหรับเตรียมและสร้าง object ต่าง ๆ เมื่อมาใช้ Dagger 2 แล้วก็ต้องจัดการเช่นกัน ซึ่งจะใช้งานผ่าน Module และ Component โดยโครงสร้างของ dependency ต่าง ๆ ถูกนำเสนอในรูปแบบของ graph ที่เป็นแบบ Directed Acyclic Graph (DAG) มันคือ directed graph ที่ไม่เกิด cyclic นั่นเอง ซึ่งเป็นที่มาของชื่อ Dagger นั่นเอง แสดงดังรูป มาดูรายละเอียดของทั้งคู่กันนิดหน่อย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 กันอย่างไร