मुझे सीधे DI कोड के विपरीत IoC कंटेनर की आवश्यकता क्यों है? [बन्द है]


598

मैं थोड़ी देर के लिए डिपेंडेंसी इंजेक्शन (DI) का उपयोग कर रहा हूं , या तो कंस्ट्रक्टर, प्रॉपर्टी या विधि में इंजेक्ट कर रहा हूं । मैंने कभी भी नियंत्रण के उलट (IoC) कंटेनर का उपयोग करने की आवश्यकता महसूस नहीं की है । हालांकि, जितना अधिक मैं पढ़ता हूं, उतना अधिक दबाव मुझे समुदाय से आईओसी कंटेनर का उपयोग करने के लिए महसूस होता है।

मैंने स्ट्रक्चर कंटेनर , एनइजेक्ट , यूनिटी और फंक जैसे .NET कंटेनरों के साथ खेला । मैं अभी भी यह देखने में विफल रहता हूं कि आईओसी कंटेनर मेरे कोड को कैसे लाभ / सुधार करने जा रहा है।

मैं काम पर एक कंटेनर का उपयोग शुरू करने से भी डरता हूं क्योंकि मेरे कई सहकर्मी कोड देखेंगे जो उन्हें समझ में नहीं आते हैं। उनमें से कई नई तकनीक सीखने के लिए अनिच्छुक हो सकते हैं।

कृपया, मुझे आश्वस्त करें कि मुझे आईओसी कंटेनर का उपयोग करने की आवश्यकता है। जब मैं काम पर अपने साथी डेवलपर्स से बात करता हूं तो मैं इन तर्कों का उपयोग करने जा रहा हूं।


6
अच्छा प्रश्न। मैं टिप्पणियों में इसका जवाब दे रहा हूं क्योंकि मैं आईओसी के विचार के लिए बहुत नया हूं। यह प्लग एंड प्ले घटकों और ढीले युग्मन के विचार जैसा दिखता है। क्या आपको वर्तमान एक के स्थान पर कुछ अन्य घटक का उपयोग करने की आवश्यकता होगी, आवश्यकता आधारित है। आईओसी का उपयोग इस तरह के बदलाव के लिए कोड तैयार करना है, अगर यह आईएमओ उठता है।
१०

3
@ शशाकलेश लेकिन मैं साधारण डीआई के साथ ढीली कपलिंग हासिल कर सकता हूं। हालाँकि, यदि मैं कॉन्फ़िगरेशन फ़ाइल का उपयोग करता हूं तो मुझे आपकी बात दिखाई देती है। हालाँकि, मुझे यकीन नहीं है कि मुझे कॉन्फ़िगरेशन फ़ाइल का उपयोग करना पसंद है। कॉन्फिग फाइल्स बहुत ही वर्बोज़ हैं, रीफ़ैक्टरिंग के साथ कठिनाइयाँ, और कई फाइलों के बीच स्विच करना।
वादिम

110
सिर्फ एक टिप्पणी जोड़ने के बाद से ऐसा लगता है कि आप मुख्य रूप से आईओसी का उपयोग करने के कारणों की तलाश कर रहे हैं; लेकिन आपके मुद्दे के बारे में कुछ और कहा जाना चाहिए। आप अपने कोड को अपनी टीम के सबसे बुरे व्यक्ति के स्तर पर या इस डर से नहीं लिख सकते कि वे सीखना चाहते हैं। आपके पास एक पेशेवर होने के लिए ही नहीं बल्कि आपके भविष्य को भी विकसित करने की जिम्मेदारी है और आपकी टीम को आपको वापस नहीं रखना चाहिए।
केविन शेफील्ड

4
@ केविन, वास्तव में हम IoC का उपयोग कर रहे हैं। आईओसी के बारे में सभी को पढ़ाना उतना कठिन नहीं था।
वादिम

21
मुझे पता नहीं क्यों मध्यस्थों ने बड़े पैमाने पर उत्थान और उपयोगी प्रश्नों को बंद कर दिया है। शायद इस मामले में, इस सवाल को समझ नहीं पाएंगे, या वह यह नहीं समझते हैं कि लोग स्टैकएक्सचेंज के लिए क्या उपयोग करते हैं? यदि यह "स्टेक्सएक्सचेंज के प्रश्नोत्तर प्रारूप के लिए एक अच्छा फिट नहीं है" तो शायद इस बात पर विचार करें कि आपकी नीति गलत है और इन सैकड़ों उपयोगी प्रश्नों के साथ सैकड़ों अप-वोट और अप-वोट वाले उपयोगी उत्तर नहीं हैं।
NickG

जवाबों:


441

वाह, विश्वास नहीं हो सकता है कि जोएल इसका समर्थन करेगा:

var svc = new ShippingService(new ProductLocator(), 
   new PricingService(), new InventoryService(), 
   new TrackingRepository(new ConfigProvider()), 
   new Logger(new EmailLogger(new ConfigProvider())));

इस पर:

var svc = IoC.Resolve<IShippingService>();

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

IoC कंटेनर जटिल हो सकते हैं, हाँ। लेकिन इस सरल मामले के लिए मैंने दिखाया है कि यह अविश्वसनीय रूप से आसान है।


ठीक है, चलिए इसे और भी सही ठहराते हैं। मान लें कि आपके पास कुछ इकाइयाँ या मॉडल ऑब्जेक्ट हैं जिन्हें आप स्मार्ट UI से बाँधना चाहते हैं। यह स्मार्ट UI (हम इसे Sh Shorm Morms कहेंगे) चाहता है कि आप INotifyPropertyChanged को कार्यान्वित करें ताकि यह ट्रैकिंग को बदल सके और तदनुसार UI अपडेट कर सके।

"ठीक है, यह इतना कठिन ध्वनि नहीं है" इसलिए आप लिखना शुरू करते हैं।

आप इसकी शुरुआत करें:

public class Customer
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime CustomerSince { get; set; }
    public string Status { get; set; }
}

.. और इस के साथ अंत :

public class UglyCustomer : INotifyPropertyChanged
{
    private string _firstName;
    public string FirstName
    {
        get { return _firstName; }
        set
        {
            string oldValue = _firstName;
            _firstName = value;
            if(oldValue != value)
                OnPropertyChanged("FirstName");
        }
    }

    private string _lastName;
    public string LastName
    {
        get { return _lastName; }
        set
        {
            string oldValue = _lastName;
            _lastName = value;
            if(oldValue != value)
                OnPropertyChanged("LastName");
        }
    }

    private DateTime _customerSince;
    public DateTime CustomerSince
    {
        get { return _customerSince; }
        set
        {
            DateTime oldValue = _customerSince;
            _customerSince = value;
            if(oldValue != value)
                OnPropertyChanged("CustomerSince");
        }
    }

    private string _status;
    public string Status
    {
        get { return _status; }
        set
        {
            string oldValue = _status;
            _status = value;
            if(oldValue != value)
                OnPropertyChanged("Status");
        }
    }

