निर्भरता इंजेक्शन / IoC कंटेनर प्रथाओं जब लेखन चौखटे


18

मैं विभिन्न परियोजनाओं के लिए .Net के लिए विभिन्न IoC कंटेनरों (Castle.Windsor, Autofac, MEF, आदि) का उपयोग कर चुका हूं। मैंने पाया है कि वे अक्सर दुर्व्यवहार करते हैं और कई बुरी प्रथाओं को प्रोत्साहित करते हैं।

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

उदाहरण के लिए, एक कोड की गंध आती है जिसे मैंने देखा है और उसके पास अच्छे सुझाव नहीं हैं:

  1. निर्माणकर्ताओं के लिए बड़ी संख्या में पैरामीटर (> 5)। सेवाओं का निर्माण जटिल हो जाता है; सभी निर्भरताएं निर्माता के माध्यम से इंजेक्ट की जाती हैं - इस तथ्य के बावजूद कि घटक शायद ही कभी वैकल्पिक होते हैं (परीक्षण में शायद छोड़कर)।

  2. निजी और आंतरिक कक्षाओं का अभाव; यह C # और सिल्वरलाइट का उपयोग करने की एक विशिष्ट सीमा हो सकती है, लेकिन मुझे इसमें दिलचस्पी है कि इसे कैसे हल किया जाए। यह बताना मुश्किल है कि सभी वर्गों के सार्वजनिक होने पर एक फ्रेमवर्क इंटरफ़ेस क्या है; यह मुझे निजी भागों तक पहुंचने की अनुमति देता है जो मुझे संभवतः स्पर्श नहीं करना चाहिए।

  3. IoC कंटेनर में ऑब्जेक्ट जीवनचक्र को युग्मित करना। ऑब्जेक्ट बनाने के लिए आवश्यक निर्भरता का मैन्युअल रूप से निर्माण करना अक्सर मुश्किल होता है। ऑब्जेक्ट जीवनचक्र को अक्सर IoC ढांचे द्वारा प्रबंधित किया जाता है। मैंने ऐसी परियोजनाएँ देखी हैं जहाँ अधिकांश वर्ग सिंग्लेटों के रूप में पंजीकृत हैं। आपको स्पष्ट नियंत्रण की कमी हो जाती है और इसे आंतरिक प्रबंधन के लिए भी मजबूर किया जाता है (यह उपरोक्त बिंदु से संबंधित है, सभी वर्ग सार्वजनिक हैं और आपको उन्हें इंजेक्ट करना होगा)।

उदाहरण के लिए, .Net फ्रेमवर्क में कई स्थिर विधियाँ हैं। जैसे, DateTime.UtcNow। कई बार मैंने इसे लिपटे हुए और निर्माण पैरामीटर के रूप में देखा है।

ठोस कार्यान्वयन के आधार पर मेरे कोड को परीक्षण करना कठिन हो जाता है। एक निर्भरता को इंजेक्ट करने से मेरे कोड का उपयोग करना कठिन हो जाता है - विशेषकर यदि कक्षा में कई पैरामीटर हैं।

मैं एक परीक्षण योग्य इंटरफ़ेस और साथ ही उपयोग करने में आसान दोनों को कैसे प्रदान कर सकता हूं? सर्वोत्तम अभ्यास क्या हैं?


1
वे किन बुरी प्रथाओं को प्रोत्साहित करते हैं? निजी कक्षाओं के लिए, यदि आपके पास अच्छा एनकैप्सुलेशन है, तो आपको उनमें से बहुत से होने की आवश्यकता नहीं है; एक बात के लिए, वे परीक्षण के लिए बहुत कठिन हैं।
Aaronaught

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

2
क्या यह संभव है कि शायद आपके क्लास कंस्ट्रक्टर्स के लिए कई मापदंडों की आवश्यकता का संकेत खुद कोड गंध है और डीआईपी इसे और अधिक स्पष्ट कर रहा है?
dreza

3
एक विशिष्ट IoC कंटेनर को एक फ्रेमवर्क में उपयोग करना आम तौर पर अच्छा अभ्यास नहीं है। निर्भरता इंजेक्शन का उपयोग करना एक अच्छा अभ्यास है। क्या आप अंतर से अवगत हैं?
एरोनॉट

1
@Aaronaught (मृत से वापस)। "निर्भरता इंजेक्शन एक अच्छा अभ्यास है" का उपयोग करना, गलत है। निर्भरता इंजेक्शन एक उपकरण है जिसका उपयोग केवल उचित होने पर ही किया जाना चाहिए। हर समय निर्भरता इंजेक्शन का उपयोग करना एक बुरा अभ्यास है।
डेव हिलियर

जवाबों:


27

एकमात्र वैध निर्भरता इंजेक्शन एंटी-पैटर्न , जिसके बारे में मुझे पता है कि सेवा लोकेटर पैटर्न है, जो एक एंटी-पैटर्न है जब इसके लिए एक डीआई फ्रेमवर्क का उपयोग किया जाता है।

