निर्भरता व्युत्क्रम सिद्धांत क्या है और यह महत्वपूर्ण क्यों है?


178

निर्भरता व्युत्क्रम सिद्धांत क्या है और यह महत्वपूर्ण क्यों है?



3
विकिपीडिया से "उच्च स्तर" और "निम्न स्तर" की शर्तों का उपयोग करते हुए यहां पर जवाबों की हास्यास्पद मात्रा। ये शब्द अप्राप्य हैं और इस पृष्ठ पर बहुत सारे पाठक हैं। यदि आप विकिपीडिया को फिर से संगठित करने जा रहे हैं, तो कृपया संदर्भ देने के लिए अपने उत्तर में इन शर्तों को परिभाषित करें !
8bitjunkie

जवाबों:


107

इस दस्तावेज़ को देखें: डिपेंडेंसी इन्वर्सेशन प्रिंसिपल

यह मूल रूप से कहता है:

  • उच्च स्तर के मॉड्यूल को निम्न-स्तर के मॉड्यूल पर निर्भर नहीं होना चाहिए। दोनों को अमूर्तता पर निर्भर होना चाहिए।
  • विवरण कभी भी विवरण पर निर्भर नहीं होना चाहिए। विवरण अमूर्तता पर निर्भर होना चाहिए।

जैसा कि यह महत्वपूर्ण क्यों है, संक्षेप में: परिवर्तन जोखिम भरा है, और कार्यान्वयन के बजाय एक अवधारणा के आधार पर, आप कॉल साइटों पर परिवर्तन की आवश्यकता को कम करते हैं।

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

कार्यान्वयन को एक इंटरफ़ेस पर निर्भर करते हुए, आपको रन-टाइम का चयन करने की संभावना मिलती है जो कार्यान्वयन आपके विशेष वातावरण के लिए बेहतर अनुकूल है। मामलों के आधार पर, यह दिलचस्प भी हो सकता है।


31
यह उत्तर यह नहीं कहता है कि डीआईपी महत्वपूर्ण क्यों है, या डीआईपी क्या है। मैंने आधिकारिक डीआईपी दस्तावेज़ पढ़ा है, और लगता है कि यह वास्तव में एक खराब और अनुचित "सिद्धांत" है, क्योंकि यह एक दोषपूर्ण धारणा पर आधारित है: उच्च-स्तरीय मॉड्यूल पुन: प्रयोज्य हैं।
रोजेरियो

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

6
क्लास ए का उपयोग करने वाला वर्ग ए का मतलब बी के कार्यान्वयन पर ए "निर्भर" नहीं करता है; यह केवल B के सार्वजनिक इंटरफ़ेस पर निर्भर करता है। एक अलग अमूर्त जोड़ना, जिस पर A और B दोनों ही निर्भर करते हैं, इसका मतलब है कि A में अब B के सार्वजनिक इंटरफ़ेस पर एक संकलन-समय पर निर्भरता नहीं होगी, इन अतिरिक्त सार के बिना इकाइयों के बीच अलगाव आसानी से प्राप्त किया जा सकता है; जावा और .NET में उस के लिए विशिष्ट मॉकिंग टूल हैं, जो सभी स्थितियों (स्थिर विधियों, निर्माणकर्ताओं, आदि) से निपटते हैं। DIP को लागू करना सॉफ्टवेयर को अधिक जटिल और कम बनाए रखने योग्य बनाता है, और अधिक परीक्षण योग्य नहीं है।
रोजरियो

1
फिर नियंत्रण का उलटा क्या है? निर्भरता को प्राप्त करने का एक तरीका?
user20358

2
@ रोगेरियो, नीचे डेरेक ग्रीर की प्रतिक्रिया देखें, वह बताते हैं। AFAIK, DIP का कहना है कि यह A ही है जो A को जरूरत है, और B को नहीं, जो कहता है कि A की जरूरत है। तो, इंटरफ़ेस जिसे A की आवश्यकता B द्वारा नहीं दी जानी चाहिए, लेकिन A. के लिए
ejaenv

145

एजाइल सॉफ्टवेयर डेवलपमेंट, प्रिंसिपल्स, पैटर्न और प्रैक्टिस एंड एजाइल प्रिंसिपल्स, पैटर्न, और प्रैक्टिस इन सी # डिपेंडेंसी इनवर्जन प्रिंसिपल के पीछे मूल लक्ष्यों और प्रेरणाओं को पूरी तरह से समझने के लिए सबसे अच्छे संसाधन हैं। लेख "द डिपेंडेंसी इनवर्सन प्रिंसिपल" भी एक अच्छा संसाधन है, लेकिन इस तथ्य के कारण कि यह एक मसौदे का एक संक्षिप्त संस्करण है, जिसने अंततः पहले उल्लेखित पुस्तकों में अपना रास्ता बनाया, यह कुछ महत्वपूर्ण चर्चा की अवधारणा को छोड़ देता है पैकेज और इंटरफ़ेस का स्वामित्व जो इस सिद्धांत को "सामान्य से इंटरफ़ेस में प्रोग्राम करने के लिए, न कि कार्यान्वयन के लिए" डिजाइन पैटर्न (गामा, एट अल।) के भीतर पाए जाने वाले कार्यान्वयन के लिए महत्वपूर्ण हैं।

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

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

