चलो एक सरल उदाहरण लेते हैं - शायद आप लॉगिंग के एक साधन को इंजेक्ट कर रहे हैं।
एक कक्षा में प्रवेश करना
class Worker: IWorker
{
ILogger _logger;
Worker(ILogger logger)
{
_logger = logger;
}
void SomeMethod()
{
_logger.Debug("This is a debug log statement.");
}
}
मुझे लगता है कि यह बहुत स्पष्ट है कि क्या चल रहा है। यदि आप एक IoC कंटेनर का उपयोग कर रहे हैं तो अधिक क्या है, आपको स्पष्ट रूप से कुछ भी इंजेक्ट करने की आवश्यकता नहीं है, आप बस अपनी रचना रूट में जोड़ सकते हैं:
container.RegisterType<ILogger, ConcreteLogger>();
container.RegisterType<IWorker, Worker>();
....
var worker = container.Resolve<IWorker>();
जब डिबगिंग Worker
, डेवलपर को यह निर्धारित करने के लिए कि क्या ठोस वर्ग का उपयोग किया जा रहा है, रचना रूट से परामर्श करने की आवश्यकता है।
यदि किसी डेवलपर को अधिक जटिल तर्क की आवश्यकता होती है, तो उसके पास काम करने के लिए संपूर्ण इंटरफ़ेस है:
void SomeMethod()
{
if (_logger.IsDebugEnabled) {
_logger.Debug("This is a debug log statement.");
}
}
एक विधि का इंजेक्शन लगाना
class Worker
{
Action<string> _methodThatLogs;
Worker(Action<string> methodThatLogs)
{
_methodThatLogs = methodThatLogs;
}
void SomeMethod()
{
_methodThatLogs("This is a logging statement");
}
}
सबसे पहले, ध्यान दें कि कंस्ट्रक्टर पैरामीटर का अब एक लंबा नाम है methodThatLogs
,। यह आवश्यक है क्योंकि आप यह नहीं बता सकते कि क्या Action<string>
करना चाहिए। इंटरफ़ेस के साथ, यह पूरी तरह से स्पष्ट था, लेकिन यहां हमें पैरामीटर के नामकरण पर भरोसा करना होगा। यह एक निर्माण के दौरान लागू करने के लिए स्वाभाविक रूप से कम विश्वसनीय और कठिन लगता है।
अब, हम इस विधि को कैसे इंजेक्ट करते हैं? खैर, IoC कंटेनर आपके लिए ऐसा नहीं करेगा। इसलिए जब आप तुरंत करते हैं तो आप इसे स्पष्ट रूप से इंजेक्ट करते हैं Worker
। यह कुछ समस्याओं को जन्म देता है:
- यह तत्काल काम करने के लिए अधिक है
Worker
- डिबग करने का प्रयास करने वाले डेवलपर्स को
Worker
यह पता लगाना अधिक कठिन होगा कि ठोस उदाहरण को क्या कहा जाता है। वे सिर्फ रचना जड़ से परामर्श नहीं कर सकते हैं; उन्हें कोड के माध्यम से ट्रेस करना होगा।
कैसे के बारे में अगर हम और अधिक जटिल तर्क की आवश्यकता है? आपकी तकनीक केवल एक विधि को उजागर करती है। अब मुझे लगता है कि आप लैम्ब्डा में जटिल सामान सेंकना कर सकते हैं:
var worker = new Worker((s) => { if (log.IsDebugEnabled) log.Debug(s) } );
लेकिन जब आप अपनी इकाई परीक्षण लिख रहे हैं, तो आप उस लंबोदर अभिव्यक्ति का परीक्षण कैसे करते हैं? यह गुमनाम है, इसलिए आपकी इकाई परीक्षण रूपरेखा इसे सीधे नहीं भेज सकती है। हो सकता है कि आप इसे करने के लिए कुछ चतुर तरीका समझ सकते हैं, लेकिन यह शायद इंटरफ़ेस का उपयोग करने की तुलना में एक बड़ा पीआईटीए होगा।
मतभेदों का सारांश:
- केवल एक विधि का इंजेक्शन लगाने से उद्देश्य का अनुमान लगाना कठिन हो जाता है, जबकि एक इंटरफ़ेस स्पष्ट रूप से उद्देश्य का संचार करता है।
- केवल एक विधि इंजेक्ट करने से इंजेक्शन प्राप्त करने वाले वर्ग को कम कार्यक्षमता उजागर होती है। यहां तक कि अगर आपको आज इसकी आवश्यकता नहीं है, तो आपको कल इसकी आवश्यकता हो सकती है।
- आप केवल IoC कंटेनर का उपयोग करके स्वचालित रूप से केवल एक विधि इंजेक्ट नहीं कर सकते हैं।
- आप किसी विशेष उदाहरण में रचना की जड़ से नहीं बता सकते हैं कि कौन सा ठोस वर्ग काम में है।
- यह एक समस्या है जो लैम्बडा एक्सप्रेशन को स्वयं जांचने की इकाई है।
यदि आप उपरोक्त सभी के साथ ठीक हैं, तो बस विधि को इंजेक्ट करना ठीक है। नहीं तो मेरा सुझाव है कि आप परंपरा के साथ रहें और एक इंटरफ़ेस इंजेक्ट करें।