    protected virtual void OnPropertyChanged(string property)
    {
        var propertyChanged = PropertyChanged;

        if(propertyChanged != null)
            propertyChanged(this, new PropertyChangedEventArgs(property));
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

यह नलसाजी कोड घृणित है, और मैं यह बनाए रखता हूं कि यदि आप उस तरह से कोड लिख रहे हैं तो आप अपने ग्राहक से चोरी कर रहे हैं । काम करने के बेहतर, बेहतर तरीके हैं।

कभी उस शब्द को सुनें, अधिक कठिन नहीं?

अच्छी तरह से कल्पना कीजिए कि आपकी टीम में कुछ स्मार्ट आदमी आए और कहा: "यहाँ एक आसान तरीका है"

यदि आप अपने गुणों को आभासी बनाते हैं (शांत हो जाते हैं, तो यह सौदा का उतना बड़ा नहीं है) तो हम स्वचालित रूप से उस संपत्ति व्यवहार में बुनाई कर सकते हैं। (इसे AOP कहा जाता है, लेकिन नाम की चिंता न करें, इस पर ध्यान केंद्रित करें कि यह आपके लिए क्या करने जा रहा है)

इस बात पर निर्भर करता है कि आप किस IoC टूल का उपयोग कर रहे हैं, आप कुछ ऐसा कर सकते हैं जो इस तरह दिखता है:

var bindingFriendlyInstance = IoC.Resolve<Customer>(new NotifyPropertyChangedWrapper());

Poof! प्रश्न में ऑब्जेक्ट के प्रत्येक वर्चुअल प्रॉपर्टी सेटर पर मैन्युअल रूप से INotifyPropertyChanged BS के सभी अब स्वचालित रूप से आपके लिए उत्पन्न होते हैं।

क्या यह जादू है? हाँ ! यदि आप इस तथ्य पर भरोसा कर सकते हैं कि यह कोड अपना काम करता है, तो आप मुंबो-जंबो को लपेटकर उस संपत्ति को सुरक्षित रूप से छोड़ सकते हैं। आपको हल करने के लिए व्यावसायिक समस्याएं हैं।

AOP करने के लिए एक IoC उपकरण के कुछ अन्य रोचक उपयोग:

  • घोषणात्मक और नेस्टेड डेटाबेस लेनदेन
  • घोषणा और काम की नेस्टेड इकाई
  • लॉगिंग
  • पूर्व / पोस्ट की स्थिति (अनुबंध द्वारा डिजाइन)

28
ओह, आप सभी गुणों को आभासी बनाना भूल गए, और यह काम नहीं किया। क्या आपको अपने ग्राहक से भी इस डीबगिंग को खर्च करने की आवश्यकता है? (माफी अगर आप डायनामिकप्रॉक्सी का उपयोग नहीं कर रहे हैं ।: पी)
Thom

17
आप INotifyPropertyChanged आवरण का उपयोग करके स्पष्टता का एक बहुत बलिदान करते हैं। यदि आपको उस प्लंबिंग को लिखने में कुछ मिनट से अधिक समय लगता है तो आप गलत व्यवसाय में हैं। जब आपके कोड की वाचालता की बात आती है तो कम नहीं है!
ओवरस्टूड

39
@overstood - मैं पूरी तरह से असहमत हूं। पहला, इस उदाहरण में स्पष्टता कहाँ है? उपभोक्ता के पास। उपभोक्ता स्पष्ट रूप से INotifyPropertyChanged के लिए पूछ रहा है। सिर्फ इसलिए कि हम इस प्रकार का कोड माइक्रो या मैक्रो कोड जनरेशन के साथ बना सकते हैं, इसका मतलब यह नहीं है कि इसे लिखना अच्छा होगा। कि INotifyPropertyChanged gunk सिर्फ रटे, सांसारिक, प्लंबिंग है और वास्तव में प्रश्न में कक्षा की पठनीयता से अलग हो जाता है।
बेन शेहरमैन 20

31
नीचे चिह्नित किया गया है क्योंकि आप निर्भरता इंजेक्शन पैटर्न और सेवा लोकेटर पैटर्न को भ्रमित कर रहे हैं। पूर्व का मतलब बाद के बजाय इस्तेमाल किया जाना है। उदाहरण के लिए, एक वस्तु (या वास्तव में संपूर्ण प्रणाली) को IShippingService का एक उदाहरण प्राप्त करने के लिए कभी भी हल (...) नहीं करना चाहिए। जिन वस्तुओं को IShippingService की आवश्यकता होती है, उन्हें उस उदाहरण का संदर्भ प्राप्त करना चाहिए जिसका निर्माण करते समय उन्हें उपयोग करना चाहिए, और दो वस्तुओं को एक साथ जोड़ने के लिए कुछ उच्च परत जिम्मेदार है।
नेट

30
यह जो कुछ भी है (IoC, डायनेमिकप्रॉक्सी, एओपी या काला जादू ) क्या कोई मुझे फ्रेमवर्क में एक ठोस लेख / विशिष्ट प्रलेखन से जोड़ सकता है जो इसे प्राप्त करने के लिए अधिक विवरण प्रदान करता है?
फॉस्टंडी

138

मैं तुम्हारे साथ हूं, वादिम। IoC कंटेनर एक सरल, सुरुचिपूर्ण और उपयोगी अवधारणा लेते हैं, और इसे 200 दिनों के मैनुअल के साथ दो दिनों के लिए अध्ययन करना पड़ता है।

मैं व्यक्तिगत रूप से इस बात से हैरान हूं कि IoC समुदाय ने मार्टिन फॉलर द्वारा एक सुंदर, सुरुचिपूर्ण लेख को कैसे लिया और इसे आम तौर पर 200-300 पेज के मैनुअल के साथ जटिल रूपरेखाओं के एक समूह में बदल दिया।

मैं निर्णय (HAHA!) नहीं होने की कोशिश करता हूं, लेकिन मुझे लगता है कि जो लोग आईओसी कंटेनर का उपयोग करते हैं, वे (ए) बहुत स्मार्ट हैं और (बी) उन लोगों के लिए सहानुभूति की कमी है जो उतने स्मार्ट नहीं हैं। सब कुछ उनके लिए बिल्कुल सही समझ में आता है, इसलिए उन्हें यह समझने में परेशानी होती है कि कई साधारण प्रोग्रामर अवधारणाओं को भ्रमित कर देंगे। यह ज्ञान का अभिशाप है । आईओसी कंटेनर को समझने वाले लोगों को यह विश्वास करने में परेशानी होती है कि ऐसे लोग हैं जो इसे नहीं समझते हैं।

IoC कंटेनर का उपयोग करने का सबसे मूल्यवान लाभ यह है कि आप एक कॉन्फ़िगरेशन स्विच को एक स्थान पर रख सकते हैं, जो आपको, मोड और प्रोडक्शन मोड के बीच में बदलाव करने देता है। उदाहरण के लिए, मान लीजिए कि आपके डेटाबेस एक्सेस क्लासेस के दो संस्करण हैं ... एक संस्करण जिसने आक्रामक रूप से लॉग इन किया और बहुत अधिक सत्यापन किया, जिसे आपने विकास के दौरान उपयोग किया था, और लॉगिंग या सत्यापन के बिना एक और संस्करण जो उत्पादन के लिए चिल्ला रहा था। उनके बीच एक स्थान पर स्विच करने में सक्षम होना अच्छा है। दूसरी ओर, यह एक काफी तुच्छ समस्या है जो आईओसी कंटेनरों की जटिलता के बिना सरल तरीके से आसानी से निपट जाती है।

मेरा मानना ​​है कि यदि आप IoC कंटेनरों का उपयोग करते हैं, तो आपका कोड स्पष्ट रूप से, पढ़ने के लिए बहुत कठिन हो जाता है। यह देखने के लिए कि आपको कोड क्या करने की कोशिश कर रहा है, कम से कम एक जगह पर देखने के लिए आपको कितनी जगहों पर देखना होगा। और कहीं स्वर्ग में एक देवदूत रोता है।


81
मुझे लगता है कि आप अपने तथ्यों को थोड़ा जोएल मिलाया है। IoC और कंटेनर पहले आए, फिर मार्टिन द्वारा ग्रंथ आया, न कि इसके विपरीत।
ग्लेन ब्लॉक

55
ईश अधिकांश कंटेनर आपको बहुत जल्दी जाने देते हैं। ऑटोफाक, संरचना मानचित्र, एकता, निनजेक्ट, आदि के साथ आपको कंटेनर को लगभग 5 मिनट में काम करने में सक्षम होना चाहिए। हाँ, उनके पास उन्नत सुविधाएँ हैं, लेकिन आपको उन लोगों से दूर रहने की आवश्यकता नहीं है।
ग्लेन ब्लॉक

58
जोएल मैं भी तुम्हारे जैसा ही सोचता था। फिर मैंने शाब्दिक रूप से और पांच मिनट बिताए यह पता लगाने के लिए कि सबसे बुनियादी सेटअप कैसे चल रहा है और 80/20 नियम में आश्चर्यचकित था। यह विशेष रूप से सरल मामलों में कोड को अधिक स्वच्छ बनाता है।
जस्टिन बोजोनियर

55
मैं दो साल से कम समय से प्रोग्रामिंग कर रहा हूं और मैंने निनॉज विकी को पढ़ा और उसे प्राप्त किया। मैं तब से कई जगहों पर डीआई का उपयोग कर रहा हूं। क्या तुमने देखा? दो साल से कम और विकी पर कुछ पेज पढ़ना। मैं एक जादूगर या कुछ भी नहीं हूँ। मैं खुद को जीनियस नहीं मानता, लेकिन मेरे लिए इसे समझना आसान था। मैं किसी ऐसे व्यक्ति की कल्पना नहीं कर सकता जो वास्तव में समझता है कि ओओ इसे समझ नहीं पा रहा है। इसके अलावा, आप किस 200-300 पेज मैनुअल का जिक्र कर रहे हैं? मैंने उन लोगों को कभी नहीं देखा। सभी IoC कंटेनरों का मैंने उपयोग किया है और यह बहुत ही कम है।
जेआर गार्सिया

35
+1 अच्छी तरह से लिखा और सोचा गया। एक बात जो मुझे लगता है कि बहुत से लोग महसूस नहीं करते हैं कि एक फ्रेमवर्क या "जादुई रूप से" कुछ को जोड़ने से स्वचालित रूप से एक सिस्टम में जटिलता और सीमाएं जुड़ जाती हैं। कभी-कभी यह इसके लायक है, लेकिन अक्सर कुछ अनदेखी हो जाती है और सीमाओं में प्रवेश करने वाली समस्या को ठीक करने की कोशिश में कोड में जारी किया जाता है। इससे सामने आने वाले समय की बचत हो सकती है, लेकिन लोगों को यह महसूस करना होगा कि कुछ अस्पष्ट समस्या को ठीक करने की कोशिश में लाइन में 100 गुना खर्च हो सकता है, केवल कुछ मुट्ठी भर लोगों को वास्तव में हल करने के लिए पर्याप्त ज्ञान है।
kemiller2002

37

संभवतः कोई भी आपको DI कंटेनर ढांचे का उपयोग करने के लिए मजबूर नहीं कर रहा है। आप पहले से ही अपनी कक्षाओं को कम करने और परीक्षण क्षमता में सुधार करने के लिए DI का उपयोग कर रहे हैं, इसलिए आपको कई लाभ मिल रहे हैं। संक्षेप में, आप सादगी के पक्ष में हैं, जो आमतौर पर एक अच्छी बात है।

यदि आपका सिस्टम जटिलता के एक स्तर पर पहुंच जाता है, जहां मैनुअल DI एक कोर (यानी रखरखाव बढ़ाता है) हो जाता है, तो उसे एक डीआई कंटेनर फ्रेमवर्क की टीम लर्निंग कर्व के खिलाफ तौलें।

यदि आपको निर्भरता आजीवन प्रबंधन पर अधिक नियंत्रण की आवश्यकता है (यदि आप सिंगलटन पैटर्न को लागू करने की आवश्यकता महसूस करते हैं), तो डीआई कंटेनरों को देखें।

यदि आप DI कंटेनर का उपयोग करते हैं, तो केवल उन विशेषताओं का उपयोग करें जिनकी आपको आवश्यकता है। XML कॉन्फ़िगरेशन फ़ाइल को छोड़ दें और यदि यह पर्याप्त है तो इसे कोड में कॉन्फ़िगर करें। स्टिक टू कंस्ट्रक्टर इंजेक्शन। एकता या संरचना की मूल बातें कुछ पृष्ठों तक सीमित की जा सकती हैं।

इस पर मार्क सीमन द्वारा एक महान ब्लॉग पोस्ट है: जब एक डिब कंटेनर का उपयोग करना है


बहुत अच्छी प्रतिक्रिया। केवल एक चीज जिस पर मेरी राय अलग है, वह यह है कि मैनुअल इंजेक्शन कभी नहीं या कम जटिल माना जा सकता है या नहीं।
वीकेम्पफ

+1। सबसे अच्छे उत्तरों में से एक यहाँ। ब्लॉग लेख लिंक के लिए भी धन्यवाद।
stakx - अब

1
संतुलित दृष्टिकोण के लिए +1। IoC कंटेनर हमेशा अच्छे नहीं होते हैं, और वे हमेशा खराब नहीं होते हैं। यदि आपको कोई आवश्यकता नहीं दिखती है, तो इसका उपयोग न करें। बस पता है कि उपकरण वहाँ है यदि आप एक आवश्यकता देखते हैं।
फिल

32

मेरी राय में आईओसी का नंबर एक लाभ आपके निर्भरता के कॉन्फ़िगरेशन को केंद्रीकृत करने की क्षमता है।

यदि आप वर्तमान में निर्भरता इंजेक्शन का उपयोग कर रहे हैं तो आपका कोड इस तरह दिखाई दे सकता है

public class CustomerPresenter
{
  public CustomerPresenter() : this(new CustomerView(), new CustomerService())
  {}

  public CustomerPresenter(ICustomerView view, ICustomerService service)
  {
    // init view/service fields
  }
  // readonly view/service fields
}

यदि आप एक स्थिर IoC वर्ग का उपयोग करते हैं, तो IMHO, अधिक भ्रामक, कॉन्फ़िगरेशन फ़ाइलों के विपरीत, आपके पास ऐसा कुछ हो सकता है:

public class CustomerPresenter
{
  public CustomerPresenter() : this(IoC.Resolve<ICustomerView>(), IoC.Resolve<ICustomerService>())
  {}

  public CustomerPresenter(ICustomerView view, ICustomerService service)
  {
    // init view/service fields
  }
  // readonly view/service fields
}

तब, आपका स्टेटिक IoC वर्ग इस तरह दिखेगा, मैं यहां यूनिटी का उपयोग कर रहा हूं।

public static IoC
{
   private static readonly IUnityContainer _container;
   static IoC()
   {
     InitializeIoC();
   }

   static void InitializeIoC()
   {
      _container = new UnityContainer();
      _container.RegisterType<ICustomerView, CustomerView>();
      _container.RegisterType<ICustomerService, CustomerService>();
      // all other RegisterTypes and RegisterInstances can go here in one file.
      // one place to change dependencies is good.
   }
}

11
बेन, आप जिस बारे में बात कर रहे हैं वह वास्तव में सेवा स्थान है, न कि निर्भरता इंजेक्शन - एक अंतर है। मैं हमेशा पहले वाले को पसंद करता हूं। stevenharman.net/blog/archive/2009/09/25/…
स्टीवनमैन

23
अपने डिफॉल्ट कंस्ट्रक्टर में IoC.Resolve <T> करने के बजाय, आपको आईओसी कंटेनर की आपके लिए ऑब्जेक्ट का निर्माण करने की क्षमता का लाभ उठाना चाहिए। उस खाली कंस्ट्रक्टर से छुटकारा पाएं, और आईओसी कंटेनर को आपके लिए ऑब्जेक्ट बनाने दें। var प्रस्तुतकर्ता = IoC.Resolve <CustomerPresenter> (); देखा! सभी निर्भरताएँ पहले से ही समाप्त हो गई हैं।
बेन शेहिरमैन 15

12
इस तरह के विन्यास के केंद्रीकरण का डाउन-साइड ज्ञान का डी-संदर्भीकरण है। जोएल ने इस समस्या को यह कहते हुए इंगित किया, "कोड बन जाता है, स्पष्ट रूप से, पढ़ने में बहुत कठिन"।
स्कॉट बेलवेयर

6
@ घंटी, क्या ज्ञान? एक व्यावहारिक निर्भरता के रूप में लिया जा रहा इंटरफ़ेस एक अनुबंध के रूप में कार्य करता है और यह उद्देश्य और व्यवहार दोनों को बताने के लिए पर्याप्त होना चाहिए, नहीं? मुझे लगता है कि आप अनुबंध के कार्यान्वयन में spelunking से प्राप्त ज्ञान का उल्लेख कर सकते हैं, जिस स्थिति में आपको उपयुक्त कॉन्फ़िगरेशन को ट्रैक करने की आवश्यकता होगी? मैं एक कंप्यूटर (वी # वी, इंटेलीज, आदि में) पर भरोसा करता हूं, क्योंकि वे एक ग्राफ के नोड्स और किनारों को नेविगेट करने में महान हैं; मैं अपने मस्तिष्क के ढेर को उस कार्य स्थल के संदर्भ के लिए आरक्षित करता हूं जिस पर मैं वर्तमान में केंद्रित हूं।
स्टीवनहरमैन

7
स्टीव, मैं .NET पाठ को जानता हूं और कई वर्षों तक चला। मेरे पास अन्य तरीकों और रूपों के साथ अंतरंग परिचित भी है, और मैं स्पष्ट रूप से समझता हूं कि वास्तविक ट्रेडऑफ़ हैं। मुझे पता है कि उन ट्रेडऑफ़ को कैसे और कब बनाना है, लेकिन मेरे काम जीवन में विविधता कम से कम मुझे जोएल के परिप्रेक्ष्य को समझने में मदद करती है। मुझे उन उपकरणों और ट्रिक्स पर व्याख्यान देने के बजाय जो मैं सबसे अधिक .NET मोनो-कल्चुरिस्ट्स की तुलना में लंबे समय से उपयोग कर रहा हूं, मुझे कुछ बताएं जो मुझे नहीं पता है। मैं alt.net स्टैसिस और रूढ़िवादी के बजाय विविध, महत्वपूर्ण सोच के लिए अपने मस्तिष्क के ढेर को आरक्षित करता हूं।
स्कॉट बेलवेयर

32

आईओसी कंटेनर भी गहरी नेस्टेड क्लास निर्भरता लोड करने के लिए अच्छे हैं। उदाहरण के लिए यदि आपके पास डिपेडेंसी इंजेक्शन का उपयोग करने वाला निम्नलिखित कोड है।

public void GetPresenter()
{
    var presenter = new CustomerPresenter(new CustomerService(new CustomerRepository(new DB())));
}

class CustomerPresenter
{
    private readonly ICustomerService service;
    public CustomerPresenter(ICustomerService service)
    {
        this.service = service;
    }
}

class CustomerService
{
    private readonly IRespository<Customer> repository;
    public CustomerService(IRespository<Customer> repository)
    {
        this.repository = repository;
    }
}

class CustomerRepository : IRespository<Customer>
{
    private readonly DB db;
    public CustomerRepository(DB db)
    {
        this.db = db;
    }
}

class DB { }

यदि आपके पास इन सभी निर्भरताओं में लोड किया गया था और IoC कंटेनर आप ग्राहक सेवा को हल कर सकते हैं और सभी बच्चे की निर्भरता स्वचालित रूप से हल हो जाएगी।

उदाहरण के लिए:

public static IoC
{
   private IUnityContainer _container;
   static IoC()
   {
       InitializeIoC();
   }

   static void InitializeIoC()
   {
      _container = new UnityContainer();
      _container.RegisterType<ICustomerService, CustomerService>();
      _container.RegisterType<IRepository<Customer>, CustomerRepository>();
   }

   static T Resolve<T>()
   {
      return _container.Resolve<T>();
   }
}

public void GetPresenter()
{
   var presenter = IoC.Resolve<CustomerPresenter>();
   // presenter is loaded and all of its nested child dependencies 
   // are automatically injected
   // -
   // Also, note that only the Interfaces need to be registered
   // the concrete types like DB and CustomerPresenter will automatically 
   // resolve.
}

लेकिन IoC क्लास को सर्विस लोकेटर एंटी-पैटर्न का उपयोग करना कहा जाता है। कंस्ट्रक्टर T का उपयोग करने के बजाय कंस्ट्रक्टर DI का उपयोग करके पास किया जाना चाहिए?
माइकल फ्रीजिम

@bendewey आपके उदाहरण का तात्पर्य है कि यह नए ग्राहकसेवा और नए ग्राहक सेवा के लिए निर्माणकर्ताओं के तर्क में स्वचालित रूप से पास हो जाता है। यह कैसे काम करता है? क्या होगा यदि आपके पास अन्य अतिरिक्त पैरामीटर भी हैं?
ब्रेन 2000

28

मैं घोषणात्मक प्रोग्रामिंग का प्रशंसक हूं (कितने SQL प्रश्नों का उत्तर देता हूं) पर देखो, लेकिन मैंने जिन Io कंटेनरों को देखा है वे अपने स्वयं के अच्छे के लिए बहुत ही रहस्यमय लगते हैं।

... या शायद IoC कंटेनरों के डेवलपर्स स्पष्ट दस्तावेज लिखने में असमर्थ हैं।

... या फिर दोनों एक डिग्री या दूसरे के लिए सच हैं।

मैं अवधारणा नहीं सोचता आईओसी कंटेनर खराब है। लेकिन कार्यान्वयन के लिए शक्तिशाली (यानी, लचीला) होना आवश्यक है, जो विभिन्न प्रकार के अनुप्रयोगों में उपयोगी हो, फिर भी सरल और आसानी से समझा जा सके।

यह शायद एक के छह और दूसरे के आधा दर्जन है। एक वास्तविक एप्लिकेशन (एक खिलौना या डेमो नहीं) जटिल होने के लिए बाध्य है, कई कोने के मामलों और अपवादों के नियमों के लिए लेखांकन। या तो आप उस जटिलता को अनिवार्य कोड में कूटबद्ध करते हैं, या घोषणात्मक कोड में। लेकिन आपको कहीं न कहीं इसका प्रतिनिधित्व करना होगा।


5
मुझे जटिलता की अपरिहार्य उपस्थिति के बारे में आपका अवलोकन पसंद है। कंटेनर-आधारित और मैन्युअल निर्भरता वायरिंग के बीच का अंतर यह है कि एक कंटेनर का उपयोग करके, आप प्रत्येक घटक पर व्यक्तिगत रूप से ध्यान केंद्रित कर सकते हैं, और इस प्रकार एक काफी रैखिक तरीके से बढ़ती जटिलता का प्रबंधन कर सकते हैं। मैनुअल निर्भरता वायरिंग वाले सिस्टम विकसित करने के लिए अधिक चुनौतीपूर्ण हैं, क्योंकि एक घटक को कॉन्फ़िगर करने का कार्य बाकी सभी चीजों के विन्यास से अलग करना मुश्किल है।
निकोलस ब्लमहार्ट

मुझे AspectJ पसंद है। यह जावा नहीं है, लेकिन यह XML भी नहीं है। यह आईएस जावा की तरह है , जिसमें यह महसूस करता है और इसका विस्तार होने से जावा जैसा दिखता है। मैं अपने पहलुओं को अपने POJO और अपने व्यावसायिक तर्क से बाहर रखना चाहूंगा। मैं अपने IoCs को भी बाहर रखना चाहता हूं। पूरी तरह से उपकरण, IMHO वायरिंग में बहुत अधिक XML है। यदि मेरे पास कॉन्फ़िगरेशन फ़ाइलें हैं, तो उन्हें बीनशेल स्क्रिप्ट होने दें। / जावा, अपनी .Net कार्य-सूची यहां लागू करें ->
क्रिस के

2
मैं निश्चित रूप से आपके उत्तर को समझता हूं, लेकिन मुझे लगता है कि समस्या का एक बड़ा हिस्सा यह है कि बहुत सारे IoC फ्रेमवर्क (और, वास्तव में, अन्य चीजों के लिए बहुत सारे अन्य ढांचे भी) वर्णित हैं और दूसरों के लिए पहले से ही परिचित अन्य लोगों के लिए दस्तावेज हैं। अपेक्षित अवधारणाएं और शब्दावली। मैं इसके बारे में बहुत कुछ सीख रहा हूँ जो सिर्फ दूसरे प्रोग्रामर का कोड विरासत में मिला है। मुझे यह समझने में दिक्कत हो रही है कि जब 'ऑब्जेक्ट ग्राफ' काफी छोटा है तो कोड IoC का उपयोग क्यों कर रहा है और कोड का कोई वास्तविक परीक्षण कवरेज नहीं है। SQL प्रोग्रामर के रूप में, आप शायद ORC के साथ IoC का उपयोग करके बेहतर सराहना कर सकते हैं।
केनी एविट

1
@ केनी इविट, अच्छी बात है, यह एक आईओसी ढांचे का उपयोग करने के लिए समयपूर्व प्रतीत होगा यदि किसी के पास एक साधारण ऐप है और उसने अच्छी परीक्षा कवरेज के लिए भी परेशान नहीं किया है।
बिल कार्विन

27

कंटेनर का उपयोग ज्यादातर एक घोषणा के लिए आरंभीकरण और कॉन्फ़िगरेशन की अनिवार्य / स्क्रिप्टेड शैली से बदलने के बारे में है । इसके कुछ अलग लाभकारी प्रभाव हो सकते हैं:

  • हेयरबॉल मुख्य-कार्यक्रम स्टार्टअप दिनचर्या को कम करना ।
  • काफी गहरी तैनाती-समय पुनर्संरचना क्षमताओं को सक्षम करना।
  • निर्भरता-इंजेक्शन शैली को नए काम के लिए कम से कम प्रतिरोध का मार्ग बनाना।

बेशक, कठिनाइयाँ हो सकती हैं:

  • कोड जिसे जटिल स्टार्टअप / शटडाउन / जीवनचक्र प्रबंधन की आवश्यकता होती है, आसानी से कंटेनर में अनुकूलित नहीं किया जा सकता है।
  • आपको शायद किसी भी व्यक्तिगत, प्रक्रिया और टीम संस्कृति के मुद्दों को नेविगेट करना होगा - लेकिन फिर, इसीलिए आपने पूछा ...
  • कुछ टूलकिट तेजी से स्वयं भारी हो रहे हैं, इस तरह की गहरी निर्भरता को प्रोत्साहित करते हैं कि कई डीआई कंटेनरों ने बैकलैश के खिलाफ शुरुआत की।

23

यह मुझे लगता है जैसे आप पहले से ही अपने IoC कंटेनर का निर्माण किया (विभिन्न पैटर्न का उपयोग करके जो मार्टिन फॉलर द्वारा वर्णित किया गया था) और पूछ रहे हैं कि किसी और का कार्यान्वयन आपके मुकाबले बेहतर क्यों है।

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

एक तृतीय-पक्ष IoC कंटेनर पर विचार करने के लिए पेशेवरों

  • आपको कीड़े मुफ्त में मिलते हैं
  • पुस्तकालय का डिज़ाइन आपसे बेहतर हो सकता है
  • लोग पहले से ही विशेष पुस्तकालय से परिचित हो सकते हैं
  • लाइब्रेरी आपकी तुलना में तेज़ हो सकती है
  • इसमें कुछ विशेषताएं हो सकती हैं जिन्हें आप लागू करना चाहते हैं, लेकिन आपके पास कभी समय नहीं था (क्या आपके पास सेवा लोकेटर है?)

विपक्ष

  • आपको मुफ्त में कीड़े मिलेंगे :)
  • पुस्तकालय का डिज़ाइन आपके से भी बदतर हो सकता है
  • आपको एक नया एपीआई सीखना होगा
  • बहुत सारी सुविधाएँ जो आप कभी भी उपयोग नहीं करेंगे
  • आमतौर पर यह डिबग कोड कठिन है जो आपने नहीं लिखा
  • पिछले IoC कंटेनर से माइग्रेट करना थकाऊ हो सकता है

तो, अपने विपक्ष के खिलाफ अपने पेशेवरों का वजन करें और निर्णय लें।


मैं आपसे सहमत हूं सैम - DI एक प्रकार का आईओसी है, इसलिए यदि मूल पोस्टर डीआई कर रहा है, तो वे पहले से ही आईओसी कर रहे हैं इसलिए असली सवाल यह है कि अपना खुद का रोल क्यों करें।
जेमी लव

3
मैं असहमत हूं। IOC DI करने का एक तरीका है। आईओसी कंटेनर्स डायनेमिक रनटाइम रिफ्लेक्शन का उपयोग करके संतोष पर निर्भरता और इंजेक्शन लगाने के लिए टाइप इंस्टेंटिएशन का नियंत्रण लेते हुए डीआई करते हैं। ओपी सुझाव दे रहा है कि वह स्टैटिक डीआई कर रहा है और इस बात पर विचार कर रहा है कि आईओसी के डायनेमिक रनटाइम रिफ्लेक्शन से जुड़े फायदों के लिए उसे संकलन के समय की जांच करने की आवश्यकता क्यों है।
मैक्सम ०० Max

17

मुझे लगता है कि एक IoC का अधिकांश मूल्य DI का उपयोग करके किया जाता है। चूँकि आप पहले से ही ऐसा कर रहे हैं, बाकी लाभ वृद्धिशील है।

आपको मिलने वाला मूल्य आपके द्वारा काम कर रहे आवेदन के प्रकार पर निर्भर करेगा:

  • बहु-किरायेदार के लिए, आईओसी कंटेनर विभिन्न क्लाइंट संसाधनों को लोड करने के लिए कुछ बुनियादी ढांचे के कोड की देखभाल कर सकता है। जब आपको एक घटक की आवश्यकता होती है जो क्लाइंट विशिष्ट है, तो तर्क को संभालने के लिए एक कस्टम चयनकर्ता का उपयोग करें और अपने क्लाइंट कोड से इसके बारे में चिंता न करें। आप निश्चित रूप से इसे स्वयं बना सकते हैं लेकिन यहां एक उदाहरण है कि आईओसी कैसे मदद कर सकता है।

  • एक्स्टेंसिबिलिटी के कई बिंदुओं के साथ, IoC को कॉन्फ़िगरेशन से घटकों को लोड करने के लिए उपयोग किया जा सकता है। यह निर्माण करने के लिए एक सामान्य बात है, लेकिन उपकरण कंटेनर द्वारा प्रदान किए जाते हैं।

  • यदि आप कुछ क्रॉस-कटिंग चिंताओं के लिए एओपी का उपयोग करना चाहते हैं, तो आईओसी विधि इनवोकेशन को रोकने के लिए हुक प्रदान करता है । यह आमतौर पर परियोजनाओं पर तदर्थ रूप से किया जाता है, लेकिन IoC इसे आसान बनाता है।

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

जैसा कि दूसरों द्वारा बताया गया है, आप केंद्रीय रूप से कॉन्फ़िगर कर सकते हैं कि आप किन वर्गों का उपयोग करना चाहते हैं। हालांकि यह एक अच्छी बात हो सकती है, यह गलत तरीके और जटिलता की कीमत पर आता है। अधिकांश अनुप्रयोगों के लिए मुख्य घटक को प्रतिस्थापित नहीं किया जाता है इसलिए व्यापार बंद करना थोड़ा कठिन है।

मैं एक IoC कंटेनर का उपयोग करता हूं और कार्यक्षमता की सराहना करता हूं, लेकिन यह स्वीकार करना होगा कि मैंने ट्रेड-ऑफ पर ध्यान दिया है: मेरा कोड कक्षा स्तर पर अधिक स्पष्ट हो जाता है और एप्लिकेशन स्तर पर कम स्पष्ट होता है (अर्थात नियंत्रण प्रवाह की कल्पना करना)।


16

मैं ठीक होने वाला आईओसी व्यसनी हूं। मैं इन दिनों ज्यादातर मामलों में DI के लिए IOC का उपयोग करना उचित समझता हूं। आईओसी कंटेनर संकलित समय की जांच करते हैं और बदले में माना जाता है कि आप "आसान" सेटअप, जटिल जीवनकाल प्रबंधन और रन टाइम पर निर्भरता की खोज पर उड़ान भरते हैं। मुझे संकलन के समय की हानि का पता चलता है और जिसके परिणामस्वरूप समय जादू / अपवाद होता है, अधिकांश मामलों में घंटियाँ और सीटी बजने लायक नहीं होती हैं। बड़े उद्यम अनुप्रयोगों में वे जो भी चल रहा है उसका पालन करना बहुत कठिन बना सकते हैं।

मैं केंद्रीकरण तर्क नहीं खरीदता हूं क्योंकि आप स्थैतिक सेटअप को बहुत आसानी से केंद्रीकृत कर सकते हैं और साथ ही अपने आवेदन के लिए एक अमूर्त कारखाने का उपयोग कर सकते हैं और धार्मिक रूप से वस्तु के निर्माण को अमूर्त कारखाने अर्थात उचित DI में कर सकते हैं।

इस तरह स्थिर जादू-रहित DI क्यों नहीं करते:

interface IServiceA { }
interface IServiceB { }
class ServiceA : IServiceA { }
class ServiceB : IServiceB { }

class StubServiceA : IServiceA { }
class StubServiceB : IServiceB { }

interface IRoot { IMiddle Middle { get; set; } }
interface IMiddle { ILeaf Leaf { get; set; } }
interface ILeaf { }

class Root : IRoot
{
    public IMiddle Middle { get; set; }

    public Root(IMiddle middle)
    {
        Middle = middle;
    }

}

class Middle : IMiddle
{
    public ILeaf Leaf { get; set; }

    public Middle(ILeaf leaf)
    {
        Leaf = leaf;
    }
}

class Leaf : ILeaf
{
    IServiceA ServiceA { get; set; }
    IServiceB ServiceB { get; set; }

    public Leaf(IServiceA serviceA, IServiceB serviceB)
    {
        ServiceA = serviceA;
        ServiceB = serviceB;
    }
}


interface IApplicationFactory
{
    IRoot CreateRoot();
}

abstract class ApplicationAbstractFactory : IApplicationFactory
{
    protected abstract IServiceA ServiceA { get; }
    protected abstract IServiceB ServiceB { get; }

    protected IMiddle CreateMiddle()
    {
        return new Middle(CreateLeaf());
    }

    protected ILeaf CreateLeaf()
    {
        return new Leaf(ServiceA,ServiceB);
    }


    public IRoot CreateRoot()
    {
        return new Root(CreateMiddle());
    }
}

class ProductionApplication : ApplicationAbstractFactory
{
    protected override IServiceA ServiceA
    {
        get { return new ServiceA(); }
    }

    protected override IServiceB ServiceB
    {
        get { return new ServiceB(); }
    }
}

class FunctionalTestsApplication : ApplicationAbstractFactory
{
    protected override IServiceA ServiceA
    {
        get { return new StubServiceA(); }
    }

    protected override IServiceB ServiceB
    {
        get { return new StubServiceB(); }
    }
}


namespace ConsoleApplication5
{
    class Program
    {
        static void Main(string[] args)
        {
            var factory = new ProductionApplication();
            var root = factory.CreateRoot();

        }
    }

    //[TestFixture]
    class FunctionalTests
    {
        //[Test]
        public void Test()
        {
            var factory = new FunctionalTestsApplication();
            var root = factory.CreateRoot();
        }
    }
}

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

लाभ:

  • सभी सेटअप और ऑब्जेक्ट निर्माण कॉन्फ़िगरेशन केंद्रीकृत है।
  • कॉन्फ़िगरेशन सिर्फ कोड है
  • संकलन समय की जाँच करना आसान बना देता है क्योंकि आप अपने पंजीकरण को अद्यतन करना नहीं भूल सकते।
  • कोई रन-टाइम रिफ्लेक्शन मैजिक नहीं

मैं संशयवादियों को सलाह देता हूं कि इसे अगली हरी फील्ड परियोजना के लिए जाना चाहिए और ईमानदारी से अपने आप से पूछना चाहिए कि आपको किस बिंदु पर कंटेनर की आवश्यकता है। IOC कंटेनर में बाद में फैक्टर करना आसान है क्योंकि आप एक IOC कंटेनर कॉन्फ़िगरेशन मॉड्यूल के साथ एक कारखाना कार्यान्वयन की जगह ले रहे हैं।


यह मुझे आईओसी के खिलाफ एक तर्क की तरह नहीं लगता है, लेकिन कॉन्फ़िगर करने योग्य आईओसी फ्रेमवर्क के खिलाफ एक तर्क है । क्या आपके कारखाने यहाँ सरल हार्ड-कोडित IoCs को उबाल नहीं सकते हैं ?
श्री मिन्डोर

मुझे लगता है कि जब पोस्टर ने आईओसी का उल्लेख किया था तो आईओसी कंटेनर फ्रेमवर्क था। मूल लेखन के लिए धन्यवाद, यह मुझे एक ढांचे के बिना जाने के लिए मनाने में मदद करता है। तो अगर यह परीक्षण और उत्पादन कोड में विन्यास योग्य है, तो "विन्यास योग्य" ढांचे का क्या फायदा है?
ह्यूगी

शब्दावली की मेरी समझ से, व्युत्क्रम नियंत्रण का मतलब रन-टाइम पर निर्भरता खोजना है। तो हां, आप कह सकते हैं कि कारखाना मूल रूप से एक हार्ड-कोडेड या स्थिर कंटेनर है, लेकिन यह IOC कंटेनर नहीं है। संकलन समय पर प्रकार हल किए जाते हैं। यह कॉन्फ़िगर करने योग्य चौखटे का उपयोग करने के खिलाफ एक तर्क है जो रनटाइम के प्रकारों को हल करने के लिए शब्दकोश लुकअप का उपयोग करता है।
मैक्सम Max००

14

मेरे लिए IoC कंटेनरों का उपयोग करने का सबसे बड़ा लाभ (व्यक्तिगत रूप से, मैं Ninject का उपयोग करता हूं) सेटिंग्स और अन्य प्रकार के वैश्विक राज्य ऑब्जेक्ट्स के पास होने को समाप्त करने के लिए किया गया है।

मैं वेब के लिए कार्यक्रम नहीं करता हूं, मेरा एक कंसोल एप्लिकेशन है और ऑब्जेक्ट ट्री में गहरी कई जगहों पर मुझे उपयोगकर्ता द्वारा निर्दिष्ट सेटिंग्स या मेटाडेटा तक पहुंच की आवश्यकता है जो ऑब्जेक्ट ट्री की पूरी तरह से अलग शाखा पर बनाई गई हैं। IoC के साथ, मैं केवल निनजे को सेटिंग्स को एक एकल के रूप में व्यवहार करने के लिए कहता हूं (क्योंकि हमेशा उनमें से केवल एक उदाहरण है), रचनाकार और presto में सेटिंग्स या शब्दकोश का अनुरोध करें ... वे जादुई रूप से तब प्रकट होते हैं जब मुझे उनकी आवश्यकता होती है!

एक IoC कंटेनर का उपयोग किए बिना मुझे 2, 3, ..., n ऑब्जेक्ट्स के माध्यम से सेटिंग्स और / या मेटाडेटा को नीचे पारित करना होगा, वास्तव में इसका उपयोग उस ऑब्जेक्ट द्वारा किया गया था जिसे इसकी आवश्यकता थी।

DI / IoC कंटेनरों को कई अन्य लाभ हैं क्योंकि अन्य लोग यहां विस्तृत हैं और वस्तुओं को बनाने के विचार से आगे बढ़कर वस्तुओं को झुकने वाले हो सकते हैं, लेकिन DI का उपयोग करना मेरे और मेरी टीम के लिए बहुत मददगार था इसलिए शायद आप इसे जोड़ सकें अपने शस्त्रागार के लिए!


2
यह बहुत बड़ा प्लस है। विश्वास नहीं कर सकता कि किसी और ने इसका उल्लेख नहीं किया है। टेम्पोरी ऑब्जेक्ट्स को पास या स्टोर करने की आवश्यकता के बिना कोड बहुत अधिक क्लीनर बनाता है।
फिंगलस

1
@qble ग्लोबल ऑब्जेक्ट्स महान काम करते हैं ... यदि आप चाहते हैं कि आपका कोड आधार एक कसकर युग्मित, संयुक्त राष्ट्र के परीक्षण योग्य दुःस्वप्न हो जो समय के साथ संशोधित करने के लिए कठिन और कठिन हो जाता है। उसके साथ अच्छा भाग्य।
जेफरी कैमरन

2
@JeffreyCameron आईओसी कंटेनर है वैश्विक वस्तु। यह आपकी वैश्विक निर्भरता को दूर नहीं करता है।
at१३ पर क़ाबिल

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

1
@ मक्खी पर क्षणिक उदाहरण बनाने के लिए कारखानों का उपयोग करें। कारखाने एकल सेवाएं हैं। यदि आईओसी कंटेनर से क्षणिक आवृत्तियों को कुछ की आवश्यकता होती है, तो उन्हें कारखाने में तार दें और निर्भरता को पार करने के लिए कारखाने को प्राप्त करें।
जेफरी कैमरन

14

यदि आप चाहते हैं तो IoC फ्रेमवर्क उत्कृष्ट हैं ...

  • ... टाइप सेफ्टी फेंक देते हैं। कई (सभी?) IoC चौखटे आपको कोड निष्पादित करने के लिए मजबूर करते हैं यदि आप कुछ निश्चित होना चाहते हैं तो सही ढंग से झुका हुआ है। "अरे! आशा है कि मुझे सब कुछ मिल गया है, इसलिए इन 100 वर्गों की मेरी शुरुआत उत्पादन में असफल नहीं होगी, नेल-पॉइंटर फेंकने की!"

  • ... ग्लोबल्स के साथ अपने कोड को लिट करें (आईओसी ढांचे सभी वैश्विक राज्यों को बदलने के बारे में हैं)।

  • ... अस्पष्ट निर्भरता के साथ भद्दा कोड लिखें जो कि रिफ्लेक्टर के लिए कठिन है क्योंकि आप कभी नहीं जान पाएंगे कि क्या निर्भर करता है।

IoC के साथ समस्या यह है कि जो लोग उनका उपयोग करते हैं वे इस तरह कोड लिखते थे

public class Foo {
    public Bar Apa {get;set;}
    Foo() {
        Apa = new Bar();
    }
}

जो जाहिर है फू और बार के बीच निर्भरता के बाद से त्रुटिपूर्ण है। तब उन्हें एहसास हुआ कि कोड लिखना बेहतर होगा

public class Foo {
    public IBar Apa {get;set;}
    Foo() {
        Apa = IoC<IBar>();
    }
}

जो त्रुटिपूर्ण है, लेकिन कम स्पष्ट रूप से ऐसा है। हास्केल में का प्रकार Foo()होगा, IO Fooलेकिन आप वास्तव में नहीं चाहते हैंIO -पार्टी और यह चेतावनी संकेत होना चाहिए कि आपके डिज़ाइन के साथ कुछ गलत है अगर आपको यह मिल गया है।

इसे (IO- भाग) से छुटकारा पाने के लिए, IoC- चौखटे के सभी लाभ प्राप्त करें और इसमें से कोई भी कमियां नहीं हैं जो आप एक सार कारखाने का उपयोग कर सकते हैं।

सही समाधान कुछ इस तरह होगा

data Foo = Foo { apa :: Bar }

या हो सकता है

data Foo = forall b. (IBar b) => Foo { apa :: b }

और इंजेक्शन (लेकिन मैं इसे इंजेक्शन नहीं कहूंगा) बार।

इसके अलावा: एरिक मेजर (LINQ के आविष्कारक) के साथ इस वीडियो को देखें जहां वह कहता है कि DI उन लोगों के लिए है जो गणित नहीं जानते (और मैं अधिक सहमत नहीं हो सकता): http://www.youtube.com/watch?v = 8Mttjyf-8P4

श्री स्पोलस्की के विपरीत, मुझे विश्वास नहीं है कि जो लोग आईओसी-फ्रेमवर्क का उपयोग करते हैं, वे बहुत स्मार्ट हैं - मेरा मानना ​​है कि वे गणित नहीं जानते हैं।


9
थ्रो टाइप सेफ्टी - अपने उदाहरण को छोड़कर, अभी भी सुरक्षित है, यही इंटरफ़ेस है। आप ऑब्जेक्ट के प्रकार के आसपास नहीं गुजर रहे हैं, लेकिन इंटरफ़ेस प्रकार। और प्रकार की सुरक्षा शून्य संदर्भ अपवादों के साथ दूर नहीं करती है, आप सुरक्षित संदर्भों के रूप में अशक्त संदर्भों को पास कर सकते हैं - यह एक प्रकार का सुरक्षा मुद्दा नहीं है।
ब्लरडार्ट

आप टाइप सुरक्षा को फेंक देते हैं क्योंकि आपको पता नहीं है कि आईओसी-कंटेनर में टाइप किया गया है या नहीं (IoC <IBar> का प्रकार नहीं है IBar, यह वास्तव में नहीं है IO IBar) .. और हां, हास्केल-उदाहरण में मुझे अशक्त-संदर्भ नहीं मिल सकता है।
फाइनेंसन

प्रकार सुरक्षा वास्तव में किसी वस्तु के बारे में नहीं बताई जाती है, कम से कम जावा / सी # में नहीं, यह केवल वस्तु के सही प्रकार के होने के बारे में है। और कंक्रीटक्लास मायक्लास = नल अभी भी सही प्रकार का है। यदि आप अशक्त नहीं लागू करना चाहते हैं तो कोड अनुबंध खेलने में आते हैं।
ब्लीडार्ट

2
मैं कुछ हद तक आपके 1 बिंदु से सहमत हूं, मैं 2 के कुछ स्पष्टीकरण चाहता हूं और तीसरा मेरे लिए कभी भी समस्या नहीं रहा है। आपका C # नमूना IoC कंटेनर को सेवा लोकेटर, एक सामान्य गलती के रूप में उपयोग करता है। और सी # बनाम हास्केल = सेब बनाम संतरे की तुलना करना।
मौरिसियो शेफ़र

2
आप टाइप-सेफ्टी को फेंकते नहीं हैं। कुछ (यदि अधिकांश नहीं) DI कंटेनर आपको पंजीकरण प्रक्रिया के बाद संपूर्ण ऑब्जेक्ट ग्राफ को सत्यापित करने की अनुमति देते हैं। ऐसा करते समय आप एप्लिकेशन को मिसकॉन्फ़िगरेशन (तेजी से विफल) पर शुरू होने से रोक सकते हैं और मेरे अनुप्रयोगों में हमेशा कुछ इकाई परीक्षण होते हैं जो मुझे परीक्षण के दौरान इन त्रुटियों को खोजने की अनुमति देने के लिए उत्पादन कॉन्फ़िगरेशन कहते हैं। मैं एक IoC कंटेनर का उपयोग करके सभी को सलाह दूंगा कि कुछ इकाई परीक्षण लिखें जो सुनिश्चित करें कि सभी शीर्ष-स्तरीय ऑब्जेक्ट हल किए जा सकते हैं।
स्टीवन

10

मैंने पाया है कि प्रोग्रामर को टेस्टबिलिटी, फ्लेक्सिबिलिटी, मेंटेनेंस, और स्केलेबिलिटी को बेहतर बनाने में मदद करने के लिए कई अन्य प्रोग्रामिंग प्रैक्टिस का उपयोग करने के लिए प्रोग्रामर को सही ढंग से लागू करने के लिए डिपेंडेंसी इंजेक्शन लागू करना सही है: सिंगल रिस्पॉन्सिबिलिटी प्रिंसिपल, कंसर्न की सेपरेशन और कोडिंग जैसी प्रैक्टिस। एपीआई के खिलाफ। ऐसा लगता है कि मैं अधिक मॉड्यूलर, काटने के आकार की कक्षाओं और विधियों को लिखने के लिए मजबूर हो रहा हूं, जिससे कोड को पढ़ने में आसान हो जाता है, क्योंकि इसे काटने के आकार के टुकड़ों में लिया जा सकता है।

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

var merger = new SimpleWorkflowInstanceMerger(
    new BitFactoryLog(typeof(SimpleWorkflowInstanceMerger).FullName), 
    new WorkflowAnswerRowUtil(
        new WorkflowFieldAnswerEntMapper(),
        new ActivityFormFieldDisplayInfoEntMapper(),
        new FieldEntMapper()),
    new AnswerRowMergeInfoRepository());

रेट्रोस्पेक्ट में, यह IoC फ्रेमवर्क का उपयोग करने के लिए तेज होता, क्योंकि मॉड्यूल कन्वेंशन द्वारा इस सामान के सभी को बहुत अधिक परिभाषित करते हैं।

इस सवाल के जवाब और टिप्पणियों का अध्ययन करने में कुछ समय बिताने के बाद, मुझे यकीन है कि जो लोग एक IoC कंटेनर का उपयोग करने का विरोध कर रहे हैं वे सच्चे निर्भरता इंजेक्शन का अभ्यास नहीं कर रहे हैं। मैंने जो उदाहरण देखे हैं वे उन प्रथाओं के हैं जो आमतौर पर निर्भरता इंजेक्शन के साथ भ्रमित होते हैं। कुछ लोग कोड को "पढ़ने" में कठिनाई के बारे में शिकायत कर रहे हैं। यदि सही ढंग से किया जाता है, तो आपके कोड का विशाल बहुमत एक आईओसी कंटेनर का उपयोग करते समय डीआई को हाथ से उपयोग करते समय समान होना चाहिए। अंतर पूरी तरह से आवेदन के भीतर कुछ "लॉन्चिंग पॉइंट" में रहना चाहिए।

दूसरे शब्दों में, यदि आप IoC कंटेनरों को पसंद नहीं करते हैं, तो आप शायद डिपेंडेंसी इंजेक्शन नहीं कर रहे हैं जिस तरह से यह माना जाता है।

एक और बिंदु: यदि आप कहीं भी प्रतिबिंब का उपयोग करते हैं तो निर्भरता इंजेक्शन वास्तव में हाथ से नहीं किया जा सकता है। जबकि मैं नेविगेशन को कोड करने के लिए क्या प्रतिबिंब से नफरत करता हूं, आपको यह पहचानना होगा कि कुछ निश्चित क्षेत्र हैं जहां इसे वास्तव में टाला नहीं जा सकता है। उदाहरण के लिए, ASP.NET MVC, प्रत्येक अनुरोध पर प्रतिबिंब के माध्यम से नियंत्रक को तुरंत करने का प्रयास करता है। हाथ से निर्भरता इंजेक्शन करने के लिए, आपको प्रत्येक नियंत्रक को "संदर्भ मूल" बनाना होगा , जैसे:

public class MyController : Controller
{
    private readonly ISimpleWorkflowInstanceMerger _simpleMerger;
    public MyController()
    {
        _simpleMerger = new SimpleWorkflowInstanceMerger(
            new BitFactoryLog(typeof(SimpleWorkflowInstanceMerger).FullName), 
            new WorkflowAnswerRowUtil(
                new WorkflowFieldAnswerEntMapper(),
                new ActivityFormFieldDisplayInfoEntMapper(),
                new FieldEntMapper()),
            new AnswerRowMergeInfoRepository())
    }
    ...
}

अब इसकी तुलना डीआई फ्रेमवर्क को आपके लिए करने की अनुमति के साथ करें:

public MyController : Controller
{
    private readonly ISimpleWorkflowInstanceMerger _simpleMerger;
    public MyController(ISimpleWorkflowInstanceMerger simpleMerger)
    {
        _simpleMerger = simpleMerger;
    }
    ...
}

DI ढांचे का उपयोग करते हुए, ध्यान दें कि:

  • मैं इस क्लास को यूनिट-टेस्ट कर सकता हूं। मॉक बनाकरISimpleWorkflowInstanceMerger , मैं यह परीक्षण कर सकता हूं कि यह डेटाबेस कनेक्शन या किसी भी चीज की आवश्यकता के बिना, मेरे प्रत्याशित तरीके का उपयोग करता है।
  • मैं बहुत कम कोड का उपयोग करता हूं, और कोड को पढ़ना बहुत आसान है।
  • अगर मेरी एक निर्भरता निर्भरता में बदलाव की है, तो मुझे नियंत्रक में कोई बदलाव नहीं करना है। यह विशेष रूप से अच्छा है जब आप समझते हैं कि एकाधिक नियंत्रकों में कुछ समान निर्भरता का उपयोग करने की संभावना है।
  • मैंने अपनी डेटा लेयर से स्पष्ट रूप से संदर्भ कक्षाएं कभी नहीं लीं। मेरा वेब एप्लिकेशन ISimpleWorkflowInstanceMergerइंटरफ़ेस वाले प्रोजेक्ट के संदर्भ को शामिल कर सकता है। यह मुझे अलग मॉड्यूल में एप्लिकेशन को तोड़ने और एक सच्चे मल्टी-टियर आर्किटेक्चर को बनाए रखने की अनुमति देता है, जो बदले में चीजों को बहुत अधिक लचीला बनाता है।

एक विशिष्ट वेब एप्लिकेशन में काफी कुछ नियंत्रक होंगे। प्रत्येक नियंत्रक में हाथ से DI करने के दर्द के सभी वास्तव में आपके आवेदन बढ़ने पर जोड़ देंगे। यदि आपके पास केवल एक संदर्भ रूट के साथ एक आवेदन है, जो कभी भी प्रतिबिंब द्वारा किसी सेवा को त्वरित करने की कोशिश नहीं करता है, तो यह उतनी बड़ी समस्या नहीं है। फिर भी, कोई भी एप्लिकेशन जो डिपेंडेंसी इंजेक्शन का उपयोग करता है, एक निश्चित आकार तक पहुंचने के बाद प्रबंधन करने के लिए बेहद महंगा हो जाएगा, जब तक कि आप निर्भरता ग्राफ को प्रबंधित करने के लिए किसी प्रकार के ढांचे का उपयोग नहीं करते हैं।


9

जब भी आप "नए" कीवर्ड का उपयोग करते हैं, तो आप एक ठोस श्रेणी पर निर्भरता पैदा कर रहे होते हैं और थोड़ा अलार्म बेल आपके सिर में चला जाना चाहिए। अलगाव में इस वस्तु का परीक्षण करना कठिन हो जाता है। समाधान को इंटरफेस पर निर्भर करने और निर्भरता को इंजेक्षन करने के लिए प्रोग्राम करना है ताकि ऑब्जेक्ट को किसी भी चीज के साथ परीक्षण किया जा सके जो कि इंटरफ़ेस (जैसे। नकली)।

मुसीबत यह है कि आपको कहीं न कहीं वस्तुओं का निर्माण करना होगा। फ़ैक्टरी पैटर्न आपके POXOs से बाहर युग्मन को स्थानांतरित करने का एक तरीका है (प्लेन ओल्ड "अपनी ओओ भाषा को" ऑब्जेक्ट्स "यहां डालें)। यदि आप और आपके सहकर्मी सभी इस तरह कोड लिख रहे हैं तो एक आईओसी कंटेनर अगला "इंक्रीमेंटल इम्प्रूवमेंट" है जिसे आप अपने कोडबेस में बना सकते हैं। यह आपके साफ ऑब्जेक्ट्स और व्यावसायिक लॉजिक से उस सभी नॉटी फैक्ट्री बॉयलरप्लेट कोड को स्थानांतरित कर देगा। वे इसे प्राप्त करेंगे और इसे प्यार करेंगे। बिल्ली, एक कंपनी को इस बारे में बात दें कि आप इसे क्यों पसंद करते हैं और सभी को उत्साहित करते हैं।

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


8

क्योंकि सभी निर्भरताएं स्पष्ट रूप से दिखाई देती हैं, यह उन घटकों को बनाने को बढ़ावा देता है जो शिथिल युग्मित होते हैं और एक ही समय में आसानी से सुलभ और पुन: प्रयोज्य होते हैं।


7

आपको IoC कंटेनर की आवश्यकता नहीं है

लेकिन यदि आप एक DI पैटर्न का कठोरता से पालन कर रहे हैं, तो आप पाएंगे कि एक टन अनावश्यक, उबाऊ कोड को हटा देगा।

पुस्तकालय / रूपरेखा का उपयोग करने का सबसे अच्छा समय अक्सर होता है, वैसे भी - जब आप समझते हैं कि यह क्या कर रहा है और पुस्तकालय के बिना कर सकता है।


6

मैं अभी तक घर से बाहर हो जाना DI कोड yanking और एक IOC के साथ बदलने की प्रक्रिया में हो सकता है। मैंने शायद कोड की 200 से अधिक लाइनों को अच्छी तरह से हटा दिया है और इसे लगभग 10. के साथ बदल दिया है। हां, मुझे कंटेनर (विंसर) का उपयोग करने के बारे में थोड़ा सीखना था, लेकिन मैं एक इंजीनियर हूं जो इंटरनेट तकनीकों पर काम कर रहा हूं। 21 वीं सदी इसलिए मुझे इसकी आदत है। मैं शायद लगभग 20 मिनट बिताता हूं कि कैसे टॉस किया जाता है। यह मेरे समय के लायक था।


3
"लेकिन मैं 21 वीं सदी में इंटरनेट तकनीकों पर काम करने वाला एक इंजीनियर हूं, इसलिए मैं इसका उपयोग कर रहा हूं" -> +1
user96403

5

जैसे-जैसे आप अपनी कक्षाओं को कम करते जा रहे हैं और अपनी निर्भरता को उलटते जा रहे हैं, कक्षाएं छोटी बनी रहती हैं और "निर्भरता का ग्राफ" आकार में बढ़ता रहता है। (यह बुरा नहीं है।) एक IoC कंटेनर की बुनियादी विशेषताओं का उपयोग करने से इन सभी वस्तुओं को तुच्छ बना दिया जाता है, लेकिन इसे मैन्युअल रूप से करने से बहुत बोझ लग सकता है। उदाहरण के लिए, क्या होगा अगर मैं "फू" का एक नया उदाहरण बनाना चाहता हूं, लेकिन इसे "बार" की आवश्यकता है। और "बार" को "ए", "बी" और "सी" की आवश्यकता होती है। और उनमें से प्रत्येक को 3 अन्य चीजों की आवश्यकता है, आदि आदि (हां, मैं अच्छे नकली नामों के साथ नहीं आ सकता हूं :))।

आपके लिए अपने ऑब्जेक्ट ग्राफ को बनाने के लिए एक IoC कंटेनर का उपयोग करने से जटिलता एक टन कम हो जाती है और इसे एक बार के कॉन्फ़िगरेशन में धकेल देती है। मैं बस कहता हूं "मुझे एक 'फू' बनाएं" और यह पता लगाता है कि एक का निर्माण करने के लिए क्या आवश्यक है।

कुछ लोग बहुत अधिक बुनियादी ढांचे के लिए IoC कंटेनरों का उपयोग करते हैं, जो उन्नत परिदृश्यों के लिए ठीक है, लेकिन उन मामलों में मैं सहमत हूं कि यह नए देवों के लिए कोड को पढ़ने और डिबग करने के लिए कठिन बना सकता है।


1
क्यों हम उन्हें खींचने के लिए काम के बजाय सबसे कम आम भाजक को खुश करना जारी रखते हैं?
स्टीवनहरमैन

4
मैंने खुश करने के बारे में कुछ नहीं कहा। मैंने अभी कहा कि उन्नत परिदृश्य चीजों को नए देवों के लिए अधिक अस्पष्ट बना सकते हैं - यह एक तथ्य है। मैंने नहीं कहा "तो ऐसा मत करो"। लेकिन फिर भी (शैतान के वकील के लिए समय) एक ही चीज़ को पूरा करने के लिए अक्सर अन्य तरीके होते हैं जो कोडबेस को अधिक स्पष्ट और स्वीकार्य बनाते हैं। अपने इंफ्रास्ट्रक्चर टूल कस्टम कॉन्फ़िगरेशन में जटिलता छिपाना सिर्फ इसलिए कि आप सही कारण नहीं बता सकते हैं, और यह किसी को भी नहीं खींचता है।
आरोन लेरच

4

एकता के बारे में Dittos। बहुत बड़ा हो जाओ, और तुम बेड़ा गर्त में सुन सकते हो।

यह मुझे कभी आश्चर्यचकित नहीं करता है जब लोग इस बारे में बोलना शुरू करते हैं कि आईओसी कोड कितना साफ दिखता है, उसी तरह के लोग हैं जो एक समय में बोलते थे कि कैसे सी ++ में टेम्पलेट 90 के दशक में वापस जाने के लिए सुरुचिपूर्ण तरीके थे, फिर भी आजकल उन्हें आर्कन के रूप में कम कर देगा। । बाह!


2

.NET की दुनिया में AOP बहुत लोकप्रिय नहीं है, इसलिए DI के लिए एक फ्रेमवर्क ही आपका एकमात्र वास्तविक विकल्प है, चाहे आप स्वयं लिखें या किसी अन्य फ्रेमवर्क का उपयोग करें।

यदि आपने AOP का उपयोग किया है तो आप अपने आवेदन को संकलित कर सकते हैं, जो कि जावा में अधिक सामान्य है।

DI को कई लाभ हैं, जैसे कम युग्मन इसलिए इकाई परीक्षण आसान है, लेकिन आप इसे कैसे लागू करेंगे? क्या आप इसे स्वयं करने के लिए प्रतिबिंब का उपयोग करना चाहते हैं?


नया MEF फ्रेमवर्क .NET के लिए बस यही अनुमति देता है और मुझे कहना होगा कि कोड क्लीनर और समझने में आसान है, यह DI अवधारणा को समझना बहुत आसान बनाता है।
टेरजेटाइल ऑक्ट

4
@TT: MEF है नहीं एक निर्भरता इंजेक्शन कंटेनर और AOP के साथ कोई संबंध नहीं है।
मौरिसियो शेफ़र

2

तो, यह लगभग 3 साल है, एह?

  1. आईओसी फ्रेमवर्क के पक्ष में टिप्पणी करने वालों में से 50% आईओसी और आईओसी फ्रेमवर्क के बीच अंतर को नहीं समझते हैं। मुझे संदेह है कि वे जानते हैं कि आप ऐप सर्वर पर तैनात किए बिना कोड लिख सकते हैं

  2. यदि हम सबसे लोकप्रिय जावा स्प्रिंग फ्रेमवर्क लेते हैं, तो यह आईओसी कॉन्फ़िगरेशन एक्सएमएल से कोड में स्थानांतरित हो गया है और अब इस तरह दिखता है

`@Configuration सार्वजनिक वर्ग AppConfig {

public @Bean TransferService transferService() {
    return new TransferServiceImpl(accountRepository());
}

public @Bean AccountRepository accountRepository() {
    return new InMemoryAccountRepository();
}

} `और हमें ऐसा करने के लिए एक रूपरेखा की आवश्यकता है कि वास्तव में क्यों?


1

ईमानदारी से, मुझे नहीं लगता कि ऐसे कई मामले हैं जहां IoC कंटेनरों की आवश्यकता होती है, और ज्यादातर समय, वे सिर्फ अनावश्यक जटिलता जोड़ते हैं।

यदि आप इसे किसी ऑब्जेक्ट के निर्माण को सरल बनाने के लिए उपयोग कर रहे हैं, तो मुझे पूछना होगा कि क्या आप इस ऑब्जेक्ट को एक से अधिक स्थानों पर इंस्टेंट कर रहे हैं? क्या एक सिंगलटन आपकी आवश्यकताओं के अनुरूप नहीं होगा? क्या आप रनटाइम में कॉन्फ़िगरेशन बदल रहे हैं? (स्विचिंग डेटा स्रोत प्रकार, आदि)।

यदि हाँ, तो आपको आईओसी कंटेनर की आवश्यकता हो सकती है। यदि नहीं, तो आप अभी आरंभीकरण को दूर ले जा रहे हैं जहाँ से डेवलपर इसे आसानी से देख सकता है।

किसने कहा कि एक इंटरफ़ेस वैसे भी विरासत से बेहतर है? कहते हैं कि आप एक सेवा का परीक्षण कर रहे हैं। कंस्ट्रक्टर डि का उपयोग क्यों नहीं करते हैं, और इनहेरिटेंस का उपयोग करके निर्भरता के नकली बनाएं? मैं जिन सेवाओं का उपयोग करता हूं उनमें केवल कुछ निर्भरताएं हैं। इस तरह से इकाई परीक्षण करना एक टन बेकार इंटरफेस को बनाए रखने से रोकता है और इसका मतलब है कि आपको एक विधि की घोषणा को खोजने के लिए रेस्परर का उपयोग करने की आवश्यकता नहीं है

मेरा मानना ​​है कि अधिकांश कार्यान्वयनों के लिए, यह कहना कि IoC कंटेनर अनावश्यक कोड हटाते हैं, एक मिथक है।

सबसे पहले, पहले स्थान पर कंटेनर स्थापित कर रहा है। फिर आपको अभी भी प्रत्येक ऑब्जेक्ट को परिभाषित करना होगा जिसे आरंभीकृत करने की आवश्यकता है। इसलिए आप कोड को इनिशियलाइज़ेशन में सेव नहीं करते हैं, आप इसे स्थानांतरित करते हैं (जब तक कि आपकी वस्तु एक से अधिक बार उपयोग नहीं की जाती है। क्या यह सिंगलटन के रूप में बेहतर है?)। फिर, इस तरह से प्रत्येक ऑब्जेक्ट के लिए, आपको एक इंटरफ़ेस बनाना और बनाए रखना होगा।

क्या किसी के पास इस पर कोई विचार है?


यहां तक ​​कि छोटी परियोजनाओं के लिए, एक्सएमएल में कॉन्फ़िगरेशन डालने से यह बहुत क्लीनर और अधिक मॉड्यूलर हो जाता है - और पहली बार, कोड को पुन: प्रयोज्य बनाता है (क्योंकि यह अब गोंद से दूषित नहीं होता है)। उचित सॉफ्टवेयर उत्पादों के लिए, आप कॉन्फ़िगर या उदाहरण के लिए स्वैप कर सकते हैं ShippingCostCalculatorया ProductUIPresentation, या किसी अन्य रणनीति / कार्यान्वयन, ठीक उसी codebase के भीतर सिर्फ एक बदली हुई एक्सएमएल फ़ाइल वितरित करते हुए,।
थॉमस डब्ल्यू

यदि यह एक सामान्य अभ्यास के रूप में विली-नीली लागू किया गया है, तो मुझे लगता है कि आप अधिक जटिलता जोड़ते हैं, कम नहीं। जब आपको रनटाइम पर कुछ स्वैप करने की आवश्यकता होती है, तो वे बहुत अच्छे होते हैं, लेकिन आक्षेप क्यों जोड़ते हैं? उन चीज़ों के लिए अतिरिक्त इंटरफेस का ओवरहेड क्यों रखें, जिन्हें कभी भी बंद नहीं किया जाएगा? मैं यह नहीं कह रहा कि परीक्षण के लिए IoC का उपयोग न करें। हर तरह से, संपत्ति या यहां तक ​​कि कंस्ट्रक्टर निर्भरता इंजेक्शन का उपयोग करें। क्या आपको एक इंटरफ़ेस का उपयोग करने की आवश्यकता है? क्यों नहीं अपने परीक्षण वस्तुओं उपवर्ग? कि क्लीनर नहीं होगा?
फ्रेड

XML कॉन्फ़िगरेशन / IoC करने के लिए आपको बिल्कुल भी इंटरफेस की आवश्यकता नहीं है। मुझे केवल 8 पृष्ठों और 5 या 6 सेवाओं के साथ एक छोटी सी परियोजना में स्पष्टता में बहुत सुधार मिला। सेवाओं और नियंत्रकों के बाद अब गोंद कोड की आवश्यकता नहीं होने के कारण कम आक्षेप है
थॉमस डब्ल्यू

1

यदि आपको अपने आश्रितों के विन्यास को केंद्रीकृत करने की आवश्यकता है तो आपको एक IoC कंटेनर की आवश्यकता होगी ताकि वे आसानी से बाहर सामूहिक रूप से अदला-बदली कर सकें। यह टीडीडी में सबसे अधिक समझ में आता है, जहां कई निर्भरताएं बाहर हो जाती हैं, लेकिन जहां निर्भरता के बीच बहुत कम निर्भरता होती है। यह कुछ हद तक वस्तु निर्माण के नियंत्रण के प्रवाह को बाधित करने की कीमत पर किया जाता है, इसलिए एक अच्छी तरह से व्यवस्थित और यथोचित दस्तावेज विन्यास महत्वपूर्ण है। ऐसा करने के लिए एक कारण होना भी अच्छा है, अन्यथा, यह केवल अमूर्त सोना-चढ़ाना है । मैंने इसे इतने खराब तरीके से देखा है कि इसे निर्माणकर्ताओं के लिए एक गोटो बयान के बराबर होने के लिए नीचे खींच लिया गया था।


1

यहाँ क्यों है। परियोजना को IOC-with-Ninject कहा जाता है। आप इसे विजुअल स्टूडियो के साथ डाउनलोड और चला सकते हैं। यह उदाहरण Ninject का उपयोग करता है, लेकिन सभी 'नए' कथन एक स्थान पर हैं और आप पूरी तरह से बदल सकते हैं कि किस तरह से उपयोग करने के लिए बाइंड मॉड्यूल को बदलकर आपका आवेदन चलता है। उदाहरण सेट किया गया है ताकि आप सेवाओं के नकली संस्करण या वास्तविक संस्करण से बंध सकें। छोटी परियोजनाओं में जो बात नहीं हो सकती है, लेकिन बड़ी परियोजनाओं में यह एक बड़ी बात है।

बस स्पष्ट होने के लिए, फायदे जैसे कि मैं उन्हें देखता हूं: 1) कोड के रूट पर एक स्थान पर सभी नए बयान। 2) एक परिवर्तन के साथ पूरी तरह से फिर से कारक कोड। 3) 'कूल फैक्टर' के लिए अतिरिक्त बिंदु यह कारण है ... अच्छी तरह से: अच्छा। : p


