11

पर त्रुटियों की जांच करें मेरे पास एक साधारण सवाल है।आईओसी कंटेनर, संकलन समय

मान लें कि मेरे पास नेट क्लास लाइब्रेरीज़ (ब्लब्लूएल, दाल इत्यादि) जैसी विभिन्न परियोजनाओं के साथ एक नेट समाधान है और एक मुख्य परियोजना जो वेब एप्लिकेशन या डब्लूपीएफ एप्लीकेशन हो सकती है, इससे कोई फर्क नहीं पड़ता।

अब मान लें कि मैं एक आईओसी कंटेनर (जैसे विंडसर, निनजेक्ट, यूनिटी इत्यादि) का उपयोग करना चाहता हूं ताकि सत्यापनकर्ता, भंडार, सामान्य इंटरफ़ेस कार्यान्वयन और ऐसे सामानों को हल किया जा सके।

मैंने इसे सब एक साथ रखा। संकलित और ठीक चलाता है। फिर, किसी दिन, मैं एक नई सेवा जोड़ता हूं, और मेरे कोड में मैं इसे आईओसी कंटेनर के माध्यम से हल करने का प्रयास करता हूं। बात यह है कि, मैं इसे आईओसी विन्यास में पंजीकृत करना भूल जाता हूं।

सबकुछ संकलित करता है, और एप्लिकेशन को तैनात और चलाया जाता है। सभी ठीक काम करते हैं, सिवाय इसके कि जब कोई पृष्ठ कोड उस कंटेनर को उस नई सेवा के लिए पूछता है, और कंटेनर उत्तर देता है "अरे, मुझे इस सेवा के बारे में कुछ भी पता नहीं है"।

आपको अपनी त्रुटि लॉग इन और उपयोगकर्ता के अनुकूल त्रुटि पृष्ठ मिलता है। आप त्रुटि की जांच करेंगे, समस्या देखें और इसे ठीक करें। सुंदर मानक

अब मान लें कि हम प्रक्रिया को बेहतर बनाना चाहते हैं, और किसी भी तरह से संकलन समय पर जानने में सक्षम होने पर हम प्रत्येक सेवा को आईओसी कंटेनर को संभालने की अपेक्षा करते हैं, कोड में सही ढंग से पंजीकृत है।

यह कैसे प्राप्त किया जा सकता है? एक बात, यूनिट टेस्ट को संभावित उत्तरों से बाहर कर दिया गया है, यदि यह अस्तित्व में है, तो मैं एक और तरीका ढूंढ रहा हूं।

विचार?

संपादित करें - कुछ उत्तरों और टिप्पणियों के बाद, ऐसा लगता है कि यूनिट टेस्ट वास्तव में इस सुविधा को प्राप्त करने का एकमात्र तरीका है।

मैं क्या जानना चाहता हूं, अगर यूनिट टेस्ट - किसी भी कारण से - संभव नहीं है, और इस प्रकार आईओसी संकलित समय पर परीक्षण नहीं किया जा सकता है, तो यह आपको आईओसी कंटेनर का उपयोग करने और प्रत्यक्ष तत्काल चुनने से रोक देगा सब आपके कोड पर? मेरा मतलब है, क्या आप आईओसी और देर से बाइंडिंग का उपयोग करने के लिए बहुत असुरक्षित और जोखिम भरा मानेंगे, और इस "दोष" से बाहर निकलने के अपने फायदे देखेंगे?

+2

@ क्रिसयरे 2000 ने अपने जवाब में बताया, यूनिट परीक्षण आईओसी कॉन्फ़िगरेशन की जांच करने का एक बहुत ही प्रभावी तरीका है, इसलिए आप परीक्षणों का परीक्षण करने का निर्णय पुनः प्राप्त कर सकते हैं। इसका विकल्प मैन्युअल रूप से परीक्षण कर रहा है कि वेबसाइट में प्रत्येक पृष्ठ लोड होता है। – GolfWolf

+0

