जब निर्भरता उलटा सिद्धांत लागू करने के लिए नहीं?


43

मैं फिलहाल SOLID का पता लगाने की कोशिश कर रहा हूं। तो डिपेंडेंसी इनवर्सन प्रिंसिपल का मतलब है कि किसी भी दो वर्गों को इंटरफेस के माध्यम से संवाद करना चाहिए, सीधे नहीं। उदाहरण: यदि class Aएक विधि है, जो किसी प्रकार की वस्तु के लिए एक संकेतक की अपेक्षा करती है class B, तो इस विधि को वास्तव में प्रकार की वस्तु की अपेक्षा करनी चाहिए abstract base class of B। यह Open / Close के लिए भी मदद करता है।

बशर्ते कि मैं समझ गया कि सही ढंग से, मेरा सवाल यह होगा कि क्या यह सभी वर्ग इंटरैक्शन के लिए लागू करना एक अच्छा अभ्यास है या मुझे परतों के संदर्भ में सोचने की कोशिश करनी चाहिए ?

मेरे संदेह का कारण यह है कि हम इस सिद्धांत का पालन करने के लिए कुछ कीमत अदा कर रहे हैं। कहो, मुझे सुविधा लागू करने की आवश्यकता है Z। विश्लेषण के बाद, मैं यह निष्कर्ष निकालता हूं कि इस सुविधा Zमें कार्यक्षमता है A, Bऔर C। मैं एक मुखौटा वर्ग बनाता हूं Z, जो इंटरफेस के माध्यम से, कक्षाओं का उपयोग करता है A, Bऔर C। मैं कार्यान्वयन को कोड करना शुरू कर देता हूं और कुछ बिंदु पर मुझे एहसास होता है कि Zवास्तव में कार्य में कार्यक्षमता शामिल है A, Bऔर D। अब मुझे Cइंटरफ़ेस, Cक्लास प्रोटोटाइप को अलग करने Dऔर अलग इंटरफ़ेस और क्लास लिखने की आवश्यकता है । इंटरफेस के बिना, केवल कक्षा को बदलने की आवश्यकता होगी।

दूसरे शब्दों में, कुछ को बदलने के लिए, मुझे 1. कॉल करने वाले को बदलने की आवश्यकता है 2. इंटरफ़ेस 3. घोषणा 4. कार्यान्वयन। एक अजगर सीधे युग्मित कार्यान्वयन में, मुझे केवल कार्यान्वयन को बदलना होगा ।


13
निर्भरता उलटा बस एक तकनीक है, इसलिए इसे केवल तब ही लागू किया जाना चाहिए जब जरूरत हो ... उस डिग्री की कोई सीमा नहीं है जिसे इसे लागू किया जा सकता है, इसलिए यदि आप इसे हर जगह लागू करते हैं, तो आप कचरे के साथ समाप्त होते हैं: हर दूसरी स्थिति के साथ -स्पेशल तकनीक।
फ्रैंक हिलमैन

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

@rwong एक इंटरफ़ेस संविदात्मक आक्रमणकारियों को तभी पकड़ता है जब आप संविदात्मक सहायक का समर्थन करने वाली भाषा का उपयोग करते हैं। आम भाषाओं में (Java, C #), एक इंटरफ़ेस बस एपीआई हस्ताक्षरों का एक समूह है। अति सुंदर इंटरफेस को जोड़ने से केवल एक डिज़ाइन ख़राब होता है।
फ्रैंक हिलमैन

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

जवाबों:


87

कई कार्टून या अन्य मीडिया में, अच्छे और बुरे की ताकतों को अक्सर एक दूत और चरित्र के कंधों पर बैठे एक दानव द्वारा चित्रित किया जाता है। हमारी कहानी में, अच्छे और बुरे के बजाय, हमारे पास एक कंधे पर ठोस है, और YAGNI (आपको इसकी आवश्यकता नहीं है!) दूसरे पर बैठे हैं।

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

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

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


19
एसओएलआईडी से मेरा पहला परिचय लगभग 15 साल पहले एक नई प्रणाली पर था जो हम बना रहे थे। हम सभी ने कूल सहायता आदमी को पिया। किसी को भी कुछ भी उल्लेख किया है कि अगर लग रहा था YAGNI की तरह, हम जैसे "Pfffft ... सर्वसाधारण" थे। अगले दशक के दौरान उस प्रणाली को विकसित करने का मेरा सम्मान (डरावना) था। यह एक ऐसी अनजानी गड़बड़ बन गई जिसे कोई समझ नहीं सकता था, हम संस्थापकों को भी नहीं। आर्किटेक्ट्स को SOLID पसंद है। जो लोग वास्तव में अपने जीवित प्यार YAGNI कमाते हैं। न तो एकदम सही है, लेकिन YAGNI के पास एकदम सही है, और आपका डिफ़ॉल्ट होना चाहिए अगर आपको नहीं पता कि आप क्या कर रहे हैं। :-)
कैल्फ़ूल