निर्भरता उलटा सिद्धांत क्या संदर्भित नहीं करता है, इंटरफेस के उपयोग के माध्यम से अमूर्त निर्भरता का सरल अभ्यास है (जैसे MyService → [ILogger ger Logger])। हालांकि यह निर्भरता के विशिष्ट कार्यान्वयन विवरण से एक घटक को विघटित करता है, यह उपभोक्ता और निर्भरता (जैसे [MyService → IMyServiceLogger] ger लकड़हारा के बीच संबंधों को उल्टा नहीं करता है।

निर्भरता उलटा सिद्धांत का महत्व सॉफ्टवेयर घटकों का पुन: उपयोग करने में सक्षम होने के एक विलक्षण लक्ष्य को पूरा किया जा सकता है जो उनकी कार्यक्षमता (लॉगिंग, सत्यापन, आदि) के एक हिस्से के लिए बाहरी निर्भरता पर निर्भर करते हैं।

पुन: उपयोग के इस सामान्य लक्ष्य के भीतर, हम पुन: उपयोग के दो उप-प्रकारों को चित्रित कर सकते हैं:

  1. उप-निर्भरता कार्यान्वयन के साथ कई अनुप्रयोगों के भीतर एक सॉफ्टवेयर घटक का उपयोग करना (जैसे कि आपने एक डीआई कंटेनर विकसित किया है और लॉगिंग प्रदान करना चाहते हैं, लेकिन अपने कंटेनर को एक विशिष्ट लकड़हारे से युगल नहीं करना चाहते हैं, जो आपके कंटेनर का उपयोग करने वाले सभी को भी करना है अपनी चुनी हुई लॉगिंग लाइब्रेरी का उपयोग करें)।

  2. एक विकसित संदर्भ के भीतर सॉफ्टवेयर घटकों का उपयोग करना (जैसे आपने व्यावसायिक-तर्क घटक विकसित किए हैं जो एक एप्लिकेशन के कई संस्करणों में समान रहते हैं जहां कार्यान्वयन विवरण विकसित हो रहे हैं)।

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

व्यवसाय-तर्क घटकों (अर्थात "उच्च-स्तरीय घटकों") के पुन: उपयोग के दूसरे मामले के साथ, लक्ष्य आपके आवेदन विवरण के मूल डोमेन कार्यान्वयन को आपके कार्यान्वयन विवरणों की बदलती जरूरतों (यानी हठ पुस्तकालयों को बदलते / उन्नत / अपग्रेड करना) से अलग करना है। , एन्क्रिप्शन रणनीतियों, आदि)। आदर्श रूप से, किसी एप्लिकेशन के कार्यान्वयन विवरण को बदलने से एप्लिकेशन के व्यावसायिक तर्क को समझने वाले घटकों को नहीं तोड़ना चाहिए।

नोट: कुछ इस दूसरे मामले को वास्तविक पुन: उपयोग के रूप में वर्णित करने पर आपत्ति कर सकते हैं, तर्क है कि एकल-विकसित अनुप्रयोग के भीतर उपयोग किए जाने वाले व्यावसायिक-तर्क घटकों जैसे घटक केवल एक ही उपयोग का प्रतिनिधित्व करते हैं। हालांकि, यह विचार यह है कि अनुप्रयोग के कार्यान्वयन विवरण में प्रत्येक परिवर्तन एक नया संदर्भ प्रदान करता है और इसलिए एक अलग उपयोग मामला है, हालांकि अंतिम लक्ष्यों को अलगाव बनाम पोर्टेबिलिटी के रूप में प्रतिष्ठित किया जा सकता है।

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

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


17
धन्यवाद। मैं अब देख रहा हूं कि मेरा उत्तर कैसे याद आता है। MyService → [ILogger] Logger] और [MyService → IMyServiceLogger] ger Logger के बीच का अंतर सूक्ष्म लेकिन महत्वपूर्ण है।
पैट्रिक McElhaney

2
उसी पंक्ति में इसकी बहुत अच्छी तरह से यहाँ व्याख्या की गई है: खो
ejaenv

1
मैं कैसे कामना करता हूं कि लोग निर्भरता इंजेक्शन के लिए लॉगऑन के रूप में लॉगर का उपयोग करना बंद कर दें। विशेष रूप से log4net के संबंध में जहां इसका लगभग एक विरोधी पैटर्न है। यह एक तरफ, स्पष्टीकरण की व्याख्या!
कैस्पर लियोन नील्सन

4
@ कैस्पर लियोन नीलसन - DIP का DI से कोई लेना-देना नहीं है वे समानार्थी नहीं हैं और न ही समान अवधारणाएं हैं।
TSmith

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