यह कोई निर्णय नहीं है, मैं जानना चाहता हूं कि इकाई परीक्षणों के अलावा इसे प्राप्त करने के लिए एक और संगत और विश्वसनीय तरीका है, जो अभी तक, मुझे पता है कि एकमात्र तरीका है। –

+0

आप एक विधि इकाई परीक्षण का उपयोग क्यों नहीं कर पाएंगे? – Chriseyre2000

उत्तर

8

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

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

कुछ डी ढांचे आपको शुद्धता के लिए कंटेनर सत्यापित करने की अनुमति देते हैं। उदाहरण के लिए Simple Injector में Verify() विधि शामिल है, जो बस सभी रजिस्ट्रेशनों पर पुन: सक्रिय हो जाएगी और प्रत्येक पंजीकरण के लिए एक उदाहरण हल करेगी। एप्लिकेशन स्टार्टअप के दौरान इस विधि को कॉल करके (या एक समान दृष्टिकोण का उपयोग करके), यदि आप DI कॉन्फ़िगरेशन में कुछ गलत है तो यह (डेवलपर) परीक्षण के दौरान पता लगाएगा और यह एप्लिकेशन को प्रारंभ होने से रोक देगा। आप इसे यूनिट टेस्ट में भी कर सकते हैं।

हालांकि महत्वपूर्ण है कि डीआई कॉन्फ़िगरेशन का परीक्षण करने के लिए ज्यादा रखरखाव की आवश्यकता नहीं है। यदि आपको कंटेनर को सत्यापित करने के लिए पंजीकृत प्रत्येक प्रकार के लिए यूनिट टेस्ट जोड़ना होगा, तो आप असफल हो जाएंगे, क्योंकि बस गायब पंजीकरण (और इस प्रकार एक लापता इकाई परीक्षण) पहली जगह विफल होने का कारण होगा।

यह आपको 'लगभग' संकलन-समय समर्थन देता है। हालांकि, आपको अपने आवेदन के डिजाइन और जिस तरह से आप चीजों को एक साथ तार के बारे में सचेत होना चाहिए। यहां कुछ सुझाव दिए गए हैं:

  1. निहित संपत्ति इंजेक्शन से दूर रहें, जहां कंटेनर को संपत्ति को इंजेक्शन देने की अनुमति है यदि उसे पंजीकृत निर्भरता नहीं मिलती है। यह आपके एप्लिकेशन को तेज़ी से विफल होने की अनुमति नहीं देगा और इसके परिणामस्वरूप NullReferenceException के बाद में परिणाम होगा। स्पष्ट संपत्ति इंजेक्शन, जहां आप किसी संपत्ति को इंजेक्ट करने के लिए कंटेनर को मजबूर करते हैं, ठीक है, हालांकि, जब भी संभव हो, कन्स्ट्रक्टर इंजेक्शन का उपयोग करें।
  2. यदि संभव हो तो सभी रूट ऑब्जेक्ट्स को स्पष्ट रूप से पंजीकृत करें। उदाहरण के लिए, कंटेनर में स्पष्ट रूप से सभी एएसपी.नेट एमवीसी Controller उदाहरण पंजीकृत करें। इस तरह कंटेनर रूट ऑब्जेक्ट्स से शुरू होने वाले पूर्ण निर्भरता ग्राफ को देख सकता है। आपको सभी रूट ऑब्जेक्ट्स को एक स्वचालित फैशन में पंजीकृत करना चाहिए, उदाहरण के लिए सभी रूट प्रकारों को खोजने के लिए प्रतिबिंब का उपयोग करके। उदाहरण के लिए सरल इंजेक्टर के MVC3 Integration NuGet Package में, RegisterMvcControllers एक्सटेंशन विधि है जो आपके लिए यह करेगी। अन्य कंटेनर के एकीकरण पैकेज में समान विशेषताएं होती हैं।
  3. यदि रूट ऑब्जेक्ट्स पंजीकृत करना संभव या व्यवहार्य नहीं है, तो स्टार्टअप के दौरान मैन्युअल रूप से प्रत्येक रूट ऑब्जेक्ट के निर्माण का परीक्षण करें। उदाहरण के लिए एएसपी.नेट वेब फॉर्म Page कक्षाओं के साथ, आप शायद कंटेनर को अपने कन्स्ट्रक्टर के भीतर से कॉल करेंगे (क्योंकि Page कक्षाओं में दुर्भाग्यवश एक डिफ़ॉल्ट कन्स्ट्रक्टर होना चाहिए)। यहां फिर से कुंजी प्रतिबिंब का उपयोग करके उन्हें सभी में ढूंढ रही है। प्रतिबिंब का उपयोग करके सभी पृष्ठ वर्गों को ढूंढकर और उन्हें तुरंत चालू करने से, आपको पता चल जाएगा (ऐप स्टार्ट-अप या परीक्षण समय के दौरान) क्या आपके DI कॉन्फ़िगरेशन में कोई समस्या है या नहीं।
  4. आपके आईओसी कंटेनर के लिए आपके द्वारा प्रबंधित की जाने वाली सभी सेवाओं को एक ही सार्वजनिक कन्स्ट्रक्टर है। कई रचनाकार अस्पष्टता में परिणाम देते हैं और अप्रत्याशित तरीकों से आपके आवेदन को तोड़ सकते हैं। multiple constructors is an anti-pattern होने के बाद।
  5. ऐसे परिदृश्य हैं जहां कुछ निर्भरता अभी तक एप्लिकेशन स्टार्ट-अप के दौरान नहीं बनाई जा सकती हैं। यह सुनिश्चित करने के लिए कि एप्लिकेशन सामान्य रूप से प्रारंभ किया जा सकता है और बाकी डीआई कॉन्फ़िगरेशन को अभी भी सत्यापित किया जा सकता है, प्रॉक्सी या अमूर्त फैक्ट्री के पीछे उन निर्भरताओं को सारणीबद्ध करें।
