निर्भरता इंजेक्शन बनाम स्टेटिक तरीके


21

मैंने एक और डेवलपर के साथ आज एक दिलचस्प चर्चा की कि किस तरह से एक विधि के साथ एक वर्ग से संपर्क करें जो एक स्ट्रिंग को स्वीकार करता है और स्ट्रिंग को आउटपुट करता है।

निम्नलिखित की तरह कुछ कल्पना कीजिए जो पूरी तरह से उदाहरण के उद्देश्य से बनाई गई है

public string GetStringPart(string input)
{ 
   //Some input validation which is removed for clarity

   if(input.Length > 5)
        return input.Substring(0,1);

   if(input.Substring(0,1) == "B")
        return input.Substring(0,3);

   return string.empty;
}

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


1
@ ईवन सहायक विधियों के लिए जिनके पास अमूर्तता के लिए कोई उपयोग नहीं है। उदाहरण: अपाचे FileUtils।
Walfrat

3
@ ईवान: साइड इफेक्ट्स के बिना स्थिर तरीके सबसे अच्छे तरीके हैं, क्योंकि वे समझने में सरल और परीक्षण करने में सरल हैं।
जैक्सबी

1
लेकिन वे उन चीजों का परीक्षण करना असंभव बना देते हैं जो उन पर निर्भर करती हैं
इवान

3
@ इवान एह, वास्तव में नहीं। क्या Math.Max ​​() खराब है क्योंकि यह स्थिर है? यदि आप अपनी स्थैतिक विधि का परीक्षण करते हैं और यह काम कर रहा है, तो आप इसे बिना मुद्दों के अपने अन्य तरीकों पर सुरक्षित रूप से उपयोग कर सकते हैं। यदि स्थिर एक विफल हो रहा है, तो इसका परीक्षण इसे पकड़ लेगा।
टी। सार -

1
अगर 'स्टेटिक' ने बिना किसी साइड इफेक्ट की गारंटी दी हो, तो मैं तर्क को देखने में सक्षम हो सकता हूँ। लेकिन यह नहीं है।
इवान

जवाबों:


25

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

कोई निर्भरता के साथ कार्यों को अमूर्त करने की आवश्यकता नहीं है, यह ओवरकिल है।

यदि यह अधिक जटिल हो जाता है, तो हो सकता है कि एक निर्माणकर्ता या विधि में एक इंटरफ़ेस गुजर रहा है। लेकिन, मैं उस सड़क से नीचे नहीं जाऊंगा जब तक कि मेरे पास GetStringPartस्थान आदि के आधार पर जटिल तर्क न हों ।


2
यह सही जवाब है! खराब करने के लिए कार्गो-पंथ के उत्तर को स्वीकार किया गया है।
जैक्सबीबी

3
इस समारोह में कोई निर्भरता नहीं है कि बात नहीं है। समस्या यह है कि जब अन्य चीजें फ़ंक्शन पर निर्भर करती हैं और इसे कसकर युग्मित हो जाती हैं
इवान

2
क्या होगा यदि फ़ंक्शन 6 महीने में बदल जाता है और इतना शुद्ध नहीं होता है, लेकिन यह पहले से ही बहुत सारे स्थानों में उपयोग किया जाता है। यह एक स्टेटिक के रूप में एक्स्टेंसिबल नहीं है और यह ऐसी चीज भी नहीं है जिसे क्लास यूनिट टेस्ट के सेवन से अलग किया जा सकता है। अगर बदलाव का थोड़ा सा भी मौका है तो मैं इसे इंजेक्ट करने जाऊंगा। उस ने कहा, मैं विरोधी तर्कों को सुनने के लिए तैयार हूं, यही इस पद की बात है। यह इंजेक्शन के लिए डाउनसाइड क्या हैं और स्थैतिक की सकारात्मकता?
जेम्स

1
सामान्यतया, इस वेब-साइट पर निर्भरता इंजेक्शन पर चर्चा करने वाले लोगों को निर्भरता इंजेक्शन की आवश्यकता नहीं है। इसलिए अनावश्यक जटिलता की ओर पूर्वाग्रह।
फ्रैंक हिलमैन

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

12

यहाँ पर क्यों