1

मैं यह जानने की कोशिश करूंगा कि आईओसी मेरे नजरिए से अच्छा क्यों नहीं हो सकता है।

सब कुछ के साथ के रूप में, IOC कंटेनर (या जैसा कि आइंस्टीन इसे I = OC ^ 2 होगा) एक अवधारणा है जिसे आपको अपने लिए तय करना होगा कि आपको इसकी आवश्यकता है या नहीं। हाल ही में आईओसी के बारे में फैशन आउटरीच केवल यही है, फैशन। फैशन के लिए मत गिरो, वह पहले है। वहाँ अवधारणाओं के असंख्य हैं वहाँ आप अपने कोड में लागू कर सकते हैं। सबसे पहले, मैं निर्भरता इंजेक्शन का उपयोग कर रहा हूं क्योंकि मैंने प्रोग्रामिंग शुरू कर दी है, और इस शब्द के तहत लोकप्रिय होने पर शब्द ही सीखा है। निर्भरता नियंत्रण एक बहुत पुराना विषय है और इसे अब तक खरबों तरीकों से संबोधित किया गया है, जो इस बात पर निर्भर करता है कि किस चीज से क्या डिकॉय किया गया था। हर चीज को हर चीज से अलग करना एक बकवास है। IOC कंटेनर के साथ समस्या यह है कि यह Entity Framework या NHibernate जितना उपयोगी है। ऑब्जेक्ट-रिलेशनल मैपर लिखते समय बस इतना ही करना चाहिए जैसे ही आपको अपने सिस्टम के साथ किसी भी डेटाबेस को जोड़ना है, आईओसी कंटेनर हमेशा आवश्यक नहीं है। इसलिए जब IOC कंटेनर उपयोगी हो:

  1. जब आपके पास कई निर्भरताओं के साथ एक स्थिति है जिसे आप व्यवस्थित करना चाहते हैं
  2. जब आप अपने कोड को तीसरे पक्ष के उत्पाद के साथ युग्मित करने की परवाह नहीं करते हैं
  3. जब आपके डेवलपर्स सीखना चाहते हैं कि नए टूल के साथ कैसे काम करें