11
@ हाँ, हम एक परियोजना पर किया था। इसके साथ पागल हो गया। ओवर-मॉकिंग के कारण अब हमारे परीक्षणों को पढ़ना या बनाए रखना असंभव है। उसके ऊपर, निर्भरता इंजेक्शन के कारण, यह कोड के माध्यम से नेविगेट करने के लिए रियर में एक दर्द है जब आप कुछ जानने की कोशिश कर रहे हैं। ठोस चांदी की गोली नहीं है। YAGNI चांदी की गोली नहीं है। स्वचालित परीक्षण एक चांदी की गोली नहीं है। कुछ भी नहीं की कड़ी मेहनत करने से आप को बचा सकता सोच तुम क्या कर रहे हैं और करने के बारे में निर्णय लेने के बारे में यह मदद या बाधा आपके कार्यालय या किसी और के लिए हो रहा है या नहीं।
jpmc26

22
यहां बहुत सारा सॉलिड-सेंटीमेंट है। SOLID और YAGNI एक स्पेक्ट्रम के दो छोर नहीं हैं। वे एक चार्ट पर X और Y निर्देशांक की तरह हैं। एक अच्छी प्रणाली में बहुत कम कोड (YAGNI) होता है और SOLID सिद्धांतों का पालन करता है।
स्टीफन

31
मेह, (ए) मैं असहमत हूं कि SOLID = enterprisey और (b) SOLID का पूरा बिंदु यह है कि हम बेहद गरीब पूर्वानुमान लगाते हैं, जिसकी आवश्यकता होगी। मुझे यहां @Stephen से सहमत होना होगा। YAGNI का कहना है कि हमें भविष्य की आवश्यकताओं की आशा करने की कोशिश नहीं करनी चाहिए जो आज स्पष्ट रूप से नहीं हैं। SOLID का कहना है कि हमें समय के साथ डिजाइन को विकसित करने की उम्मीद करनी चाहिए और इसे सरल बनाने के लिए कुछ सरल तकनीकों को लागू करना चाहिए। वे परस्पर अनन्य नहीं हैं ; दोनों बदलती आवश्यकताओं के अनुकूल होने की तकनीकें हैं। वास्तविक समस्याएं तब होती हैं जब आप अस्पष्ट या बहुत दूर की आवश्यकताओं के लिए डिजाइन करने का प्रयास करते हैं।
Aaronaught

8
"आप आसानी से एक नेटवर्क स्ट्रीम के लिए एक फ़ाइल से पढ़ने को स्वैप कर सकते हैं" - यह एक अच्छा उदाहरण है जहां डीआई का एक अधिक सरल विवरण लोगों को भटकाता है। लोग कभी-कभी सोचते हैं (वास्तव में), "यह विधि एक का उपयोग करेगी File, इसलिए इसके बजाय यह IFileकाम करेगा, काम किया है"। तब वे आसानी से एक नेटवर्क स्ट्रीम को स्थानापन्न नहीं कर सकते हैं , क्योंकि उन्होंने इंटरफ़ेस की अधिक मांग की है, और ऐसे ऑपरेशन हैं IFileजो उपयोग नहीं करते हैं, जो सॉकेट पर लागू नहीं होते हैं, इसलिए सॉकेट लागू नहीं हो सकता है IFile। डीआई के लिए एक चांदी की गोली नहीं है, चीजों में से एक सही सार (इंटरफेस) का आविष्कार कर रहा है :-)
स्टीव जेसप

11

आम आदमी के शब्दों में:

डीआईपी लागू करना आसान और मजेदार दोनों है । पहले प्रयास में डिजाइन सही नहीं मिलना डीआईपी पर पूरी तरह से देने का पर्याप्त कारण नहीं है।

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

दूसरी ओर, इंटरफेस और OOD के साथ प्रोग्रामिंग प्रोग्रामिंग के कभी-कभी बासी शिल्प में खुशी ला सकती है।

कुछ लोग कहते हैं कि यह जटिलता को जोड़ता है लेकिन मुझे लगता है कि ऑपोसिट सच है। छोटी परियोजनाओं के लिए भी। यह परीक्षण / मज़ाक करना आसान बनाता है। यदि कोई caseस्टेटमेंट या नेस्टेड है तो यह आपके कोड को कम करता है ifs। यह चक्रीय जटिलता को कम करता है और आपको नए तरीके से सोचने पर मजबूर करता है। यह वास्तविक दुनिया के डिजाइन और विनिर्माण के लिए प्रोग्रामिंग को और अधिक समान बनाता है।


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