14

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

अंतिम वाले निम्न स्तर की कक्षाओं पर निर्भर करते हैं। इस तरह की संरचनाओं को लागू करने का एक प्राकृतिक तरीका निम्न स्तर की कक्षाएं लिखना होगा और एक बार हमारे पास जटिल उच्च स्तरीय कक्षाएं लिखने के लिए होगा। चूंकि उच्च स्तरीय कक्षाएं दूसरों के संदर्भ में परिभाषित की जाती हैं, ऐसा करने का तार्किक तरीका लगता है। लेकिन यह एक लचीला डिजाइन नहीं है। यदि हमें निम्न स्तर के वर्ग को बदलने की आवश्यकता है तो क्या होगा?

निर्भरता उलटा सिद्धांत बताता है कि:

  • उच्च स्तर के मॉड्यूल को निम्न स्तर के मॉड्यूल पर निर्भर नहीं होना चाहिए। दोनों को अमूर्तता पर निर्भर होना चाहिए।
  • विवरण विवरण पर निर्भर नहीं होना चाहिए। विवरण अमूर्तता पर निर्भर होना चाहिए।

यह सिद्धांत पारंपरिक धारणा को "उल्टा" करना चाहता है कि सॉफ्टवेयर में उच्च स्तर के मॉड्यूल को निचले स्तर के मॉड्यूल पर निर्भर होना चाहिए। यहाँ उच्च स्तर के मॉड्यूल अमूर्त (उदाहरण के लिए, इंटरफ़ेस के तरीकों को तय करना) के मालिक हैं, जो निचले स्तर के मॉड्यूल द्वारा कार्यान्वित किए जाते हैं। इस प्रकार निचले स्तर के मॉड्यूल को उच्च स्तर के मॉड्यूल पर निर्भर करना।


11

निर्भरता उलटा अच्छी तरह से लागू आपके आवेदन की पूरी वास्तुकला के स्तर पर लचीलापन और स्थिरता देता है। यह आपके एप्लिकेशन को अधिक सुरक्षित और स्थिर रूप से विकसित करने की अनुमति देगा।

पारंपरिक स्तरित वास्तुकला

परंपरागत रूप से एक स्तरित वास्तुकला यूआई व्यावसायिक परत पर निर्भर करता था और यह बदले में डेटा एक्सेस परत पर निर्भर करता था।

आपको लेयर, पैकेज या लाइब्रेरी को समझना होगा। देखते हैं कि कोड कैसा होगा।

हमारे पास डेटा एक्सेस लेयर के लिए एक लाइब्रेरी या पैकेज होगा।

// DataAccessLayer.dll
public class ProductDAO {

}

और एक अन्य लाइब्रेरी या पैकेज लेयर बिजनेस लॉजिक जो डेटा एक्सेस लेयर पर निर्भर करता है।

// BusinessLogicLayer.dll
using DataAccessLayer;
public class ProductBO { 
    private ProductDAO productDAO;
}

निर्भरता उलटा के साथ स्तरित वास्तुकला

निर्भरता उलटा निम्न इंगित करता है:

उच्च-स्तरीय मॉड्यूल को निम्न-स्तर के मॉड्यूल पर निर्भर नहीं होना चाहिए। दोनों को अमूर्तता पर निर्भर होना चाहिए।

विवरण विवरण पर निर्भर नहीं होना चाहिए। विवरण अमूर्तता पर निर्भर होना चाहिए।

उच्च-स्तरीय मॉड्यूल और निम्न स्तर क्या हैं? लाइब्रेरी या पैकेज जैसे सोच मॉड्यूल, उच्च-स्तरीय मॉड्यूल वे होंगे जो परंपरागत रूप से निर्भरता और निम्न स्तर पर होते हैं, जिस पर वे निर्भर करते हैं।

दूसरे शब्दों में, मॉड्यूल उच्च स्तर वह होगा जहां कार्रवाई को लागू किया जाता है और निम्न स्तर जहां कार्रवाई की जाती है।

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

कल्पना करें कि हम अपना कोड इस प्रकार अनुकूलित करते हैं:

हमारे पास डेटा एक्सेस लेयर के लिए एक लाइब्रेरी या पैकेज होगा जो अमूर्तता को परिभाषित करता है।

// DataAccessLayer.dll
public interface IProductDAO
public class ProductDAO : IProductDAO{

}

और एक अन्य लाइब्रेरी या पैकेज लेयर बिजनेस लॉजिक जो डेटा एक्सेस लेयर पर निर्भर करता है।

// BusinessLogicLayer.dll
using DataAccessLayer;
public class ProductBO { 
    private IProductDAO productDAO;
}

यद्यपि हम व्यापार और डेटा पहुंच के बीच एक अमूर्त निर्भरता पर निर्भर हैं।