1: ऐसा नहीं है कि अक्सर आपके पास अपने कोड में बहुत अधिक निर्भरता होती है, या आप उन्हें डिजाइन के बारे में जल्दी जानते हैं। सार सोच के कारण सार सोच उपयोगी है।

2: अपने कोड को तृतीय-पक्ष कोड के साथ युग्मित करना एक HuGe समस्या है। मैं उस कोड के साथ काम कर रहा था जो 10+ वर्ष पुराना है और उस समय फैंसी और उन्नत अवधारणाओं ATL, COM, COM + इत्यादि का अनुसरण कर रहा था। अब आप उस कोड के साथ कुछ भी नहीं कर सकते हैं। मैं जो कह रहा हूं वह यह है कि एक उन्नत अवधारणा एक स्पष्ट लाभ देती है, फिर भी यह लंबे समय तक पुराने लाभ के साथ ही रद्द कर दिया जाता है। यह सिर्फ यह सब और अधिक महंगा बना दिया था।

3: सॉफ्टवेयर विकास काफी कठिन है। यदि आप कुछ उन्नत अवधारणा को अपने कोड में क्रॉप करने देते हैं तो आप इसे पहचानने योग्य स्तर तक बढ़ा सकते हैं। IOC2 के साथ एक समस्या है। हालाँकि यह निर्भरता को कम कर रहा है, यह तर्क प्रवाह को भी कम कर रहा है। कल्पना कीजिए कि आपको एक बग मिल गया है और आपको स्थिति की जांच करने के लिए एक ब्रेक सेट करने की आवश्यकता है। IOC2, किसी भी अन्य उन्नत अवधारणा के रूप में, इसे और अधिक कठिन बना रहा है। एक अवधारणा के भीतर बग को ठीक करना एक सादे कोड में बग को ठीक करने की तुलना में अधिक कठिन है, क्योंकि जब आप बग को ठीक करते हैं तो एक अवधारणा को फिर से पालन करना होगा। (बस आपको एक उदाहरण देने के लिए, C ++ .NET सिंटैक्स को लगातार इतना बदल रहा है कि आपको .NET के कुछ पुराने संस्करण को रिफलेक्टर करने से पहले आपको कठिन सोचने की आवश्यकता है।) तो IOC के साथ समस्या क्या है? समस्या निर्भरता को हल करने में है। हल करने का तर्क आमतौर पर IOC2 में ही छिपा होता है, शायद असामान्य तरीके से लिखा जाए जिसे आपको सीखने और बनाए रखने की आवश्यकता है। क्या आपका तृतीय-पक्ष उत्पाद 5 वर्षों में होगा? Microsoft का नहीं था।