यह उत्तर डीआई के बारे में क्यों बात कर रहा है अगर सवाल डीआईपी के बारे में था? डीआईपी एक अवधारणा है 1990 से, जबकि डीआई 2004 से है। वे बहुत अलग हैं।
रोजेरियो

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

@ रोजेरियो आमतौर पर डीआई का उपयोग करते समय, प्रत्येक वर्ग एक अलग इंटरफ़ेस लागू नहीं करता है। कई वर्गों द्वारा लागू किया जा रहा एक इंटरफ़ेस आम है।
ट्यूलेंस कोरडोवा

@ रोजेरियो मैंने अपना जवाब सही किया, हर बार जब मैंने डि का उल्लेख किया तो मेरा मतलब डीआईपी था।
ट्यूलेंस कोर्डोवा 11

9

निर्भरता उलटा का उपयोग करें जहां यह समझ में आता है।

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

यदि आपके पास एक मॉड्यूल में आंतरिक रूप से उपयोग की जाने वाली वस्तुओं का एक समूह है जो अन्य मॉड्यूल के संपर्क में नहीं हैं या कहीं भी उपयोग नहीं किए जाते हैं, तो यह संभवतः DI का उपयोग करने के प्रयास के लायक नहीं है।

मेरी राय में डीआई को स्वचालित रूप से उपयोग किए जाने के दो स्थान हैं:

  1. विस्तार के लिए डिज़ाइन किए गए मॉड्यूल में । यदि एक मॉड्यूल का पूरा उद्देश्य इसे विस्तारित करना और व्यवहार को बदलना है, तो यह शुरू से ही DI को सेंकना करने के लिए सही समझ में आता है।

  2. मॉड्यूल में जो आप कोड पुन: उपयोग के उद्देश्य के लिए रिफैक्टिंग कर रहे हैं। शायद आपने कुछ करने के लिए एक वर्ग को कोडित किया है, फिर बाद में एहसास होता है कि एक रिफ्लेक्टर के साथ आप उस कोड को कहीं और ले सकते हैं और ऐसा करने की आवश्यकता है । यह DI और अन्य एक्स्टेंसिबिलिटी परिवर्तनों के लिए एक महान उम्मीदवार है।

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

DI एक महान उपकरण है, लेकिन किसी भी * उपकरण की तरह, इसका अत्यधिक उपयोग या दुरुपयोग हो सकता है।

* उपरोक्त नियम के अपवाद: एक देखा जाने वाला कार्य किसी भी नौकरी के लिए सही उपकरण है। यदि यह आपकी समस्या को ठीक नहीं करता है, तो यह इसे हटा देगा। स्थायी रूप से।


3
क्या होगा अगर "आपकी समस्या" दीवार में एक छेद है? एक आरा इसे नहीं हटाएगा; यह इसे बदतर बना देगा। ;)
मेसन व्हीलर

3
@MasonWheeler एक शक्तिशाली और मजेदार उपयोग के साथ देखा, "दीवार में छेद" "द्वार" में बदल सकता है जो एक उपयोगी संपत्ति है :-)

1
आप छेद के लिए एक पैच बनाने के लिए एक आरा का उपयोग नहीं कर सकते हैं?
जेफ़ओ

हालांकि गैर-उपयोगकर्ता-एक्स्टेंसिबल Stringप्रकार के होने के कुछ फायदे हैं , ऐसे कई मामले हैं जहां वैकल्पिक प्रतिनिधित्व उपयोगी होगा यदि प्रकार में वर्चुअल ऑपरेशन का एक अच्छा सेट था (उदाहरण के लिए, निर्दिष्ट के एक हिस्से के एक विकल्प की प्रतिलिपि बनाएँ short[], रिपोर्ट करें कि क्या ए सबरिंग में केवल ASCII शामिल हो सकता है, किसी विकल्प के एक निर्दिष्ट भाग में ASCII को शामिल करने के लिए विश्वास किए गए सबस्ट्रिंग को कॉपी करने का प्रयास करें byte[], आदि) यह बहुत बुरा फ्रेमवर्क है उनके स्ट्रिंग प्रकार किसी भी उपयोगी स्ट्रिंग-संबंधित इंटरफेस को लागू नहीं करते हैं।
सुपरकैट

1
यह उत्तर डीआई के बारे में क्यों बात कर रहा है अगर सवाल डीआईपी के बारे में था? डीआईपी एक अवधारणा है 1990 से, जबकि डीआई 2004 से है। वे बहुत अलग हैं।
रोजेरियो