निर्भरता व्युत्क्रम प्राप्त करने के लिए, दृढ़ता इंटरफ़ेस को मॉड्यूल या पैकेज में परिभाषित किया जाना चाहिए जहां यह उच्च स्तरीय तर्क या डोमेन है और निम्न-स्तरीय मॉड्यूल में नहीं है।

पहले परिभाषित करें कि डोमेन लेयर क्या है और इसके संचार का अमूर्त होना दृढ़ता को परिभाषित करता है।

// Domain.dll
public interface IProductRepository;

using DataAccessLayer;
public class ProductBO { 
    private IProductRepository productRepository;
}

दृढ़ता परत डोमेन पर निर्भर करता है, के बाद अब उलटा हो रही है अगर एक निर्भरता परिभाषित किया गया है।

// Persistence.dll
public class ProductDAO : IProductRepository{

}


(स्रोत: xurxodev.com )

सिद्धांत को गहरा करना

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

लेकिन हम एक निर्भरता को उल्टा क्यों करते हैं? विशिष्ट उदाहरणों से परे मुख्य उद्देश्य क्या है?

इस तरह की आमतौर पर सबसे स्थिर चीजों की अनुमति होती है, जो कम स्थिर चीजों पर निर्भर नहीं होती हैं, अधिक बार बदलने के लिए।

हठ के साथ संवाद करने के लिए डिज़ाइन किए गए डोमेन लॉजिक या क्रियाओं की तुलना में एक ही डेटाबेस तक पहुंचने के लिए या तो डेटाबेस या तकनीक को बदलना आसान है। इस वजह से, निर्भरता उलट जाती है क्योंकि अगर यह परिवर्तन होता है तो दृढ़ता को बदलना आसान होता है। इस तरह हमें डोमेन नहीं बदलना पड़ेगा। डोमेन परत सभी में सबसे अधिक स्थिर है, यही कारण है कि इसे किसी भी चीज पर निर्भर नहीं होना चाहिए।

लेकिन सिर्फ यह रिपॉजिटरी उदाहरण नहीं है। ऐसे कई परिदृश्य हैं जहां यह सिद्धांत लागू होता है और इस सिद्धांत पर आधारित आर्किटेक्चर हैं।

आर्किटेक्चर

ऐसे आर्किटेक्चर हैं जहां निर्भरता व्युत्क्रम इसकी परिभाषा के लिए महत्वपूर्ण है। सभी डोमेन में यह सबसे महत्वपूर्ण है और यह वह सार है जो डोमेन के बीच संचार प्रोटोकॉल को इंगित करेगा और बाकी पैकेज या लाइब्रेरी परिभाषित हैं।

साफ वास्तुकला

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


(स्रोत: 8 वें.कॉम )

हेक्सागोनल वास्तुकला

यह हेक्सागोनल वास्तुकला के साथ उसी तरह से होता है, जहां डोमेन मध्य भाग में भी स्थित है और पोर्ट डोमिनोज़ आउटवर्ड से संचार के सार हैं। यहां फिर से यह स्पष्ट है कि डोमेन सबसे स्थिर है और पारंपरिक निर्भरता उलटा है।


मुझे यकीन नहीं है कि यह कहने के लिए क्या है, लेकिन यह वाक्य असंगत है: "लेकिन हम जो दृष्टिकोण लेते हैं, उसके अनुसार हम निवेश को गलत तरीके से निर्भर कर सकते हैं, लेकिन एक अमूर्तता है।" शायद आप ठीक करना चाहेंगे?
मार्क अमेरी

9

मेरे लिए, डिपेंडेंसी इनवर्सन प्रिंसिपल, जैसा कि आधिकारिक लेख में वर्णित है वास्तव में कम पुन: प्रयोज्य होने वाले मॉड्यूल की पुन: प्रयोज्य को बढ़ाने के लिए एक भ्रामक प्रयास है, साथ ही सी ++ भाषा में एक समस्या को हल करने का एक तरीका है।

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

उच्च-स्तरीय मॉड्यूल निम्न-स्तर के मॉड्यूल की तुलना में स्वाभाविक रूप से कम पुन: प्रयोज्य हैं क्योंकि पूर्व सामान्य रूप से उत्तरार्द्ध की तुलना में अधिक अनुप्रयोग / संदर्भ हैं। उदाहरण के लिए, यूआई स्क्रीन को लागू करने वाला एक घटक उच्चतम स्तर का है और यह भी बहुत (पूरी तरह से?) अनुप्रयोग के लिए विशिष्ट है। एक अलग अनुप्रयोग में इस तरह के एक घटक का पुन: उपयोग करने का प्रयास काउंटर-उत्पादक है, और केवल ओवर-इंजीनियरिंग के लिए नेतृत्व कर सकता है।

तो, एक घटक A के समान स्तर पर एक अलग अमूर्त का निर्माण एक घटक B पर निर्भर करता है (जो A पर निर्भर नहीं करता है) केवल तभी किया जा सकता है जब घटक A विभिन्न अनुप्रयोगों या संदर्भों में पुन: उपयोग के लिए उपयोगी होगा। अगर ऐसा नहीं है, तो डीआईपी लागू करना खराब डिजाइन होगा।