class DOSClient {
    OrderParser orderParser;
    string orderCode;

    DOSClient(OrderParser orderParser, string ordercode) { 
        this.orderParser = orderParser; 
        this.ordercode = ordercode;
    }
    void DisplayOrderCode() {
        Console.Write( "Prefix: " + orderParser.GetStringPart(ordercode) ); 
        ...
    }
}

class GUIClient {
    OrderParser orderParser;
    string orderCode;
    GUI gui;

    GUIClient(OrderParser orderParser, string ordercode, GUI gui) { 
        this.orderParser = orderParser; 
        this.ordercode = ordercode;
        this.gui = gui;
    }

    void DisplayOrderCode() {
        gui.Prefix( orderParser.GetStringPart(ordercode) ); 
        ...
    }
}

 

class OrderParserUS : IOrderParser {

    public string GetStringPart(string input)
    { 
        //Some input validation which is removed for clarity

        if(input.Length > 5)
            return input.Substring(0,1);

        if(input.Substring(0,1) == "B")
            return input.Substring(0,3);

        return string.empty;
    }
}

class OrderParserEU : IOrderParser {

    public string GetStringPart(string input)
    { 
        //Some input validation which is removed for clarity

        if(input.Length > 6)
            return input.Substring(0,1);

        if(input.Substring(0,1) == "#")
            return input.Substring(0,3);

        return string.empty;
    }
}

यदि आप एक स्थिर पद्धति के साथ गए थे, GetStringPartतो पुराने व्यवहार को नष्ट किए बिना या सशर्त तर्क के साथ इसे प्रदूषित किए बिना व्यवहार को बदलने का कोई तरीका नहीं होगा । यह सच है कि स्टेटिक्स भेस में बुरी ग्लोबल्स हैं, लेकिन यह तथ्य कि वे बहुरूपता को निष्क्रिय करते हैं, उनके बारे में मेरी मुख्य शिकायत है। OOP भाषाओं में स्टेटिक तरीके प्रथम श्रेणी के नहीं हैं। इस पद्धति को रहने के लिए एक वस्तु देकर, यहां तक ​​कि बिना किसी राज्य के, हम विधि को पोर्टेबल बनाते हैं। इसके व्यवहार को एक चर के मान की तरह पास किया जा सकता है।

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

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

BTW, GetStringPartएक भयानक नाम है।


* कोष्ठक कोड शैली में स्ट्रिंग * मैं अनुमान लगा रहा हूं कि आप एक जावा प्रोग्रामर हैं जो सी # कोड लिखने की कोशिश कर रहे हैं? मुझे लगता है कि एक को जानने के लिए एक लेता है। :)
नील

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

परीक्षण एक कारण है लेकिन और भी हैं। मुझे यह परीक्षण करने के लिए दोषी ठहराना ज्यादा पसंद नहीं है क्योंकि यह सिर्फ परीक्षण की आलोचना करने वाले लोगों को शुरू करता है। यदि आप प्रक्रियात्मक रूप से कार्यक्रम नहीं करते हैं तो सरल तथ्य प्रक्रियात्मक प्रोग्रामर है।
कैंडिड_ऑरेंज

आप बस नहीं कह सकते static getStringPartEU()? आपका उदाहरण केवल तभी समझ में आता है जब उस वर्ग में अन्य विधियां हैं जिनके लिए विशिष्ट यूरोपीय संघ उपचार की भी आवश्यकता होती है और उन्हें एक इकाई के रूप में माना जाता है।
रॉबर्ट हार्वे

2
आप निश्चित रूप से अनावश्यक जटिलता के पक्ष में बहस कर रहे हैं। हर चीज में ज्यादा से ज्यादा कोड जोड़ा जा सकता है। जिन चीजों को बदलने की आवश्यकता है, उन्हें संशोधित करना आसान होना चाहिए, लेकिन आपको यह भविष्यवाणी करने की कोशिश नहीं करनी चाहिए कि भविष्य में क्या बदलना चाहिए। स्थैतिक क्षेत्र वैश्विक चर के समान हो सकते हैं, लेकिन स्थिर विधियां शुद्ध हो सकती हैं, सबसे अच्छा संभव प्रकार की विधि।
फ्रैंक हिलमैन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.