nattapong99 / book

0 stars 0 forks source link

Part 2: Do you need a Dependency Injection Container? #6

Open nattapong99 opened 6 years ago

nattapong99 commented 6 years ago

Do you need a Dependency Injection Container?

โดยส่วนใหญ่แล้ว คุณไม่จำเป็นต้องมี Dependency Injection Container เพื่อที่จะได้รับประโยชน์จากการใช้ Dependency Injection

แต่เวลาที่คุณต้องจัดการกับ object จำนวนมากด้วย dependency จำนวนมาก ๆ Dependency Injection Container จะสามารถช่วยคุณได้ (นึกถึง framework เป็นตัวอย่าง)

ถ้าคุณจำตัวอย่างในบทความแรกได้ที่ การสร้าง User object ต้องการการสร้าง SessionStorage object ก่อน โดยคุณต้องรู้ว่าคุณต้องใช้ dependencies อะไรก่อนที่จะสร้าง object ที่คุณต้องการ

01

ในบทความต่อ ๆ ไป เราจะพูดถึงการใช้งาน Dependency Injection Container สำหรับ Symfony เพื่อต้องการแสดงให้เห็นว่าการใช้งาน Dependency Injection Container ไม่เกี่ยวกับ Symfony จึงจะใช้ Zend Framework ในการอธิบายประกอบกับบทความนี้

Mail library ของ Zend Framework ทำหน้าที่ในการจัดการกับอีเมลล์ โดยการใข้ฟังก์ชั่น mail() เป็นค่าเริ่มตันสำหรับส่งอีเมลล์ไม่ค่อยมีความยืดหยุ่น แต่มีวิธีง่าย ๆ ที่จะแก้ไขสิ่งนี้โดยการส่ง object ลองดูจากตัวอย่างข้างล่างที่แสดงการสร้าง Zend_Mail object เพื่อใช้ส่งอีเมลล์

02

เพื่อให้บทความนี้ไม่ยาวเกินไป จากตัวอย่างสั้น ๆ ที่เห็นอาจไม่สมเหตุสมผลที่จะใช้ container 
แต่ให้ลองนึกว่าตัวอย่างสั้น ๆ นี้เป็นส่วนเล็ก ๆ ของ collection of object ที่ต้องการการจัดการ
โดยใช้ container

Dependency Injection Container คือ object ที่รู้วิธีสร้างอินสแตนซ์และการกำหนดค่า object และเพื่อให้สามารถทำงานได้ก็จำเป็นต้องรู้เกี่ยวกับ arguments ของ constructor และความสัมพันธ์ระหว่าง object

นี่คือตัวอย่าง hardcode container สำหรับ Zend_Mail ข้างบน

03

การเรียกใช้คลาส container

04

เมื่อไหร่ที่ใช้ container เราแค่เรียก mailer object โดยที่เราไม่จำเป็นต้องเกี่ยวกับวิธีการสร้างมันอีกต่อไป เนื่องจากวิธีการสร้างทั้งหมดนั้นถูกฝั่งไว้ใน container เรียบร้อยแล้ว ซึ่ง dependency ของการส่งอีเมลล์ได้ injection เข้ามาอัตโนมัติโดย container แล้ว

แต่ถ้าลองสังเกตุดูดี ๆ จะเห็นปัญหาบางอย่าง โค้ดในตัว container ทุกอย่างจะ hardcode เกินไป ดังนั้นเพื่อความยืดหยุ่น จึงได้เพิ่มพารามิเตอร์เข้ามาดังรูป

05

ตอนนี้มันง่ายแล้วที่จะเปลี่ยน Google username ลแะ password โดยส่งพารามิเตอร์ไปยัง constructor ของ container

06

ถ้าคุณต้องการเปลี่ยนคลาส mailler ที่จะใช้ทดสอบ ก็ส่งชื่อคลาส object ด้วยพารามิเตอร์ได้เช่นกัน

07

สุดท้ายแต่ไม่ท้ายสุด ในแต่ละครั้งที่คุณต้องการอีเมลล์ คุณอาจไม่ต้องการให้มีการสร้าง instance ใหม่เสมอ ดังนั้น container สามารถเปลี่ยนที่จะให้มันส่ง object ตัวเดิมกลับมาเสมอได้

08

ด้วยการใช้ 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