यहां तक ​​कि अगर उच्च-स्तरीय अमूर्त केवल उस एप्लिकेशन के संदर्भ में उपयोगी है, जिसका मूल्य तब हो सकता है जब आप वास्तविक कार्यान्वयन को परीक्षण के लिए एक स्टब के साथ बदलना चाहते हैं (या आमतौर पर वेब पर उपलब्ध एप्लिकेशन को कमांड-लाइन इंटरफ़ेस प्रदान करते हैं)
Przemek पोक्रीवका

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

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

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

1
यूआई स्क्रीन निश्चित रूप से उच्चतम स्तर का मॉड्यूल नहीं है या किसी भी एप्लिकेशन के लिए नहीं होना चाहिए। उच्चतम स्तर के मॉड्यूल वे होते हैं जिनमें व्यावसायिक नियम होते हैं। उच्चतम स्तर के मॉड्यूल को पुन: प्रयोज्य के लिए इसकी क्षमता द्वारा भी परिभाषित नहीं किया गया है। कृपया इस लेख में अंकल बॉब की सरल व्याख्या देखें: blog.cleancoder.com/uncle-bob/2016/01/04/…
humbaba

8

मूल रूप से यह कहता है:

क्लास को एब्स्ट्रैक्ट (उदाहरण के लिए इंटरफ़ेस, एब्सट्रैक्ट क्लास) पर निर्भर होना चाहिए, न कि विशिष्ट विवरण (कार्यान्वयन) पर।


क्या यह इतना आसान हो सकता है? DerekGreer के रूप में लंबे लेख और यहां तक ​​कि किताबें भी हैं? मैं वास्तव में सरल उत्तर की तलाश में था, लेकिन इसकी अविश्वसनीय अगर यह इतना सरल है: D
Darius.V

1
@ darius-v यह "अमूर्त का उपयोग करें" कहने का दूसरा संस्करण नहीं है। यह इंटरफेस के मालिक के बारे में है। प्रिंसिपल का कहना है कि क्लाइंट (उच्च स्तर के घटक) को इंटरफेस को परिभाषित करना चाहिए और निचले स्तर के घटकों को उन्हें लागू करना चाहिए।
बोरान

6

अच्छे उत्तर और अच्छे उदाहरण पहले से ही यहां दूसरों द्वारा दिए गए हैं।

कारण DIP महत्वपूर्ण है क्योंकि यह OO-सिद्धांत 'शिथिल युग्मित डिजाइन "सुनिश्चित करता है।

आपके सॉफ़्टवेयर की वस्तुओं को एक पदानुक्रम में नहीं जाना चाहिए जहां कुछ ऑब्जेक्ट शीर्ष-स्तर वाले होते हैं, जो निम्न-स्तर की वस्तुओं पर निर्भर होते हैं। निम्न-स्तरीय ऑब्जेक्ट में परिवर्तन तब आपके शीर्ष-स्तरीय ऑब्जेक्ट में रिपल-थ्रू होगा जो सॉफ़्टवेयर को परिवर्तन के लिए बहुत नाजुक बना देता है।

आप चाहते हैं कि आपकी 'टॉप-लेवल' वस्तुएं बहुत स्थिर हों और बदलाव के लिए नाजुक न हों, इसलिए आपको निर्भरता को उलटने की जरूरत है।


6
जावा या .NET कोड के लिए DIP वास्तव में कैसा करता है? उन भाषाओं में, C ++ के विपरीत, निम्न-स्तरीय मॉड्यूल के कार्यान्वयन में परिवर्तन के लिए उच्च-स्तरीय मॉड्यूल में परिवर्तनों का उपयोग करने की आवश्यकता नहीं होती है। केवल सार्वजनिक इंटरफ़ेस में परिवर्तन के माध्यम से तरंगित होगा, लेकिन तब उच्च स्तर पर परिभाषित अमूर्तता को भी बदलना होगा।
रोजरियो

5

डिपेंडेंसी इनवर्जन प्रिंसिपल को बताने का एक बहुत ही स्पष्ट तरीका है:

आपके मॉड्यूल जो जटिल व्यावसायिक तर्क को अतिक्रमण करते हैं, उन्हें अन्य मॉड्यूल पर सीधे निर्भर नहीं होना चाहिए जो व्यावसायिक तर्क को एन्क्रिप्ट करते हैं। इसके बजाय, उन्हें केवल साधारण डेटा के इंटरफेस पर निर्भर होना चाहिए।

अपने वर्ग Logicको लागू करने के बजाय, जैसा कि आमतौर पर लोग करते हैं:

class Dependency { ... }
class Logic {
    private Dependency dep;
    int doSomething() {
        // Business logic using dep here
    }
}

आपको कुछ इस तरह करना चाहिए:

class Dependency { ... }
interface Data { ... }
class DataFromDependency implements Data {
    private Dependency dep;
    ...
}
class Logic {
    int doSomething(Data data) {
        // compute something with data
    }
}

Dataऔर DataFromDependencyउसी मॉड्यूल में रहना चाहिए, जैसे कि Logicनहीं Dependency

यह क्यों?

  1. दो बिजनेस लॉजिक मॉड्यूल अब डिकॉय हो गए हैं। जब Dependencyपरिवर्तन होता है, तो आपको बदलने की आवश्यकता नहीं होती है Logic
  2. यह समझना कि क्या करना Logicबहुत सरल कार्य है: यह केवल उसी पर संचालित होता है जो ADT जैसा दिखता है।
  3. Logicअब और अधिक आसानी से परीक्षण किया जा सकता है। अब आप सीधे Dataफर्जी डेटा के साथ सीधे प्रवेश कर सकते हैं और इसे पास कर सकते हैं । मॉक या जटिल परीक्षण मचान की आवश्यकता नहीं है।

मुझे नहीं लगता कि यह सही है। यदि DataFromDependency, जो सीधे संदर्भ देता है Dependency, उसी मॉड्यूल में है Logic, तो Logicमॉड्यूल अभी भी सीधे Dependencyसंकलन समय पर मॉड्यूल पर निर्भर करता है । सिद्धांत के प्रति अंकल बॉब का स्पष्टीकरण , इससे बचना डीआईपी का पूरा बिंदु है। बल्कि, डीआईपी का पालन करने के लिए, Dataसमान मॉड्यूल में होना चाहिए Logic, लेकिन उसी मॉड्यूल में DataFromDependencyहोना चाहिए Dependency
मार्क अमेरी

3

नियंत्रण का उलटा (IoC) एक डिजाइन पैटर्न है जहां किसी वस्तु को अपनी निर्भरता के लिए एक रूपरेखा पूछने के बजाय एक बाहरी ढांचे द्वारा अपनी निर्भरता सौंप दी जाती है।

पारंपरिक लुकअप का उपयोग करते हुए स्यूडोकोड उदाहरण:

class Service {
    Database database;
    init() {
        database = FrameworkSingleton.getService("database");
    }
}

IoC का उपयोग करने वाला समान कोड:

class Service {
    Database database;
    init(database) {
        this.database = database;
    }
}

IoC के लाभ हैं:

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

क्या निर्भरता उलटा सिद्धांत और नियंत्रण का उलटा एक ही बात है?
पीटर मॉर्टेंसन

3
डीआईपी में "उलटा" नियंत्रण के उलट के समान नहीं है। पहला एक संकलन-समय की निर्भरता के बारे में है, जबकि दूसरा एक रनटाइम के तरीकों के बीच नियंत्रण के प्रवाह के बारे में है।
रोजरियो

मुझे लगता है कि IoC संस्करण कुछ याद कर रहा है। डेटाबेस ऑब्जेक्ट कैसे परिभाषित होता है, यह कहां से आता है। मैं यह समझने की कोशिश कर रहा हूं कि यह कैसे एक विशाल भगवान पर निर्भरता में शीर्ष स्तर तक सभी निर्भरताओं को निर्दिष्ट करने में देरी नहीं करता है
रिचर्ड टिंगल

1
जैसा कि पहले ही @ Rogério ने कहा है, DIP DI / IoC नहीं है। यह उत्तर गलत है IMO
zeraDev

1

निर्भरता उलटा का बिंदु पुन: प्रयोज्य सॉफ्टवेयर बनाना है।

विचार यह है कि कोड के दो टुकड़े एक-दूसरे पर निर्भर होने के बजाय, वे कुछ सार इंटरफेस पर भरोसा करते हैं। फिर आप दूसरे के बिना या तो टुकड़े का पुन: उपयोग कर सकते हैं।

जिस तरह से यह सबसे अधिक प्राप्त किया जाता है वह जावा में स्प्रिंग जैसे नियंत्रण (IoC) कंटेनर के व्युत्क्रम के माध्यम से होता है। इस मॉडल में, वस्तुओं के गुणों को एक्सएमएल कॉन्फ़िगरेशन के माध्यम से सेट किया जाता है बजाय वस्तुओं के बाहर जाने और उनकी निर्भरता खोजने के लिए।

इस छद्मकोड की कल्पना करें ...

public class MyClass
{
  public Service myService = ServiceLocator.service;
}

MyClass सीधे सेवा वर्ग और ServiceLocator वर्ग दोनों पर निर्भर करता है। यदि आप इसे किसी अन्य एप्लिकेशन में उपयोग करना चाहते हैं तो इसे उन दोनों की आवश्यकता है। अब जरा इसकी कल्पना करें ...

public class MyClass
{
  public IService myService;
}

अब, MyClass एक इंटरफ़ेस, IService इंटरफ़ेस पर निर्भर करता है। हम IoC कंटेनर को वास्तव में उस वैरिएबल का मान सेट करने देंगे।