"हम जानते हैं कि कैसे" IOC2 के बारे में सभी जगह सिंड्रोम लिखा गया है। यह स्वचालन परीक्षण के समान है। पहली नज़र में फैंसी शब्द और सही समाधान, आप बस रात को निष्पादित करने और सुबह परिणाम देखने के लिए अपने सभी परीक्षण डालते हैं। कंपनी के बाद कंपनी की व्याख्या करना वास्तव में दर्दनाक है कि स्वचालित परीक्षण का वास्तव में क्या मतलब है। स्वचालित परीक्षण निश्चित रूप से बग की संख्या को कम करने का एक त्वरित तरीका नहीं है जिसे आप अपने उत्पाद की गुणवत्ता बढ़ाने के लिए रात भर में पेश कर सकते हैं। लेकिन, फैशन उस धारणा को कष्टप्रद बना रहा है। IOC2 एक ही सिंड्रोम से ग्रस्त है। यह माना जाता है कि आपके सॉफ़्टवेयर को अच्छा बनाने के लिए आपको इसे लागू करने की आवश्यकता है। हाल ही में साक्षात्कार से पूछा गया कि क्या मैं IOC2 और स्वचालन को लागू कर रहा हूं। यह फैशन का संकेत है: कंपनी के पास MFC में लिखे गए कोड का कुछ हिस्सा था जिसे वे नहीं छोड़ेंगे।

