मैं आपके अंकों के माध्यम से संख्यात्मक रूप से जाऊंगा, लेकिन सबसे पहले, कुछ ऐसा है, जिस पर आपको बहुत सावधान रहना चाहिए: इस बात की पुष्टि न करें कि एक पुस्तकालय का उपयोग कैसे किया जाता है, इसके साथ एक उपभोक्ता कैसे पुस्तकालय का उपयोग करता है । इसके अच्छे उदाहरण हैं Entity Framework (जिसे आप स्वयं एक अच्छी लाइब्रेरी के रूप में उद्धृत करते हैं) और ASP.NET के MVC हैं। ये दोनों हुड के नीचे एक भयानक बहुत कुछ करते हैं, उदाहरण के लिए, प्रतिबिंब, जो बिल्कुल अच्छा डिजाइन नहीं माना जाएगा यदि आप इसे दिन-प्रतिदिन के कोड के माध्यम से फैलाते हैं।
इन पुस्तकालयों बिल्कुल हैं नहीं "पारदर्शी" वे कैसे काम में, या क्या वे परदे के पीछे कर रहे हैं। लेकिन यह एक बाधा नहीं है, क्योंकि वे अपने उपभोक्ताओं में अच्छे प्रोग्रामिंग सिद्धांतों का समर्थन करते हैं । इसलिए जब भी आप इस तरह की लाइब्रेरी के बारे में बात करते हैं, तो याद रखें कि एक लाइब्रेरी के उपभोक्ता के रूप में, इसके कार्यान्वयन या रखरखाव के बारे में चिंता करना आपका काम नहीं है। आपको केवल इस बारे में चिंता करनी चाहिए कि यह आपके द्वारा लिखे गए कोड को कैसे मदद करता है या उसमें बाधा डालता है जो लाइब्रेरी का उपयोग करता है। इन अवधारणाओं को भ्रमित न करें!
तो, बिंदु से गुजरने के लिए:
तुरंत हम उस तक पहुंचते हैं जो मैं केवल मान सकता हूं कि ऊपर का एक उदाहरण है। आप कहते हैं कि आईओसी कंटेनर स्थैतिक के रूप में सबसे अधिक निर्भरता स्थापित करते हैं। खैर, शायद वे कैसे काम करते हैं, इसके कुछ कार्यान्वयन विवरण में स्थिर भंडारण शामिल है (हालांकि यह देखते हुए कि वे एक वस्तु का एक उदाहरण है जैसे कि निनजे का IKernel
उनके मुख्य भंडारण के रूप में, मुझे संदेह है कि)। लेकिन यह आपकी चिंता नहीं है!
वास्तव में, IoC कंटेनर गरीब आदमी की निर्भरता इंजेक्शन के रूप में गुंजाइश के साथ स्पष्ट है। (मैं IoC कंटेनरों की तुलना गरीब आदमी के DI से करने जा रहा हूं क्योंकि उनकी तुलना किसी भी DI से नहीं करना अनुचित और भ्रमित करने वाला होगा। और, स्पष्ट होने के लिए, मैं "गरीब आदमी का DI" एक सहकर्मी के रूप में उपयोग नहीं कर रहा हूं।)
गरीब आदमी के डीआई में, आप मैन्युअल रूप से एक निर्भरता को रोक देंगे, फिर उसे उस वर्ग में इंजेक्ट करें जिसे इसकी आवश्यकता है। उस बिंदु पर जहां आप निर्भरता का निर्माण करते हैं, आप यह चुनेंगे कि इसके साथ क्या करना है- इसे स्थानीय रूप से स्कोप किए गए वैरिएबल में स्टोर करें, एक क्लास वैरिएबल, एक स्टैटिक वैरिएबल, इसे बिल्कुल भी स्टोर न करें, जो भी हो। आप कई वर्गों में एक ही उदाहरण दे सकते हैं, या आप प्रत्येक वर्ग के लिए एक नया बना सकते हैं। जो कुछ। बिंदु यह है कि जो हो रहा है उसे देखने के लिए, आप बिंदु को देखते हैं- शायद एप्लिकेशन रूट के पास- जहां निर्भरता बनाई जाती है।
अब एक IoC कंटेनर के बारे में क्या? ठीक है, आप बिल्कुल वैसा ही करते हैं! फिर, Ninject शब्दावली से जा रहा है, तुम कहाँ बंधन की स्थापना की है को देखो, और लगता है कि क्या यह कहते हैं कुछ की तरह InTransientScope
, InSingletonScope
, या जो कुछ भी। यदि ऐसा कुछ भी संभावित रूप से स्पष्ट है, क्योंकि आपके पास अपना दायरा घोषित करने का अधिकार है, बजाय इसके कि किसी वस्तु का क्या होता है, उस पर नज़र रखने के लिए एक विधि के माध्यम से देखा जाए (किसी वस्तु को किसी खंड में खिसकाया जा सकता है, लेकिन क्या इसमें कई बार उपयोग किया जाता है ब्लॉक या सिर्फ एक बार, उदाहरण के लिए)। इसलिए हो सकता है कि आप गुंजाइश को निर्धारित करने के लिए कच्ची भाषा की सुविधा के बजाय IoC कंटेनर पर एक सुविधा का उपयोग करने के विचार से निरस्त हों, लेकिन जब तक आप अपने IoC पुस्तकालय पर भरोसा करते हैं- जो आपको चाहिए! - इसका कोई वास्तविक नुकसान नहीं है! ।
मुझे अभी भी नहीं पता कि आप यहाँ क्या बात कर रहे हैं। क्या आईओसी कंटेनर अपने आंतरिक कार्यान्वयन के हिस्से के रूप में निजी गुणों को देखते हैं? मुझे नहीं पता कि वे क्यों करेंगे, लेकिन फिर से, अगर वे करते हैं, तो यह आपकी चिंता नहीं है कि आप जिस लाइब्रेरी का उपयोग कर रहे हैं वह कैसे लागू किया जाता है।
या, हो सकता है, वे निजी वासियों में इंजेक्शन लगाने जैसी क्षमता को उजागर करते हों? ईमानदारी से, मैंने कभी भी इसका सामना नहीं किया है, और मुझे इस बारे में संदेह है कि क्या यह वास्तव में एक सामान्य विशेषता है। लेकिन यहां तक कि अगर यह वहां है, तो यह एक उपकरण का सरल मामला है जिसका दुरुपयोग किया जा सकता है। याद रखें, यहां तक कि एक IoC कंटेनर के बिना, यह एक निजी संपत्ति का उपयोग करने और संशोधित करने के लिए प्रतिबिंब कोड की कुछ पंक्तियां हैं। यह कुछ ऐसा है जो आपको लगभग कभी नहीं करना चाहिए, लेकिन इसका मतलब यह नहीं है कि क्षमता को उजागर करने के लिए .NET बुरा है। यदि कोई स्पष्ट रूप से और बेतहाशा किसी उपकरण का दुरुपयोग करता है, तो यह व्यक्ति की गलती है, उपकरण की नहीं।
यहाँ अंतिम बिंदु 2 के समान है। अधिकांश समय, IoC कंटेनर कंस्ट्रक्टर का उपयोग करते हैं! सेटर इंजेक्शन बहुत विशिष्ट परिस्थितियों के लिए पेश किया जाता है, जहां विशेष कारणों से, कंस्ट्रक्टर इंजेक्शन का उपयोग नहीं किया जा सकता है। कोई भी व्यक्ति जो इस बात को कवर करने के लिए हर समय सेटर इंजेक्शन का उपयोग करता है कि कितनी निर्भरताएं बीत रही हैं, बड़े पैमाने पर उपकरण को समाप्त कर रहा है। यह उपकरण की गलती नहीं है, यह उनका है।
अब, अगर यह मासूमियत से बनाने के लिए वास्तव में आसान गलती थी, और एक कि आईओसी कंटेनर प्रोत्साहित करते हैं, तो ठीक है, शायद आपके पास एक बिंदु होगा। यह मेरी कक्षा के प्रत्येक सदस्य को सार्वजनिक करने और फिर अन्य लोगों को दोषी ठहराने जैसा होगा जब वे उन चीजों को संशोधित करते हैं जो उन्हें सही नहीं चाहिए? लेकिन जो कोई भी एसआरपी के उल्लंघन को कवर करने के लिए सेटर इंजेक्शन का उपयोग करता है, वह या तो मूल डिजाइन सिद्धांतों की अनदेखी या पूरी तरह से अनभिज्ञ है। IoC कंटेनर में इसके लिए दोष देना अनुचित है।
यह विशेष रूप से सच है क्योंकि यह कुछ ऐसा है जिसे आप गरीब आदमी के डीआई के साथ आसानी से कर सकते हैं:
var myObject
= new MyTerriblyLargeObject { DependencyA = new Thing(), DependencyB = new Widget(), Dependency C = new Repository(), ... };
तो वास्तव में, यह चिंता पूरी तरह से orthogonal लगती है कि क्या IoC कंटेनर का उपयोग किया जाता है या नहीं।
यह बदलना कि आपकी कक्षाएं एक साथ कैसे काम करती हैं, ओसीपी का उल्लंघन नहीं है। यदि ऐसा होता है, तो सभी निर्भरता उलटा ओसीपी के उल्लंघन को प्रोत्साहित करेंगे। अगर ऐसा होता, तो वे दोनों एक ही SOLID में नहीं होते!
इसके अलावा, न तो अंक a) और न ही b) OCP के साथ कुछ भी करने के करीब आते हैं। मैं यह भी नहीं जानता कि OCP के संबंध में इनका कैसे उत्तर दिया जाए।
केवल एक चीज जो मैं अनुमान लगा सकता हूं कि आपको लगता है कि ओसीपी को रनटाइम में परिवर्तन नहीं किए जाने के साथ व्यवहार करना है, या कोड में निर्भरता के जीवनचक्र को कहां से नियंत्रित किया जाता है। यह। आवश्यकताओं को जोड़ने या बदलने पर OCP मौजूदा कोड को संशोधित नहीं करने वाला है। यह सब कोड लिखने के बारे में है , न कि आपके द्वारा पहले से लिखे गए कोड को एक साथ कैसे चिपकाया जाता है (हालांकि, निश्चित रूप से, ढीली युग्मन ओसीपी प्राप्त करने का एक महत्वपूर्ण हिस्सा है)।
और एक अंतिम बात जो आप कहते हैं:
लेकिन मैं उसी विश्वास को तीसरे पक्ष के उपकरण में नहीं डाल सकता जो कि मेरे द्वारा मैन्युअल रूप से करने में सक्षम नहीं होने वाली चीजों के लिए कार्य करने के लिए मेरे संकलित कोड को बदल रहा है।
हाँ, आप कर सकते हैं । आपके पास यह सोचने का कोई कारण नहीं है कि ये उपकरण- बड़ी संख्या में परियोजनाओं पर निर्भर हैं- किसी भी अन्य तृतीय-पक्ष पुस्तकालय की तुलना में किसी भी अधिक छोटी गाड़ी या अप्रत्याशित व्यवहार की संभावना है।
परिशिष्ट
मैंने अभी देखा कि आपके इंट्रो पैराग्राफ कुछ एड्रेसिंग का भी इस्तेमाल कर सकते हैं। आप यह कहते हैं कि IoC कंटेनर कुछ गुप्त तकनीक का उपयोग नहीं कर रहे हैं जो हमने "गन्दा, दोहराव-प्रवण कोड से बचने के लिए निर्भरता ग्राफ बनाने के लिए कभी नहीं सुना है।" और आप काफी सही हैं, वे जो कर रहे हैं, वास्तव में इन चीजों को उसी मूल तकनीकों से संबोधित कर रहे हैं जैसा कि हम हमेशा करते हैं।
मुझे एक काल्पनिक परिदृश्य के माध्यम से बात करने दो। आप एक प्रोग्रामर के रूप में, एक बड़े एप्लिकेशन को एक साथ रखते हैं, और एंट्री पॉइंट पर, जहाँ आप अपना ऑब्जेक्ट ग्राफ बना रहे हैं, आपको लगता है कि आपके पास काफी गन्दा कोड है। काफी कुछ कक्षाएं हैं जो बार-बार उपयोग की जाती हैं, और हर बार जब आप उनमें से एक का निर्माण करते हैं तो आपको उनके तहत फिर से निर्भरता की पूरी श्रृंखला का निर्माण करना होगा। साथ ही आप पाते हैं कि आपके पास निर्भरता के जीवनचक्र को घोषित करने या नियंत्रित करने का कोई भी स्पष्ट तरीका नहीं है, सिवाय प्रत्येक के लिए कस्टम कोड के। आपका कोड असंरचित है और पुनरावृत्ति से भरा है। यह वह गड़बड़ है जिसके बारे में आप अपने इंट्रो पैराग्राफ में बात करते हैं।
तो सबसे पहले, आप थोड़ा रिफ्लेक्टर करना शुरू करते हैं- जहाँ कुछ दोहराया हुआ कोड संरचित होता है, आप इसे सहायक विधियों में खींचते हैं, और इसी तरह। लेकिन फिर आप सोचना शुरू करते हैं- क्या यह एक समस्या है जिसे मैं शायद सामान्य अर्थों में निपटा सकता हूं , एक यह जो इस विशेष परियोजना के लिए विशिष्ट नहीं है लेकिन आपकी भविष्य की सभी परियोजनाओं में आपकी मदद कर सकती है?
इसलिए आप बैठें, और इसके बारे में सोचें, और तय करें कि एक वर्ग होना चाहिए जो निर्भरता को हल कर सके। और आपको पता चलता है कि किन सार्वजनिक तरीकों की आवश्यकता होगी:
void Bind(Type interfaceType, Type concreteType, bool singleton);
T Resolve<T>();
Bind
कहते हैं, "जहां आपको एक प्रकार का एक निर्माता तर्क दिखाई देता है interfaceType
, एक उदाहरण में पास करें concreteType
"। अतिरिक्त singleton
पैरामीटर कहता है कि क्या concreteType
हर बार एक ही उदाहरण का उपयोग करना है , या हमेशा एक नया बनाना है।
Resolve
बस T
किसी भी निर्माता के साथ निर्माण करने की कोशिश करेंगे यह पा सकते हैं जिनके तर्क सभी प्रकार के हैं जो पहले से बाध्य हैं। यह सभी तरह से निर्भरता को हल करने के लिए खुद को पुनरावर्ती भी कह सकता है। यदि यह एक उदाहरण को हल नहीं कर सकता है क्योंकि सब कुछ बाध्य नहीं है, यह एक अपवाद फेंकता है।
आप इसे स्वयं लागू करने का प्रयास कर सकते हैं, और आप पाएंगे कि आपको थोड़ा प्रतिबिंब की आवश्यकता है, और बाइंडिंग के लिए कुछ कैशिंग जहां singleton
सत्य है, लेकिन निश्चित रूप से कठोर या भयानक कुछ भी नहीं है। और एक बार जब आप कर रहे हैं- voila , आप अपने खुद के IoC कंटेनर का मूल है! क्या यह वास्तव में डरावना है? इस और निनजेक्ट या स्ट्रक्च्योर मैप या कैसल विंडसर या जो कुछ भी आप पसंद करते हैं, के बीच एकमात्र वास्तविक अंतर यह है कि उन लोगों को कवर करने के लिए बहुत अधिक कार्यक्षमता है (कई!) उन मामलों का उपयोग करते हैं जहां यह मूल संस्करण पर्याप्त नहीं होगा। लेकिन इसके दिल में, आपके पास एक IoC कंटेनर का सार है।
IOC
औरExplicitness of code
बिल्कुल वही चीज है जिसके साथ मुझे समस्या है। मैनुअल डीआई आसानी से एक घर का काम बन सकता है, लेकिन यह कम से कम एक स्थान पर स्वनिर्धारित स्पष्ट कार्यक्रम प्रवाह डालता है - "आप जो देखते हैं, आप देखते हैं कि आपको क्या मिलता है"। जबकि आईओसी के कंटेनरों की बाइंडिंग और घोषणाएं आसानी से अपने आप में एक छिपी हुई समानांतर कार्यक्रम बन सकती हैं।