Open nattapong99 opened 6 years ago
โดยส่วนใหญ่แล้ว คุณไม่จำเป็นต้องมี Dependency Injection Container เพื่อที่จะได้รับประโยชน์จากการใช้ Dependency Injection
แต่เวลาที่คุณต้องจัดการกับ object จำนวนมากด้วย dependency จำนวนมาก ๆ Dependency Injection Container จะสามารถช่วยคุณได้ (นึกถึง framework เป็นตัวอย่าง)
ถ้าคุณจำตัวอย่างในบทความแรกได้ที่ การสร้าง User object ต้องการการสร้าง SessionStorage object ก่อน โดยคุณต้องรู้ว่าคุณต้องใช้ dependencies อะไรก่อนที่จะสร้าง object ที่คุณต้องการ
User
SessionStorage
ในบทความต่อ ๆ ไป เราจะพูดถึงการใช้งาน Dependency Injection Container สำหรับ Symfony เพื่อต้องการแสดงให้เห็นว่าการใช้งาน Dependency Injection Container ไม่เกี่ยวกับ Symfony จึงจะใช้ Zend Framework ในการอธิบายประกอบกับบทความนี้
Mail library ของ Zend Framework ทำหน้าที่ในการจัดการกับอีเมลล์ โดยการใข้ฟังก์ชั่น mail() เป็นค่าเริ่มตันสำหรับส่งอีเมลล์ไม่ค่อยมีความยืดหยุ่น แต่มีวิธีง่าย ๆ ที่จะแก้ไขสิ่งนี้โดยการส่ง object ลองดูจากตัวอย่างข้างล่างที่แสดงการสร้าง Zend_Mail object เพื่อใช้ส่งอีเมลล์
mail()
Zend_Mail
เพื่อให้บทความนี้ไม่ยาวเกินไป จากตัวอย่างสั้น ๆ ที่เห็นอาจไม่สมเหตุสมผลที่จะใช้ container แต่ให้ลองนึกว่าตัวอย่างสั้น ๆ นี้เป็นส่วนเล็ก ๆ ของ collection of object ที่ต้องการการจัดการ โดยใช้ container
Dependency Injection Container คือ object ที่รู้วิธีสร้างอินสแตนซ์และการกำหนดค่า object และเพื่อให้สามารถทำงานได้ก็จำเป็นต้องรู้เกี่ยวกับ arguments ของ constructor และความสัมพันธ์ระหว่าง object
นี่คือตัวอย่าง hardcode container สำหรับ Zend_Mail ข้างบน
การเรียกใช้คลาส container
เมื่อไหร่ที่ใช้ container เราแค่เรียก mailer object โดยที่เราไม่จำเป็นต้องเกี่ยวกับวิธีการสร้างมันอีกต่อไป เนื่องจากวิธีการสร้างทั้งหมดนั้นถูกฝั่งไว้ใน container เรียบร้อยแล้ว ซึ่ง dependency ของการส่งอีเมลล์ได้ injection เข้ามาอัตโนมัติโดย container แล้ว
แต่ถ้าลองสังเกตุดูดี ๆ จะเห็นปัญหาบางอย่าง โค้ดในตัว container ทุกอย่างจะ hardcode เกินไป ดังนั้นเพื่อความยืดหยุ่น จึงได้เพิ่มพารามิเตอร์เข้ามาดังรูป
ตอนนี้มันง่ายแล้วที่จะเปลี่ยน Google username ลแะ password โดยส่งพารามิเตอร์ไปยัง constructor ของ container
ถ้าคุณต้องการเปลี่ยนคลาส mailler ที่จะใช้ทดสอบ ก็ส่งชื่อคลาส object ด้วยพารามิเตอร์ได้เช่นกัน
สุดท้ายแต่ไม่ท้ายสุด ในแต่ละครั้งที่คุณต้องการอีเมลล์ คุณอาจไม่ต้องการให้มีการสร้าง instance ใหม่เสมอ ดังนั้น container สามารถเปลี่ยนที่จะให้มันส่ง object ตัวเดิมกลับมาเสมอได้
ด้วยการใช้ static $shared property ในแต่ละครั้งที่คุณเรียกเมธอด getMailer() object จะถูกสร้างสำหรับการเรียกครั้งแรกจะถูกส่งกลับมา
getMailer()
ที่กล่าวมาคือคุณสมบัติพื้นฐานที่จำเป็นต้องใช้โดย Dependency Injection Container โดย Dependency Injection Container จะจัดการโดยการสร้าง instantiation เพื่อกำหนดค่า ซึ่งตัว object มันเองไม่ทราบว่ามีการจัดการโดย Container และไม่รู้อะไรเกี่ยวกับ Container นั่นเป็นเหตุผลที่ Container สามารถจัดการ PHP object ใดก็ได้ จะดียิ่งขึ้นถ้า object ใช้การ Dependency Injection สำหรับการอ้างอิง แต่นั่นไม่ใช่สิ่งที่จำเป็นต้องทำก่อน
แน่นอนว่าการสร้างและบำรุงรักษาคลาส container ด้วยตนเองแต่เป็นงานที่หนักเกินไป แต่หาก requirement มีไม่มากนักการใช้ container ก็มีประโยชน์เช่นกัน ในหัวข้อต่อไปจะเป็นการใช้งาน dependency injection container ใน Symfony 2
source
Do you need a Dependency Injection Container?
โดยส่วนใหญ่แล้ว คุณไม่จำเป็นต้องมี Dependency Injection Container เพื่อที่จะได้รับประโยชน์จากการใช้ Dependency Injection
แต่เวลาที่คุณต้องจัดการกับ object จำนวนมากด้วย dependency จำนวนมาก ๆ Dependency Injection Container จะสามารถช่วยคุณได้ (นึกถึง framework เป็นตัวอย่าง)
ถ้าคุณจำตัวอย่างในบทความแรกได้ที่ การสร้าง
User
object ต้องการการสร้างSessionStorage
object ก่อน โดยคุณต้องรู้ว่าคุณต้องใช้ dependencies อะไรก่อนที่จะสร้าง object ที่คุณต้องการในบทความต่อ ๆ ไป เราจะพูดถึงการใช้งาน Dependency Injection Container สำหรับ Symfony เพื่อต้องการแสดงให้เห็นว่าการใช้งาน Dependency Injection Container ไม่เกี่ยวกับ Symfony จึงจะใช้ Zend Framework ในการอธิบายประกอบกับบทความนี้
Mail library ของ Zend Framework ทำหน้าที่ในการจัดการกับอีเมลล์ โดยการใข้ฟังก์ชั่น
mail()
เป็นค่าเริ่มตันสำหรับส่งอีเมลล์ไม่ค่อยมีความยืดหยุ่น แต่มีวิธีง่าย ๆ ที่จะแก้ไขสิ่งนี้โดยการส่ง object ลองดูจากตัวอย่างข้างล่างที่แสดงการสร้างZend_Mail
object เพื่อใช้ส่งอีเมลล์Dependency Injection Container คือ object ที่รู้วิธีสร้างอินสแตนซ์และการกำหนดค่า object และเพื่อให้สามารถทำงานได้ก็จำเป็นต้องรู้เกี่ยวกับ arguments ของ constructor และความสัมพันธ์ระหว่าง object
นี่คือตัวอย่าง hardcode container สำหรับ
Zend_Mail
ข้างบนการเรียกใช้คลาส container
เมื่อไหร่ที่ใช้ container เราแค่เรียก mailer object โดยที่เราไม่จำเป็นต้องเกี่ยวกับวิธีการสร้างมันอีกต่อไป เนื่องจากวิธีการสร้างทั้งหมดนั้นถูกฝั่งไว้ใน container เรียบร้อยแล้ว ซึ่ง dependency ของการส่งอีเมลล์ได้ injection เข้ามาอัตโนมัติโดย container แล้ว
แต่ถ้าลองสังเกตุดูดี ๆ จะเห็นปัญหาบางอย่าง โค้ดในตัว container ทุกอย่างจะ hardcode เกินไป ดังนั้นเพื่อความยืดหยุ่น จึงได้เพิ่มพารามิเตอร์เข้ามาดังรูป
ตอนนี้มันง่ายแล้วที่จะเปลี่ยน Google username ลแะ password โดยส่งพารามิเตอร์ไปยัง constructor ของ container
ถ้าคุณต้องการเปลี่ยนคลาส mailler ที่จะใช้ทดสอบ ก็ส่งชื่อคลาส object ด้วยพารามิเตอร์ได้เช่นกัน
สุดท้ายแต่ไม่ท้ายสุด ในแต่ละครั้งที่คุณต้องการอีเมลล์ คุณอาจไม่ต้องการให้มีการสร้าง instance ใหม่เสมอ ดังนั้น container สามารถเปลี่ยนที่จะให้มันส่ง object ตัวเดิมกลับมาเสมอได้
ด้วยการใช้ static $shared property ในแต่ละครั้งที่คุณเรียกเมธอด
getMailer()
object จะถูกสร้างสำหรับการเรียกครั้งแรกจะถูกส่งกลับมาที่กล่าวมาคือคุณสมบัติพื้นฐานที่จำเป็นต้องใช้โดย Dependency Injection Container โดย Dependency Injection Container จะจัดการโดยการสร้าง instantiation เพื่อกำหนดค่า ซึ่งตัว object มันเองไม่ทราบว่ามีการจัดการโดย Container และไม่รู้อะไรเกี่ยวกับ Container นั่นเป็นเหตุผลที่ Container สามารถจัดการ PHP object ใดก็ได้ จะดียิ่งขึ้นถ้า object ใช้การ Dependency Injection สำหรับการอ้างอิง แต่นั่นไม่ใช่สิ่งที่จำเป็นต้องทำก่อน
แน่นอนว่าการสร้างและบำรุงรักษาคลาส container ด้วยตนเองแต่เป็นงานที่หนักเกินไป แต่หาก requirement มีไม่มากนักการใช้ container ก็มีประโยชน์เช่นกัน ในหัวข้อต่อไปจะเป็นการใช้งาน dependency injection container ใน Symfony 2
source