मुझे लगता है कि दोनों के बीच अंतर को समझने का सबसे आसान तरीका है और एक सेवा लोकेटर की तुलना में डीआई कंटेनर इतना बेहतर क्यों है, इस बारे में सोचना है कि हम पहले स्थान पर निर्भरता उलटा क्यों करते हैं।
हम निर्भरता उलटा करते हैं ताकि प्रत्येक वर्ग स्पष्ट रूप से बताए कि यह ऑपरेशन के लिए किस पर निर्भर है । हम ऐसा इसलिए करते हैं क्योंकि यह हमारे द्वारा प्राप्त किए जा सकने वाले सबसे कम युग्मन का निर्माण करता है। युग्मन को कम करने वाला, कुछ आसान परीक्षण और रिफ्लेक्टर है (और आमतौर पर भविष्य में कम से कम रिफैक्टिंग की आवश्यकता होती है क्योंकि कोड क्लीनर है)।
आइए निम्न वर्ग को देखें:
public class MySpecialStringWriter
{
private readonly IOutputProvider outputProvider;
public MySpecialFormatter(IOutputProvider outputProvider)
{
this.outputProvider = outputProvider;
}
public void OutputString(string source)
{
this.outputProvider.Output("This is the string that was passed: " + source);
}
}
इस वर्ग में, हम स्पष्ट रूप से कह रहे हैं कि हमें IOutputProvider की आवश्यकता है और इस वर्ग को काम करने के लिए और कुछ नहीं चाहिए। यह पूरी तरह से परीक्षण योग्य है और एकल इंटरफ़ेस पर निर्भरता है। मैं अपने आवेदन में इस वर्ग को कहीं भी स्थानांतरित कर सकता हूं, जिसमें एक अलग परियोजना भी शामिल है और इसे IOutputProvider इंटरफ़ेस तक पहुंच की आवश्यकता है। यदि अन्य डेवलपर्स इस वर्ग में कुछ नया जोड़ना चाहते हैं, जिसके लिए एक दूसरी निर्भरता की आवश्यकता होती है, तो उन्हें इस बारे में स्पष्ट होना होगा कि उन्हें निर्माणकर्ता में इसकी क्या आवश्यकता है।
सेवा लोकेटर के साथ एक ही वर्ग को देखें:
public class MySpecialStringWriter
{
private readonly ServiceLocator serviceLocator;
public MySpecialFormatter(ServiceLocator serviceLocator)
{
this.serviceLocator = serviceLocator;
}
public void OutputString(string source)
{
this.serviceLocator.OutputProvider.Output("This is the string that was passed: " + source);
}
}
अब मैंने सेवा लोकेटर को निर्भरता के रूप में जोड़ा है। यहाँ समस्याएं हैं जो तुरंत स्पष्ट हैं:
- इसके साथ पहली समस्या यह है कि समान परिणाम प्राप्त करने में अधिक कोड लगते हैं । अधिक कोड खराब है। यह बहुत अधिक कोड नहीं है, लेकिन यह अभी भी अधिक है।
- दूसरी समस्या यह है कि मेरी निर्भरता अब स्पष्ट नहीं है । मुझे अभी भी कक्षा में कुछ इंजेक्ट करने की आवश्यकता है। सिवाय अब जो चीज मुझे चाहिए वह स्पष्ट नहीं है। यह उस चीज़ की संपत्ति में छिपा है जिसे मैंने अनुरोध किया था। अगर मुझे कक्षा को एक अलग असेंबली में ले जाना है तो अब मुझे ServiceLocator और IOutputProvider दोनों की पहुँच की आवश्यकता है।
- तीसरी समस्या यह है कि एक अन्य डेवलपर द्वारा एक अतिरिक्त निर्भरता ली जा सकती है, जो यह महसूस नहीं करते हैं कि वे इसे तब ले रहे हैं जब वे कक्षा में कोड जोड़ते हैं।
- अंत में, इस कोड का परीक्षण करना कठिन है (भले ही ServiceLocator एक इंटरफ़ेस है) क्योंकि हमें केवल IOutputProvider के बजाय ServiceLocator और IOutputProvider को मॉक करना होगा
तो हम सेवा लोकेटर को एक स्थिर वर्ग क्यों नहीं बनाते हैं? चलो एक नज़र डालते हैं:
public class MySpecialStringWriter
{
public void OutputString(string source)
{
ServiceLocator.OutputProvider.Output("This is the string that was passed: " + source);
}
}
यह बहुत सरल है, है ना?
गलत।
बता दें कि IOutputProvider बहुत लंबे समय से चल रही वेब सेवा द्वारा कार्यान्वित किया जाता है जो दुनिया भर के पंद्रह अलग-अलग डेटाबेस में स्ट्रिंग लिखती है और पूरा होने में बहुत लंबा समय लेती है।
आइए इस वर्ग का परीक्षण करने का प्रयास करें। हमें परीक्षण के लिए IOutputProvider के एक अलग कार्यान्वयन की आवश्यकता है। हम परीक्षण कैसे लिखते हैं?
अच्छी तरह से करने के लिए हमें IOutputProvider के एक अलग कार्यान्वयन का उपयोग करने के लिए स्थिर ServiceLocator वर्ग में कुछ फैंसी कॉन्फ़िगरेशन करने की आवश्यकता है, जब इसे परीक्षण द्वारा बुलाया जा रहा है। उस वाक्य को लिखना भी दर्दनाक था। इसे लागू करना अत्याचारपूर्ण होगा और यह एक बुरा सपना होगा । हमें विशेष रूप से परीक्षण के लिए एक वर्ग को संशोधित करने की आवश्यकता नहीं होनी चाहिए, खासकर यदि वह वर्ग वह वर्ग नहीं है जिसे हम वास्तव में परखने की कोशिश कर रहे हैं।
तो अब आप या तो साथ छोड़ दिए गए हैं) एक परीक्षण जो असंबंधित ServiceLocator वर्ग में अप्रिय कोड परिवर्तन का कारण बन रहा है; या बी) कोई परीक्षण नहीं। और आप एक कम लचीला समाधान के साथ छोड़ दिया है।
तो सर्विस लोकेटर क्लास को कंस्ट्रक्टर में इंजेक्ट किया जाना है। जिसका अर्थ है कि हम पहले बताई गई विशिष्ट समस्याओं से बचे हैं। सेवा लोकेटर को अधिक कोड की आवश्यकता होती है, अन्य डेवलपर्स को बताता है कि उसे ऐसी चीजों की आवश्यकता है जो इसे नहीं करती है, अन्य डेवलपर्स को बदतर कोड लिखने के लिए प्रोत्साहित करता है और हमें कम लचीलापन देता है।
सीधे शब्दों में कहें तो सर्विस लोकेटर एक आवेदन में युग्मन बढ़ाते हैं और अन्य डेवलपर्स को अत्यधिक युग्मित कोड लिखने के लिए प्रोत्साहित करते हैं ।