मुझे कन्स्ट्रक्टर आधारित निर्भरता इंजेक्शन पसंद नहीं है।निर्भरता इंजेक्शन के लिए एक व्यवहार्य विकल्प?
मेरा मानना है कि यह कोड जटिलता बढ़ाता है और रखरखाव को कम करता है, और मैं जानना चाहता हूं कि क्या कोई व्यवहार्य विकल्प हैं या नहीं।
मैं इंटरफ़ेस से कार्यान्वयन को अलग करने की अवधारणा के बारे में बात नहीं कर रहा हूं, और इंटरफ़ेस से ऑब्जेक्ट्स के सेट को गतिशील रूप से हल करने का एक तरीका है (रिकर्सिव)। मैं पूरी तरह से इसका समर्थन करता हूं। हालांकि, ऐसा करने के पारंपरिक कन्स्ट्रक्टर आधारित तरीके में कुछ समस्याएं हैं।
1) सभी परीक्षण रचनाकारों पर निर्भर करते हैं।
पिछले वर्ष की तुलना एक MVC 3 सी # परियोजना में बड़े पैमाने पर डि इस्तेमाल करने के बाद, मैं इस तरह हमारे कोड चीजों से भरा लगता है:
public interface IMyClass {
...
}
public class MyClass : IMyClass {
public MyClass(ILogService log, IDataService data, IBlahService blah) {
_log = log;
_blah = blah;
_data = data;
}
...
}
समस्या: मैं अपने कार्यान्वयन में किसी अन्य सेवा की जरूरत है मैं को संशोधित करना कन्स्ट्रक्टर; और इसका मतलब है कि इस वर्ग के ब्रेक के लिए सभी यूनिट परीक्षण।
यहां तक कि जिन परीक्षणों के पास नई कार्यक्षमता के साथ कुछ भी नहीं है, कम से कम अतिरिक्त पैरामीटर जोड़ने और उस तर्क के लिए एक नकली इंजेक्शन की आवश्यकता होती है।
यह एक छोटे से मुद्दे की तरह लगता है, और स्वचालित उपकरण जैसे कि रिशेर्पर सहायता, लेकिन यह निश्चित रूप से परेशान होता है जब इस तरह का एक साधारण परिवर्तन 100+ परीक्षणों को तोड़ने का कारण बनता है। व्यावहारिक रूप से बोलते हुए मैंने लोगों को बुलेट चीजों को बुलेट करने के बजाय कन्स्ट्रक्टर बदलने से बचने और यह होने पर सभी परीक्षणों को ठीक करने के लिए देखा है।
2) सेवा उदाहरण अनावश्यक रूप से, कोड जटिलता में वृद्धि के आसपास पारित हो जाते हैं।
public class MyWorker {
public MyWorker(int x, IMyClass service, ILogService logs) {
...
}
}
अगर तभी संभव है अगर मैं एक संदर्भ में, जहां दिए गए सेवाएं उपलब्ध हैं और स्वचालित रूप से हल किया गया है (उदाहरण के लिए। नियंत्रक) या, दुख, कई चेन सेवा उदाहरण नीचे पारित करके अंदर हूँ इस वर्ग का एक उदाहरण बनाना सहायक वर्गों का।
मैं इस की तरह कोड हर समय देखें:
public class BlahHelper {
// Keep so we can create objects later
var _service = null;
public BlahHelper(IMyClass service) {
_service = service;
}
public void DoSomething() {
var worker = new SpecialPurposeWorker("flag", 100, service);
var status = worker.DoSomethingElse();
...
}
}
मामले में उदाहरण स्पष्ट नहीं है, क्या मैं के बारे में बात कर रहा हूँ कोई कारण से कई परतों के माध्यम से हल किया डि इंटरफ़ेस उदाहरणों से गुजर रहा है नीचे नीचे की परत के अलावा उन्हें कुछ इंजेक्ट करने की आवश्यकता है।
यदि कोई कक्षा किसी सेवा पर निर्भर नहीं है, तो उसे उस सेवा पर निर्भरता होनी चाहिए। यह विचार है कि एक 'क्षणिक' निर्भरता है जहां एक वर्ग सेवा का उपयोग नहीं करता है, लेकिन मेरी राय में, बस इसे पास करता है।
हालांकि, मुझे एक बेहतर समाधान के बारे में पता नहीं है।
क्या कोई ऐसी चीज है जो इन समस्याओं के बिना DI के लाभ प्रदान करती है?
public MyClass() {
_log = Register.Get().Resolve<ILogService>();
_blah = Register.Get().Resolve<IBlahService>();
_data = Register.Get().Resolve<IDataService>();
}
वहाँ ऐसा करने के लिए किसी भी नकारात्मक पक्ष यह है:
मैं कंस्ट्रक्टर्स अंदर डि ढांचे का उपयोग कर के बजाय के रूप में इस का समाधान करता है समस्याओं के एक जोड़े पर विचार किया है?
इसका मतलब है कि यूनिट परीक्षणों में परीक्षण के दौरान सही प्रकार के लिए मोक्स बांधने के लिए कक्षा के 'पूर्व ज्ञान' होना चाहिए, लेकिन मैं किसी अन्य डाउनसाइड्स को नहीं देख सकता।
एनबी। मेरे उदाहरण सी # में हैं, लेकिन मैं अन्य भाषाओं में भी एक ही मुद्दे में ठोकर खा गया हूं, और विशेष रूप से कम परिपक्व टूलींग समर्थन वाले भाषाओं में ये प्रमुख सिरदर्द हैं।
यदि आप इसे कन्स्ट्रक्टर के अंदर रखते हैं तो आप प्रयुक्त डी घटक पर निर्भरता बनाते हैं। यदि आप कन्स्ट्रक्टर को इंटरफेस पास करते हैं तो आप डी घटक बदल सकते हैं, एन इंजेक्ट या कैसल इत्यादि के साथ ऑटोफैक कहें। इसलिए यदि आप वास्तव में वास्तव में सुनिश्चित हैं कि आप कभी भी इस्तेमाल किए गए डी घटक को नहीं बदलेंगे और कहें कि ऑटोफैक यह एक बहुत ही व्यवहार्य समाधान है। –