5

यह मुझे लगता है कि मूल प्रश्न डीआईपी के बिंदु से गायब है।

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

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

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

एक बार जब आप काम कर चुके होते हैं तो आपको किस वर्ग की Z की जरूरत होती है और किस तरह से उसे क्या चाहिए, इसके लिए आप फिर विवरण भर सकते हैं। निश्चित रूप से, कभी-कभी कक्षा Z में बदलाव करने की आवश्यकता होगी, लेकिन 99% समय ऐसा नहीं होगा।

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


5

संक्षिप्त उत्तर "लगभग कभी नहीं" है, लेकिन वास्तव में, कुछ स्थानों पर जहां डीआईपी का कोई मतलब नहीं है:

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

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

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

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

  5. यूनिट परीक्षण, और परीक्षण युगल। नकली और स्टब्स को एक काम करना चाहिए और इसे बस करना चाहिए। यदि आपके पास एक नकली है जो इस बारे में चिंता करने के लिए पर्याप्त जटिल है कि क्या निर्भरता इंजेक्शन करना है या नहीं, तो यह शायद बहुत जटिल है (शायद इसलिए कि यह एक इंटरफ़ेस लागू कर रहा है जो बहुत दूर है)।

और भी हो सकता है; ये वे हैं जिन्हें मैं कुछ हद तक देखता हूं ।


कैसे "किसी भी समय आप एक गतिशील भाषा में काम कर रहे हैं" के बारे में?
केविन

नहीं? मैं जावास्क्रिप्ट में बहुत काम करता हूं और यह अभी भी वहां समान रूप से लागू होता है। हालांकि, SOLID में "O" और "I" को थोड़ा धुंधला हो सकता है।
Aaronaught

हुह ... मुझे लगता है कि अजगर टाइपिंग के साथ संयुक्त पायथन के प्रथम श्रेणी के प्रकार इसे कम आवश्यक नहीं बनाते हैं।
केविन

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

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

2

कुछ संकेत आप डीआईपी को एक स्तर के बहुत सूक्ष्म स्तर पर लागू कर सकते हैं, जहां यह मूल्य प्रदान नहीं कर रहा है:

  • आपके पास C / CImpl या IC / C जोड़ी है, उस इंटरफ़ेस का केवल एक ही कार्यान्वयन है
  • आपके इंटरफ़ेस और कार्यान्वयन में हस्ताक्षर एक-से-एक (DRY सिद्धांत का उल्लंघन) से मेल खाते हैं
  • आप अक्सर एक ही समय में C और CImpl बदलते हैं।
  • C आपके प्रोजेक्ट के लिए आंतरिक है और लाइब्रेरी के रूप में आपके प्रोजेक्ट के बाहर साझा नहीं किया गया है।
  • आप एक्लिप्स / F12 में F3 से निराश होकर विजुअल स्टूडियो में वास्तविक कक्षा के बजाय इंटरफ़ेस पर ले जा रहे हैं

यदि यह वही है जो आप देख रहे हैं, तो आप सीधे जेड कॉल सी होने से बेहतर हो सकते हैं और इंटरफ़ेस को छोड़ सकते हैं।

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

इस ब्लॉग पोस्ट को भी देखें ।


0

यदि आप हमेशा अपनी निर्भरता को उलटते हैं, तो आपकी सारी निर्भरताएं उलटी हो जाती हैं। जिसका अर्थ है कि यदि आप निर्भरता की एक गाँठ के साथ गन्दा कोड के साथ शुरू करते हैं, तो यह वही है जो अभी भी (वास्तव में) है, बस उलटा है। यह वह जगह है जहां आपको यह समस्या आती है कि कार्यान्वयन के लिए हर बदलाव को अपना इंटरफ़ेस भी बदलना होगा।

निर्भरता उलटने की बात यह है कि आप उन निर्भरता को चुनिंदा रूप से उलट रहे हैं जो चीजों को उलझा रही हैं। जिन लोगों को A से B तक जाना चाहिए, वे अभी भी ऐसा करते हैं, यह वही हैं जो C से A तक जा रहे थे जो अब A से C तक जाते हैं।

परिणाम एक निर्भरता ग्राफ होना चाहिए जो चक्रों से मुक्त है - एक डीएजी। कर रहे हैं विभिन्न उपकरणों है कि इस संपत्ति की जाँच करेगा, और ग्राफ आकर्षित।

फुलर स्पष्टीकरण के लिए, यह लेख देखें :

निर्भरता उलटा सिद्धांत को सही ढंग से लागू करने का सार यह है:

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

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

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