तो अब, MyClass को अन्य परियोजनाओं में आसानी से पुन: उपयोग किया जा सकता है, बिना उन अन्य दो वर्गों की निर्भरता को लाने के साथ।

इससे भी बेहतर, आपको MyService की निर्भरता, और उन निर्भरताओं की निर्भरता, और ... अच्छी तरह से खींचने की ज़रूरत नहीं है, आपको यह विचार मिलता है।


2
यह जवाब वास्तव में डीआईपी के बारे में नहीं है, बल्कि कुछ और है। कोड के दो टुकड़े कुछ अमूर्त इंटरफेस पर भरोसा कर सकते हैं और एक दूसरे में नहीं, और फिर भी निर्भरता के सिद्धांत का पालन नहीं करते हैं।
रोजेरियो

1

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

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

निर्भरता व्युत्क्रम सिद्धांत में "उच्च स्तर" का अर्थ है "अधिक महत्वपूर्ण"।


1
यह उल्लेखनीय रूप से अच्छा सादृश्य है। बहुत कुछ, डीआईसी के तहत, उच्च-स्तरीय घटक अभी भी निम्न-स्तरीय लोगों पर रनटाइम पर निर्भर करते हैं, इस सादृश्य में, उच्च-स्तरीय योजनाओं का निष्पादन निम्न-स्तर की योजनाओं पर निर्भर करता है। लेकिन यह भी, जैसा कि डीआईसी के तहत यह निम्न-स्तर की योजनाएं हैं जो उच्च-स्तरीय योजनाओं पर संकलन समय पर निर्भर करती हैं , यह आपके अनुरूप में मामला है कि निम्न-स्तरीय योजनाओं का गठन उच्च-स्तरीय योजनाओं पर निर्भर करता है।
मार्क अमेरी

0

मैं देख सकता हूँ कि उपरोक्त उत्तरों में अच्छी व्याख्या दी गई है। हालाँकि मैं सरल उदाहरण के साथ कुछ आसान स्पष्टीकरण प्रदान करना चाहता हूं।

निर्भरता उलटा सिद्धांत प्रोग्रामर को हार्डकोडेड निर्भरता को दूर करने की अनुमति देता है ताकि आवेदन शिथिल रूप से युग्मित और विस्तार योग्य हो जाए।

इसे कैसे प्राप्त करें: अमूर्तता के माध्यम से

बिना निर्भरता के उलटा:

 class Student {
    private Address address;

    public Student() {
        this.address = new Address();
    }
}
class Address{
    private String perminentAddress;
    private String currentAdrress;

    public Address() {
    }
} 

उपरोक्त कोड स्निपेट में, पता ऑब्जेक्ट हार्ड-कोडेड है। इसके बजाय अगर हम निर्भरता व्युत्क्रम का उपयोग कर सकते हैं और कंस्ट्रक्टर या सेटर विधि से गुजरकर एड्रेस ऑब्जेक्ट को इंजेक्ट कर सकते हैं। चलो देखते हैं।

निर्भरता उलटा के साथ:

class Student{
    private Address address;

    public Student(Address address) {
        this.address = address;
    }
    //or
    public void setAddress(Address address) {
        this.address = address;
    }
}

-1

निर्भरता का उलटा: सार पर निर्भर करता है, न कि सहमति पर।

नियंत्रण का उलटा: मुख्य बनाम अमूर्त, और मुख्य प्रणालियों का गोंद कैसे है।

डीआईपी और आईओसी

ये कुछ अच्छी पोस्ट हैं जो इस बारे में बात कर रही हैं:

https://coderstower.com/2019/03/26/dependency-inversion-why-you-shouldnt-avoid-it/

https://coderstower.com/2019/04/02/main-and-abstraction-the-decoupled-peers/

https://coderstower.com/2019/04/09/inversion-of-control-putting-all-together/


-1

मान लीजिए कि हमारे पास दो वर्ग हैं: Engineerऔर Programmer:

क्लास इंजीनियर की प्रोग्रामर क्लास पर निर्भरता होती है, जैसे नीचे:

class Engineer () {

    fun startWork(programmer: Programmer){
        programmer.work()
    }
}

class Programmer {

    fun work(){
        //TODO Do some work here!
    }
}

इस उदाहरण में कक्षा Engineerका हमारी Programmerकक्षा पर निर्भरता है । अगर मुझे बदलने की जरूरत है तो क्या होगा Programmer?

जाहिर है मुझे Engineerभी बदलने की जरूरत है। (वाह, इस बिंदु OCPपर भी उल्लंघन किया जाता है)

फिर, इस गंदगी को साफ करने के लिए हमें क्या करना होगा? जवाब वास्तव में अमूर्त है। अमूर्तन द्वारा, हम इन दो वर्गों के बीच निर्भरता को दूर कर सकते हैं। उदाहरण के लिए, मैं Interfaceप्रोग्रामर वर्ग के लिए बना सकता हूं और अब से हर वर्ग जो इसका उपयोग करना चाहता है, Programmerउसका उपयोग करना है Interface, फिर प्रोग्रामर वर्ग को बदलकर, हमें किसी भी वर्ग को बदलने की आवश्यकता नहीं है जो इसका इस्तेमाल करते हैं, क्योंकि हम अमूर्तता के कारण हैं। उपयोग किया गया।