अन्य सभी तथाकथित DI विरोधी पैटर्न, जिनके बारे में मैंने यहाँ या कहीं और सुना है, सामान्य OO / सॉफ़्टवेयर डिज़ाइन एंटी-पैटर्न के थोड़े अधिक विशिष्ट मामले हैं। उदाहरण के लिए:

  • कंस्ट्रक्टर ओवर-इंजेक्शन एकल जिम्मेदारी सिद्धांत का उल्लंघन है । बहुत सारे निर्माता तर्क बहुत अधिक निर्भरता को इंगित करते हैं; बहुत अधिक निर्भरताएं इंगित करती हैं कि वर्ग बहुत अधिक करने की कोशिश कर रहा है। आमतौर पर यह त्रुटि अन्य कोड महक, जैसे कि असामान्य रूप से लंबी या अस्पष्ट ("प्रबंधक") श्रेणी के नामों के साथ संबंधित होती है। स्थैतिक विश्लेषण उपकरण आसानी से अत्यधिक अभिवाही / अपवाही युग्मन का पता लगा सकते हैं।

  • व्यवहार के विपरीत, डेटा का इंजेक्शन, पॉलीटर्जिस्ट विरोधी पैटर्न का एक उपप्रकार है , 'इस मामले में जिस्ट कंटेनर है। यदि किसी वर्ग को वर्तमान तिथि और समय के बारे में पता होना चाहिए, तो आप उसे इंजेक्ट नहीं करते हैं DateTime, जो डेटा है; इसके बजाय, आप सिस्टम घड़ी पर एक अमूर्त इंजेक्षन करते हैं (मैं आमतौर पर मेरा फोन करता ISystemClockहूं, हालांकि मुझे लगता है कि सिस्टमवैपर्स प्रोजेक्ट में एक अधिक सामान्य है )। यह न केवल डीआई के लिए सही है; यह परीक्षणशीलता के लिए नितांत आवश्यक है, ताकि आप वास्तव में उन पर प्रतीक्षा करने की आवश्यकता के बिना समय-भिन्न कार्यों का परीक्षण कर सकें।

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

  • एक और सामान्य त्रुटि कार्यान्वयन-विशिष्ट इंटरफ़ेस प्रकार (जैसे अजीब नामों के साथ IOracleRepository) है, बस कंटेनर में इसे पंजीकृत करने में सक्षम होने के लिए। यह अपने आप में निर्भरता के उलट सिद्धांत का उल्लंघन है (सिर्फ इसलिए कि यह एक इंटरफ़ेस है, इसका मतलब यह नहीं है कि यह वास्तव में सार है) और अक्सर इसमें इंटरफ़ेस ब्लोट भी शामिल है जो उल्लंघन करता है इंटरफ़ेस अलगाव सिद्धांत

  • अंतिम त्रुटि जो मैं आमतौर पर देखता हूं, वह "वैकल्पिक निर्भरता" है, जो उन्होंने नर्डडिनर में की थी । दूसरे शब्दों में, एक कंस्ट्रक्टर है जो निर्भरता इंजेक्शन को स्वीकार करता है, लेकिन एक अन्य कंस्ट्रक्टर भी है जो "डिफ़ॉल्ट" कार्यान्वयन का उपयोग करता है। यह डीआईपी का भी उल्लंघन करता है और झुकता है करने के लिए नेतृत्व करने के लिए LSP उल्लंघन समय के साथ, डेवलपर्स, साथ ही, डिफ़ॉल्ट कार्यान्वयन के आसपास मान्यताओं बनाने लगते हैं, और / या डिफ़ॉल्ट निर्माता का उपयोग कर नए-इंग अप उदाहरणों शुरू करते हैं।

जैसा कि पुरानी कहावत है, आप किसी भी भाषा में FORTRAN लिख सकते हैं । निर्भरता इंजेक्शन एक चांदी की गोली नहीं है जो डेवलपर्स को उनकी निर्भरता प्रबंधन को खराब करने से रोकेगा, लेकिन यह कई सामान्य त्रुटियों / विरोधी पैटर्न को रोकता है:

...और इसी तरह।

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

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

DI रॉकेट साइंस नहीं है। बस से बचने की कोशिश करें newऔर staticसिवाय इसके कि जब उनका उपयोग करने के लिए कोई सम्मोहक कारण हो, जैसे कि एक उपयोगिता विधि, जिसमें कोई बाहरी निर्भरता न हो, या एक उपयोगिता वर्ग जो संभवतः रूपरेखा के बाहर कोई उद्देश्य नहीं रख सकता है (इंटरॉप रैपर और डिक्शनरी कीज़ इसके आगे के सामान्य उदाहरण हैं) इस)।

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


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