[Dependency-injection] एक निर्भरता इंजेक्शन का उपयोग क्यों करता है?


Answers

मुझे लगता है कि लोग निर्भरता इंजेक्शन और एक निर्भरता इंजेक्शन ढांचे (या एक कंटेनर जिसे अक्सर कहा जाता है) के बीच के अंतर के बारे में उलझन में पड़ जाते हैं।

निर्भरता इंजेक्शन एक बहुत ही सरल अवधारणा है। इस कोड के बजाय:

public class A {
  private B b;

  public A() {
    this.b = new B(); // A *depends on* B
  }

  public void DoSomeStuff() {
    // Do something with B here
  }
}

public static void Main(string[] args) {
  A a = new A();
  a.DoSomeStuff();
}

आप इस तरह कोड लिखते हैं:

public class A {
  private B b;

  public A(B b) { // A now takes its dependencies as arguments
    this.b = b; // look ma, no "new"!
  }

  public void DoSomeStuff() {
    // Do something with B here
  }
}

public static void Main(string[] args) {
  B b = new B(); // B is constructed here instead
  A a = new A(b);
  a.DoSomeStuff();
}

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

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

Question

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

मुझे समझ में नहीं आता कि यह किस समस्या को हल करता है। यह कहने का एक तरीका है: "नमस्ते। जब आप इस फ़ंक्शन में भाग लेते हैं, तो इस प्रकार की ऑब्जेक्ट लौटाएं और इन पैरामीटर / डेटा का उपयोग करें।"
लेकिन ... मैं कभी इसका उपयोग क्यों करूंगा? नोट मुझे object का उपयोग करने के लिए कभी भी आवश्यकता नहीं है, लेकिन मैं समझता हूं कि इसके लिए क्या है।

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




मुझे लगता है कि क्लासिक उत्तर एक अधिक decoupled आवेदन बनाने के लिए है, जिसका कोई ज्ञान नहीं है कि रनटाइम के दौरान किस कार्यान्वयन का उपयोग किया जाएगा।

उदाहरण के लिए, हम एक केंद्रीय भुगतान प्रदाता हैं, जो दुनिया भर के कई भुगतान प्रदाताओं के साथ काम करते हैं। हालांकि, जब कोई अनुरोध किया जाता है, तो मुझे नहीं पता कि कौन सा भुगतान प्रोसेसर मैं कॉल करने जा रहा हूं। मैं एक वर्ग के स्विच मामलों के एक टन के साथ प्रोग्राम कर सकता हूं, जैसे कि:

class PaymentProcessor{

    private String type;

    public PaymentProcessor(String type){
        this.type = type;
    }

    public void authorize(){
        if (type.equals(Consts.PAYPAL)){
            // Do this;
        }
        else if(type.equals(Consts.OTHER_PROCESSOR)){
            // Do that;
        }
    }
}

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

class PaypalProcessor implements PaymentProcessor{

    public void authorize(){
        // Do PayPal authorization
    }
}

class OtherProcessor implements PaymentProcessor{

    public void authorize(){
        // Do other processor authorization
    }
}

class PaymentFactory{

    public static PaymentProcessor create(String type){

        switch(type){
            case Consts.PAYPAL;
                return new PaypalProcessor();

            case Consts.OTHER_PROCESSOR;
                return new OtherProcessor();
        }
    }
}

interface PaymentProcessor{
    void authorize();
}

** कोड संकलित नहीं होगा, मुझे पता है :)