2010-11-09 20 views
6

निर्भरता इंजेक्शन का उपयोग करते समय आप निर्भरताओं को इंजेक्ट करते हैं?मुझे किस निर्भरता को इंजेक्ट करना चाहिए?

मैं पहले सभी निर्भरता इंजेक्शन है, लेकिन जब TDD कर पाया है वहाँ आम तौर पर निर्भरता के दो प्रकार हैं:

  • उन जो वास्तविक बाहरी निर्भरता जो जैसे बदल सकते हैं कर रहे हैं ProductRepository
  • जो पूरी तरह से टेस्टेबिलिटी के लिए मौजूद हैं उदा। वर्ग के व्यवहार है कि निकाला गया है और सिर्फ testability
  • के लिए

एक दृष्टिकोण इंजेक्शन का एक हिस्सा इस

public ClassWithExternalDependency(IExternalDependency external, 
    IExtractedForTestabilityDependency internal) 
{ 
    // assign dependencies ... 
} 

की तरह सभी निर्भरता इंजेक्षन करने के लिए है, लेकिन मैं मिल गया है इस में निर्भरता ब्लोट पैदा कर सकता है डी रजिस्ट्री।

एक और दृष्टिकोण इस

public ClassWithExternalDependency(IExternalDependency external) 
    : this (external, new ConcreteClassOfInternalDependency()) 
{} 

internal ClassWithExternalDependency(IExternalDependency external, 
    IExtractedForTestabilityDependency internal) 
{ 
    // assign dependencies ... 
} 

यह और अधिक प्रयास है, लेकिन एक बहुत अधिक समझ बनाने के लिए लगता है "testability निर्भरता" को छिपाने के लिए है। डाउनसाइड सभी ऑब्जेक्ट्स को डी फ्रेमवर्क में कॉन्फ़िगर नहीं किया गया है, जिससे मैंने सुना है कि "सर्वोत्तम अभ्यास" तोड़ रहा है।

आप किस दृष्टिकोण का समर्थन करेंगे और क्यों?

उत्तर

1

मेरा मानना ​​है कि आप अपनी सभी निर्भरताओं को इंजेक्ट करने से बेहतर हैं। यदि यह थोड़ा अनावश्यक होना शुरू होता है, तो शायद यह संकेत है कि आपको चीजों को थोड़ा सा सरल बनाना या निर्भरता को किसी अन्य वस्तु में ले जाना है। आपके डिजाइन के "दर्द" को महसूस करते हुए आप वास्तव में प्रबुद्ध हो सकते हैं।

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

public class AppModule : NinjectModule 
{ 
    public override void Load() 
    { 
     Bind<IShellPresenter>().To<ShellPresenter>().InSingletonScope(); 

     BindAllResults(); 
     BindAllPresenters(); 
    } 

    /// <summary> 
    /// Automatically bind all presenters that haven't already been manually bound 
    /// </summary> 
    public void BindAllPresenters() 
    { 
     Type[] types = Assembly.GetExecutingAssembly().GetTypes(); 

     IEnumerable<Type> presenterImplementors = 
      from t in types 
      where !t.IsInterface 
      && t.Name.EndsWith("Presenter") 
      select t; 

      presenterImplementors.Run(
       implementationType => 
        { 
         if (!Kernel.GetBindings(implementationType).Any()) 
          Bind(implementationType).ToSelf(); 
        }); 
    } 

यहां तक ​​कि मैं परिणाम और प्रस्तुतकर्ताओं के आसपास चल रहा है के दर्जनों है, हालांकि, मैं उन्हें स्पष्ट रूप से रजिस्टर करने के लिए नहीं है।

0

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

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

+1

निर्भरताओं को बदलने के लाभों में से एक अलगाव में इकाइयों का परीक्षण करने में सक्षम होना है। मैं अलगाव में इसका परीक्षण करने के लिए कैलकुलेटर कक्षा निकाल सकता हूं लेकिन शायद इसे इंजेक्शन की आवश्यकता नहीं है (दूसरा कोड उदाहरण देखें)। मैं इसे सीटू में परीक्षण नहीं कर सका क्योंकि यह कैलकुलेटर वर्ग के क्लाइंट के लिए परीक्षणों को फहराएगा। – Alex

+1

सभी इंजेक्टेबल इंजेक्ट करें, सभी नए नए। इस भेद के बिना, DI को कार्यक्रम की पूरी अवधि के लिए रहने वाली सभी वस्तुओं की आवश्यकता होगी। न्यूबेल, उर्फ ​​वैल्यू टाइप, निष्क्रिय डेटा का प्रतिनिधित्व करते हैं और वैकल्पिक रूप से कुछ संबंधित परिवर्तनीय व्यवहार (यानी वे मान जो मान लेते हैं और नए मान वापस करते हैं)। इंजेक्टेबल्स, उर्फ ​​सेवा/व्यावसायिक प्रकार, कार्यक्षमता का प्रतिनिधित्व करते हैं और वैकल्पिक रूप से कुछ संबंधित प्रोग्राम स्थिति का प्रतिनिधित्व करते हैं। तर्कसंगत रूप से, हमारे पास बाह्य राज्य का प्रतिनिधित्व करने के लिए I/O प्रकार भी हैं, उदा। फ़ाइल()। I/O प्रकारों को नया होना चाहिए लेकिन सार कारखानों के माध्यम से बनाया जाना चाहिए ताकि उन्हें परीक्षण के लिए मजाक किया जा सके। – Jegschemesch

0

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

संबंधित मुद्दे

 संबंधित मुद्दे