आपको IOC2 को सॉफ़्टवेयर में किसी अन्य अवधारणा के रूप में सीखना होगा। यदि IOC2 का उपयोग करने की आवश्यकता है तो निर्णय टीम और कंपनी के भीतर है। हालाँकि, निर्णय किए जाने से पहले कम से कम सभी उपरोक्त तर्कों का उल्लेख किया जाना चाहिए। केवल अगर आप देखते हैं कि प्लस साइड नकारात्मक पक्ष से आगे निकल जाता है, तो आप सकारात्मक निर्णय ले सकते हैं।

IOC2 के साथ कुछ भी गलत नहीं है, सिवाय इसके कि यह केवल उन समस्याओं को हल करता है जो इसे हल करती है और उन समस्याओं का परिचय देती है जो इसे प्रस्तुत करती है। और कुछ नहीं। हालांकि, फैशन के खिलाफ जाना बहुत मुश्किल है, उनके पास पसीना है, किसी भी चीज के अनुयायी। यह अजीब है कि उनमें से कोई भी कैसे नहीं है जब उनके बेहोशी के साथ समस्या स्पष्ट हो जाती है। सॉफ्टवेयर उद्योग में कई अवधारणाओं का बचाव किया गया है क्योंकि वे लाभ पैदा करते हैं, किताबें लिखी जाती हैं, सम्मेलन आयोजित किए जाते हैं, नए उत्पाद बनाए जाते हैं। यह फैशन है, आमतौर पर कम रहता है। जैसे ही लोगों को कुछ और मिलता है वे इसे पूरी तरह से त्याग देते हैं। IOC2 उपयोगी है लेकिन यह वही संकेत दिखाता है जो मैंने देखा है कई अन्य गायब हो गए हैं। मुझे नहीं पता कि यह बच पाएगा या नहीं। उसके लिए कोई नियम नहीं है। आपको लगता है कि अगर यह उपयोगी है, तो यह जीवित रहेगा। नहीं, यह उस तरह से नहीं जाता है। एक बड़ी समृद्ध कंपनी पर्याप्त है और अवधारणा कुछ हफ्तों के भीतर मर सकती है। हम देखेंगे। NHibernate बच गया, EF दूसरे स्थान पर आया। शायद IOC2 भी बच जाएगा। यह मत भूलो कि सॉफ्टवेयर विकास में अधिकांश अवधारणाएं कुछ खास नहीं हैं, वे बहुत तार्किक, सरल और स्पष्ट हैं, और कभी-कभी वर्तमान नामकरण सम्मेलन को याद रखना अधिक कठिन होता है, क्योंकि यह अवधारणा को समझने के लिए ही है। क्या IOC2 का ज्ञान किसी डेवलपर को बेहतर डेवलपर बनाता है? नहीं, क्योंकि अगर कोई डेवलपर IOC2 की प्रकृति के समान अवधारणा के साथ आने में सक्षम नहीं था, तो उसके लिए यह समझना मुश्किल होगा कि IOC2 किस समस्या को हल कर रहा है, इसका उपयोग करना कृत्रिम लगेगा और वह इसका उपयोग करना शुरू कर सकता है राजनीतिक रूप से सही होने के लिए। यह मत भूलो कि सॉफ्टवेयर विकास में अधिकांश अवधारणाएं कुछ खास नहीं हैं, वे बहुत तार्किक, सरल और स्पष्ट हैं, और कभी-कभी वर्तमान नामकरण सम्मेलन को याद रखना अधिक कठिन होता है, क्योंकि यह अवधारणा को समझने के लिए ही है। क्या IOC2 का ज्ञान किसी डेवलपर को बेहतर डेवलपर बनाता है? नहीं, क्योंकि अगर कोई डेवलपर IOC2 की प्रकृति के समान अवधारणा के साथ आने में सक्षम नहीं था, तो उसके लिए यह समझना मुश्किल होगा कि IOC2 किस समस्या को हल कर रहा है, इसका उपयोग करना कृत्रिम लगेगा और वह इसका उपयोग करना शुरू कर सकता है राजनीतिक रूप से सही होने के लिए। यह मत भूलो कि सॉफ्टवेयर विकास में अधिकांश अवधारणाएं कुछ खास नहीं हैं, वे बहुत तार्किक, सरल और स्पष्ट हैं, और कभी-कभी वर्तमान नामकरण सम्मेलन को याद रखना अधिक कठिन होता है, क्योंकि यह अवधारणा को समझने के लिए ही है। क्या IOC2 का ज्ञान किसी डेवलपर को बेहतर डेवलपर बनाता है? नहीं, क्योंकि अगर कोई डेवलपर IOC2 की प्रकृति के समान अवधारणा के साथ आने में सक्षम नहीं था, तो उसके लिए यह समझना मुश्किल होगा कि IOC2 किस समस्या को हल कर रहा है, इसका उपयोग करना कृत्रिम लगेगा और वह इसका उपयोग करना शुरू कर सकता है राजनीतिक रूप से सही होने के लिए। क्या IOC2 का ज्ञान किसी डेवलपर को बेहतर डेवलपर बनाता है? नहीं, क्योंकि अगर कोई डेवलपर IOC2 की प्रकृति के समान अवधारणा के साथ आने में सक्षम नहीं था, तो उसके लिए यह समझना मुश्किल होगा कि IOC2 किस समस्या को हल कर रहा है, इसका उपयोग करना कृत्रिम लगेगा और वह इसका उपयोग करना शुरू कर सकता है राजनीतिक रूप से सही होने के लिए। क्या IOC2 का ज्ञान किसी डेवलपर को बेहतर डेवलपर बनाता है? नहीं, क्योंकि अगर कोई डेवलपर IOC2 की प्रकृति के समान अवधारणा के साथ आने में सक्षम नहीं था, तो उसके लिए यह समझना मुश्किल होगा कि IOC2 किस समस्या को हल कर रहा है, इसका उपयोग करना कृत्रिम लगेगा और वह इसका उपयोग करना शुरू कर सकता है राजनीतिक रूप से सही होने के लिए।