+0

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

+1

आपको अपने कोड से अपनी सेवाओं का अनुरोध नहीं करना चाहिए। इसके बजाय, कन्स्ट्रक्टर इंजेक्शन के माध्यम से सभी सेवाओं को इंजेक्ट करें और केवल रूट ऑब्जेक्ट्स को हल करें। इस तरह एक पूर्ण ऑब्जेक्ट ग्राफ़ एक ही समय में बनाया गया है, और इस तरह आप जानते हैं कि आपकी रूट ऑब्जेक्ट्स सही ढंग से हल होने पर सभी सेवाएं सही तरीके से पंजीकृत होती हैं। – Steven

+0

हाँ मेरा मतलब मूल वस्तुएं थीं। –

2

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

+0

मैं पूरी तरह से आपसे सहमत हूं। वैसे भी मैं वैसे भी करता हूं, मैं सिर्फ यह जानना चाहता था कि कोई व्यवहार्य विकल्प था या नहीं। –

+0

"आप बिल्ड समय पर एक कंपाइलर के साथ अपने सभी कोड का परीक्षण नहीं कर सकते हैं। यह बेतुका लगता है।" क्यों? एक कंपाइलर एक प्रोग्राम है जो निर्देशों का जवाब देता है। कोई अंतर्निहित कारण नहीं है कि एक भाषा प्रदान नहीं कर सका परीक्षण के लिए संकलन मेटा-प्रोग्राम का समर्थन नहीं कर सका। –

+1

कंपाइलर केवल स्थिर कोड विश्लेषण रखता है। लेकिन यह नहीं चलाता है। पंजीकरण और घटकों का समाधान रन टाइम पर होता है। –

3

मैं क्या जानना चाहता हूं, अगर यूनिट टेस्ट - किसी भी कारण से - संभव नहीं है, और इस प्रकार आईओसी संकलित समय पर परीक्षण नहीं किया जा सकता है, तो यह आपको आईओसी कंटेनर का उपयोग करने और चुनने से रोक देगा अपने पूरे कोड पर प्रत्यक्ष तत्काल?