नोट: DependencyInjectionहमें DIPऔर SRPभी करने में मदद कर सकता है ।


-1

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

कहते हैं, आप कंसोल I / O के माध्यम से एक स्ट्रिंग को बेस 64 प्रारूप में बदलने के लिए एक छोटा कार्यक्रम चाहते हैं । यहाँ भोली दृष्टिकोण है:

class Program
{
    static void Main(string[] args)
    {
        /*
         * BadEncoder: High-level class *contains* low-level I/O functionality.
         * Hence, you'll have to fiddle with BadEncoder whenever you want to change
         * the I/O mode or details. Not good. A good encoder should be I/O-agnostic --
         * problems with I/O shouldn't break the encoder!
         */
        BadEncoder.Run();            
    }
}

public static class BadEncoder
{
    public static void Run()
    {
        Console.WriteLine(Convert.ToBase64String(Encoding.UTF8.GetBytes(Console.ReadLine())));
    }
}    

डीआईपी मूल रूप से कहता है कि उच्च-स्तरीय घटकों को निम्न-स्तर के कार्यान्वयन पर निर्भर नहीं होना चाहिए, जहां रॉबर्ट सी मार्टिन ("क्लीन आर्किटेक्चर") के अनुसार "स्तर" I / O से दूरी है। लेकिन आप इस भविष्यवाणी से कैसे बाहर निकलते हैं? बस केंद्रीय एनकोडर को केवल उन लोगों को परेशान किए बिना इंटरफेस पर निर्भर बनाकर कैसे लागू किया जाता है:

class Program
{
    static void Main(string[] args)
    {           
        /* Demo of the Dependency Inversion Principle (= "High-level functionality
         * should not depend upon low-level implementations"): 
         * You can easily implement new I/O methods like
         * ConsoleReader, ConsoleWriter without ever touching the high-level
         * Encoder class!!!
         */            
        GoodEncoder.Run(new ConsoleReader(), new ConsoleWriter());        }
}

public static class GoodEncoder
{
    public static void Run(IReadable input, IWriteable output)
    {
        output.WriteOutput(Convert.ToBase64String(Encoding.ASCII.GetBytes(input.ReadInput())));
    }
}

public interface IReadable
{
    string ReadInput();
}

public interface IWriteable
{
    void WriteOutput(string txt);
}

public class ConsoleReader : IReadable
{
    public string ReadInput()
    {
        return Console.ReadLine();
    }
}

public class ConsoleWriter : IWriteable
{
    public void WriteOutput(string txt)
    {
        Console.WriteLine(txt);
    }
}

ध्यान दें कि GoodEncoderI / O मोड को बदलने के लिए आपको स्पर्श करने की आवश्यकता नहीं है - यह वर्ग उस I / O इंटरफेस से खुश है जो इसे जानता है; किसी भी निम्न-स्तरीय कार्यान्वयन IReadableऔर IWriteableइसे कभी परेशान नहीं करेंगे।


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

-2

निर्भरता उलटा सिद्धांत (डीआईपी) का कहना है कि

i) उच्च स्तर के मॉड्यूल को निम्न-स्तर के मॉड्यूल पर निर्भर नहीं होना चाहिए। दोनों को अमूर्तता पर निर्भर होना चाहिए।

ii) अंश कभी भी विवरण पर निर्भर नहीं होना चाहिए। विवरण अमूर्तता पर निर्भर होना चाहिए।

उदाहरण:

    public interface ICustomer
    {
        string GetCustomerNameById(int id);
    }

    public class Customer : ICustomer
    {
        //ctor
        public Customer(){}

        public string GetCustomerNameById(int id)
        {
            return "Dummy Customer Name";
        }
    }

    public class CustomerFactory
    {
        public static ICustomer GetCustomerData()
        {
            return new Customer();
        }
    }

    public class CustomerBLL
    {
        ICustomer _customer;
        public CustomerBLL()
        {
            _customer = CustomerFactory.GetCustomerData();
        }

        public string GetCustomerNameById(int id)
        {
            return _customer.GetCustomerNameById(id);
        }
    }

    public class Program
    {
        static void Main()
        {
            CustomerBLL customerBLL = new CustomerBLL();
            int customerId = 25;
            string customerName = customerBLL.GetCustomerNameById(customerId);


            Console.WriteLine(customerName);
            Console.ReadKey();
        }
    }

नोट: क्लास को इंटरफ़ेस या अमूर्त कक्षाओं जैसे सार पर निर्भर होना चाहिए, न कि विशिष्ट विवरण (इंटरफ़ेस का कार्यान्वयन) पर।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.