0

व्यक्तिगत रूप से, मैं अपने आवेदन के ढांचे के नक्शे के कुछ प्रकार के रूप में IoC का उपयोग करता हूं (हाँ, मैं भी संरचना मानचित्र पसंद करता हूं;))। परीक्षणों के दौरान Moq कार्यान्वयन के साथ मेरे ussual इंटरफ़ेस कार्यान्वयन को प्रतिस्थापित करना आसान बनाता है। एक परीक्षण सेटअप बनाना मेरे IoC- फ्रेमवर्क में एक नया इन-कॉल बनाने के रूप में आसान हो सकता है, जो भी वर्ग को प्रतिस्थापित करता है वह एक मॉक के साथ मेरी परीक्षण-सीमा है।

यह शायद IoC के लिए नहीं है, लेकिन यह वही है जो मैं खुद को सबसे ज्यादा इस्तेमाल कर पाता हूं।




0

मुझे लगता है कि यह एक पुरानी पोस्ट है, लेकिन यह अभी भी यथोचित रूप से सक्रिय है, और मैंने सोचा कि मैं कुछ ऐसे बिंदुओं का योगदान करूंगा जिनका अभी तक अन्य उत्तरों में उल्लेख नहीं किया गया है।

मैं कहूंगा कि मैं निर्भरता इंजेक्शन के लाभों से सहमत हूं, लेकिन मैं अपने जवाब में Maxm007 द्वारा उल्लिखित उस पैटर्न का उपयोग न करके स्वयं वस्तुओं का निर्माण और प्रबंधन करना पसंद करता हूं। मुझे 3 पार्टी कंटेनर का उपयोग करने के साथ दो मुख्य समस्याएं मिली हैं:

1) एक 3 पार्टी लाइब्रेरी होने से आपकी वस्तुओं के जीवनकाल का प्रबंधन "आटोमैटिकली" हो सकता है जो खुद को अप्रत्याशित परिणामों के लिए उधार दे सकता है। हमने पाया है कि विशेष रूप से बड़ी परियोजनाओं में, आप अपनी अपेक्षा की तुलना में किसी वस्तु की बहुत अधिक प्रतियां प्राप्त कर सकते हैं, और यदि आप मैन्युअल रूप से जीवन चक्र का प्रबंधन कर रहे हैं तो इससे भी अधिक। मुझे यकीन है कि यह उपयोग किए गए ढांचे के आधार पर भिन्न होता है, लेकिन समस्या फिर भी मौजूद है। यह समस्याग्रस्त भी हो सकता है यदि आपकी वस्तु संसाधन, डेटा कनेक्शन आदि रखती है, क्योंकि वस्तु कभी-कभी आपकी अपेक्षा से अधिक समय तक रह सकती है। इसलिए अनिवार्य रूप से, आईओसी कंटेनर एक आवेदन के संसाधन उपयोग और स्मृति पदचिह्न को बढ़ाते हैं।

2) IoC कंटेनर, मेरी राय में, "ब्लैक बॉक्स प्रोग्रामिंग" का एक रूप है। मैंने पाया है कि विशेष रूप से, हमारे कम अनुभवी डेवलपर्स उनका दुरुपयोग करते हैं। यह प्रोग्रामर को यह सोचने की अनुमति नहीं देता है कि वस्तुओं को एक-दूसरे से कैसे संबंधित होना चाहिए या उन्हें कैसे अलग करना चाहिए, क्योंकि यह उन्हें एक तंत्र प्रदान करता है जिसमें वे किसी भी वस्तु को पतली हवा से बाहर निकालना चाहते हैं। उदाहरण के लिए, एक अच्छा डिज़ाइन कारण हो सकता है कि ObjectA को कभी भी ObjectB के बारे में सीधे पता नहीं होना चाहिए, बल्कि एक कारखाना या पुल या सर्विस लोकेटर बनाने के बजाय, एक अनुभवहीन प्रोग्रामर बस "कोई बात नहीं" कहेगा, मैं सिर्फ IoC कंटेनर से ObjectB हड़प लूंगा "। यह वास्तव में बढ़ी हुई वस्तु युग्मन को जन्म दे सकता है, जो कि आईओसी को रोकने में मदद करने वाला है।


-8

ASP.NET प्रोजेक्ट में निर्भरता इंजेक्शन कोड की कुछ पंक्तियों के साथ पूरा किया जा सकता है। मुझे लगता है कि कंटेनर का उपयोग करने पर कुछ लाभ होता है जब आपके पास एक ऐप होता है जो कई फ्रंट एंड का उपयोग करता है और यूनिट परीक्षणों की आवश्यकता होती है।


1
क्या आप एक उदाहरण दे सकते हैं? किसी अन्य एप्लिकेशन प्रकार की तुलना में ASP.NET में DI कैसे भिन्न है?
टॉफी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.