आप यहां false choice प्रस्तुत करते हैं: या तो एक कंटेनर का उपयोग करें, या फिर "अपने कोड पर प्रत्यक्ष तत्कालता"। लेकिन आप वास्तव में अभी भी किसी कंटेनर के बिना निर्भरता इंजेक्शन का अभ्यास कर सकते हैं।इसके बजाय ऐसा करने का: इस तरह से

public void Main(string[] args) 
{ 
    var c = new C(); 
    var b = new B(c); 
    var a = new A(b); 
    var program = new Program(a); 
    program.Run(); 
} 

तुम अब भी निर्भरता इंजेक्शन के फायदे के सभी प्राप्त कर सकते हैं:

public void Main(string[] args) 
{ 
    var container = new Container(); 
    // ... register various types here... 

    // only Resolve call in entire application 
    var program = container.Resolve<Program>(); 

    program.Run(); 
} 

तुम बस ऐसा करने के घटकों एक दूसरे को नहीं बनाते हैं और बहुत ही रह सकते हैं decoupled। घटकों का निर्माण composition root आवेदन की ज़िम्मेदारी बनी हुई है, भले ही कोई कंटेनर उपयोग नहीं किया जाता है। आपको संकलित समय की जांच भी मिलती है जो आप चाहते हैं।

दो और टिप्पणी:

  1. आप अपने प्रश्न dependency-injection टैग किए गए, तो मैं आप वास्तव में निर्भरता इंजेक्शन का उपयोग कर रहे के रूप में सेवा लोकेटर पैटर्न का विरोध किया संभालने हूँ। दूसरे शब्दों में, मुझे लगता है कि आप अपने कोड में कंटेनर को उजागर नहीं कर रहे हैं और इनका उपयोग नहीं कर रहे हैं, जो आवश्यक नहीं है और not recommended है। यदि आप सेवा लोकेटर करते हैं तो मेरा जवाब अब और काम नहीं करता है। कृपया इसे मेरे लोकेटर के खिलाफ स्ट्राइक लोकेटर के खिलाफ हड़ताल के रूप में गिनें। Constructor injection एक बेहतर विकल्प है।

  2. प्रोग्रामर आमतौर पर इस मैन्युअल दृष्टिकोण के बजाय एक कंटेनर का उपयोग करना चुनते हैं, क्योंकि बड़े आवेदन में यह तत्काल के क्रम को सही रखने के लिए गैर-तुच्छ हो सकता है - बहुत सी रीडरिंग की आवश्यकता हो सकती है क्योंकि आप इसे पेश करते हैं कहीं भी एक नई निर्भरता। कंटेनर अतिरिक्त सुविधाएं भी प्रदान करते हैं जो जीवन को आसान बनाते हैं।

+0

आप सही हैं, मैं सेवा लोकेटर नहीं कर रहा हूं लेकिन डीआई, क्योंकि यह अधिक स्केलेबल और मैन्टेनेबल है। मुझे लगता है कि सेवा लोकेटर वास्तव में एक antipattern है।मेरे पास एक सामान्य संकल्प विधि के साथ सिंगलटन कंटेनर उदाहरण होता है, जो आंतरिक रूप से पसंद के अपने आईओसी कंटेनर का उपयोग करेगा। मैं इसे एक टी ऑब्जेक्ट को हल करने के लिए कहता हूं, और वह इसे तुरंत चालू करेगा, डी के माध्यम से अपनी निर्भरताओं को हल करेगा। मेरा सवाल यह समझने के बारे में था कि अगर आईओसी खराब है क्योंकि आपका कोड संकलित है लेकिन टूटा जा सकता है "तो कोई भी पानी रखता है और यदि यूनिट टेस्ट के विकल्प का विकल्प होता है (क्योंकि परीक्षण जटिलता माना जाता है)। –

+0

@MatteoMosca: क्या मैंने यहां उस प्रश्न का उत्तर नहीं दिया? मैंने दिखाया है कि यूनिट परीक्षणों के बिना, आप आईओसी और समय सुरक्षा को संकलित कर सकते हैं। –

+0

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

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

  • कोई संबंधित समस्या नहीं^_^