Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. PHP

Dependency Injection: Huh?

by
Read Time:6 minsLanguages:

Hindi (हिंदी) translation by Ashish Rampal (you can also view the original English article)

संभावना है कि आपके सीखने के कुछ बिंदु पर, आप इसे शब्द से परिचित हों "dependency injection"। यदि आप अभी भी अपने सीखने में अपेक्षाकृत प्रारंभिक हैं, तो आप शायद एक कन्फ्यूज्ड एक्सप्रेशन बना लिया है और उस भाग को छोड़ दिया है। फिर भी, यह लेखन योग्य (और testable) कोड लिखने का एक महत्वपूर्ण पहलू है। इस आलेख में, मैं इसे सरल रूप में समझाता हूँ जितना मैं सक्षम हूं।


एक उदाहरण

चलो एक काफी जेनेरिक पीस ऑफ़ कोड में कूदते हैं, और अपनी कमियों पर चर्चा करते हैं।

पहली नज़र में, यह कोड काफी हानिकारक लग सकता है। लेकिन इस तथ्य पर विचार करें कि, पहले से ही, हमने एक dependency को हार्डकोडेड किया है: डेटाबेस कनेक्शन। क्या होगा अगर हम एक अलग पर्सिस्टेंस (persistence) लेयर पेश करना चाहते हैं? या, इसके बारे में इस तरह सोचें: बाहरी स्रोतों के साथ Photo ऑब्जेक्ट को कैसे कम्यूनिकेट करना चाहिए? क्या ये concerns को अलग करने की कांसेप्ट का उल्लंघन नहीं करता है? यह निश्चित रूप से करता है इस ऑब्जेक्ट को किसी भी चीज से संबंधित नहीं होना चाहिए जो सीधे Photo से रिलेटेड नहीं है

मूल विचार यह है कि आपकी classes को केवल एक चीज़ के लिए जिम्मेदार होना चाहिए। इसके साथ दिमाग में, यह डेटाबेस और उस नेचर की अन्य चीजों से जुड़ने के लिए जिम्मेदार नहीं होना चाहिए।

उसी तरह वस्तुओं के बारे में सोचें जिस तरह आप अपने पालतू जानवरों के बारे में सोचते हैं। यह कुत्ते का फैसला नहीं होता कि कब वह घूमने के लिए बाहर जाता है या पार्क में खेलता है। तुम करो! यह इन निर्णयों को बनाने के लिए उनकी जगह नहीं है।

चलो क्लास का नियंत्रण पुनः प्राप्त करें, और इसके बजाय, डेटाबेस कनेक्शन में पास करें। यह पूरा करने के दो तरीके हैं: constructor और setter injection क्रमशः। यहां दोनों के उदाहरण हैं:

Constructor Injection

इसके बाद, हम सभी required dependencies को इंजेक्ट करते हैं, जब क्लास के constructor मेथड रन करते हैं, उनको क्लास के अंदर सीधे हार्डकोडिंग करने की बजाये।

Setter Injection

इस सरल परिवर्तन के साथ, क्लास अब किसी भी विशिष्ट कनेक्शन पर निर्भर नहीं है। बाहरी सिस्टम पूर्ण नियंत्रण बरकरार रखता है, जैसा मामला होना चाहिए। हालांकि यह तुरंत दिखाई नहीं देता है, यह तकनीक भी टेस्ट के लिए काफी आसान क्लास बनाता है, क्योंकि अब हम डेटाबेस को नकल कर सकते हैं, जब setDB मेथड को कॉल करते हैं।

इससे भी बेहतर, यदि हम बाद में एक अलग तरह के पर्सिस्टेंस का उपयोग करने का निर्णय लेते हैं, तो dependency injection के कारण, यह एक cinch है।

"Dependency Injection है जहां कंपोनेंट्स को उनकी constructors, methods या सीधे fields में अपनी dependencies दी जाती है।"


The Rub

इस तरीके से setter injection का उपयोग करने में एक समस्या है: यह class के साथ काम करना काफी अधिक कठिन बना देता है। यूजर को अब क्लास की dependencies से पूरी तरह अवगत होना चाहिए, और उन्हें निर्धारित करना अवश्य याद रखना चाहिए, तदनुसार। रेखा के नीचे, विचार करें, जब हमारे fictional class को कुछ अधिक dependencies की आवश्यकता होती है। अच्छा, dependency injection पैटर्न के नियमों का पालन करते हुए, हमें करना होगा:

ओह, क्लास अधिक मॉड्यूलर हो सकती है, लेकिन हमने confusion और कम्प्लेक्सिटी पर भी ढेर किया है इससे पहले, यूजर Photo का एक नया instance बना सकता था, लेकिन अब, उसे इन सभी dependencies को सेट करना याद रखना होगा। क्या मुसीबत है!


समाधान

इस दुविधा का हल एक कंटेनर क्लास बनाना है जो हमारे लिए काम की खामियों को संभालना होगा। यदि आप कभी भी इस टर्म के संपर्क में आए हैं, "Inversion of Control (IoC)," अब आपको पता है कि वे क्या बात कर रहे हैं।

परिभाषा: सॉफ्टवेयर इंजीनियरिंग में, Inversion of Control (IoC) एक ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग प्रैक्टिस है, जहां ऑब्जेक्ट कपलिंग एक असेम्बलर ऑब्जेक्ट द्वारा रन टाइम पर बाउंड किया जाता है और सामान्यतः स्टैटिक विश्लेषण (static analysis) का उपयोग करके compile के समय नहीं जाना जाता है।

यह क्लास हमारे प्रोजेक्ट के लिए सभी dependencies की रजिस्ट्री का संग्रह करेगी। प्रत्येक key में सम्बंधित lambda फ़ंक्शन होता है जो सम्बंधित क्लास को instantiate करता है।

इस से निपटने के लिए कुछ तरीके हैं। हम explicit हो सकते हैं, और स्टोर मेथड्स, जैसे कि newPhoto:

अब, $photo Photo class के एक नए इंस्टेंस के बराबर होंगे, जो कि सभी आवश्यक dependencies सेट के साथ होंगे। इस तरह, यूजर को मैन्युअल रूप से इन dependencies को निर्धारित करने की आवश्यकता नहीं है; वह केवल newPhoto method को कॉल करता है।

दूसरा विकल्प, हर क्लास के इंस्टैंस के लिए एक नई मेथड बनाने की बजाय, एक जेनेरिक रजिस्ट्री कंटेनर लिखना है, जैसे:

यह कोड आपको डरा न दें; यह वाकई बहुत सरल है। जब यूजर IoC::register method को कॉल करता है, तो वे एक id जोड़ रहे हैं, जैसे photo और उसके संबंधित रिज़ॉल्वर, जो सिर्फ एक lambda है जो instance बनाता है और क्लास पर आवश्यक dependencies सेट करता है।

अब, हम IoC क्लास के माध्यम से dependencies को रजिस्टर कर सकते हैं और इस तरह हल कर सकते हैं:

तो, हम यह इस पद्धति के साथ देख सकते हैं, हम मैन्युअल रूप से क्लास को instantiating नहीं कर रहे हैं। इसके बजाय, हम इसे IoC कंटेनर के साथ रजिस्टर करते हैं, और फिर एक विशिष्ट instance के लिए request करते हैं। यह जटिलता को कम कर देता है जिसे हमने पेश किया था, जब हमने क्लास के बाहर hardcoded dependencies को हटा लिया था।

वास्तव में characters की एक ही संख्या, लेकिन, अब, क्लास काफी अधिक लचीली और परीक्षण योग्य है। वास्तविक दुनिया के उपयोग में, आप शायद इस क्लास को एक्सटेंड करना चाहते हैं ताकि singletons का निर्माण भी हो सके।


मैजिक मेथड्स को सम्मलित करें

अगर हम IoC क्लास की लंबाई को भी कम करना चाहते हैं, तो हम मैजिक मेथड्स का लाभ ले सकते हैं - अर्थात् __set() और __get(), जो यूजर को एक ऐसे मेथड को कॉल करता है जो क्लास में मौजूद नहीं है।

Fabien Potencier द्वारा लोकप्रिय, यह एक सुपर-न्यूनतम इम्प्लीमेंटेशन है - लेकिन यह काम करेगा। चाहे __get() या set() रन करें या नहीं यह इस पर निर्भर होगा कि क्या user मान निर्धारित कर रहा है या नहीं।

बेसिक उपयोग होगा:

पढ़ने के लिए धन्यवाद!

Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.