क्या "इंटरफ़ेस की आवश्यकता है" केवल उसी के लिए पूछें जो आपको चाहिए?


9

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

उदाहरण के लिए, यदि मेरे पास हटाए गए प्रकारों का एक गुच्छा है, तो मैं एक Deletableइंटरफ़ेस बनाऊंगा:

interface Deletable {
   void delete();
}

फिर मैं एक सामान्य वर्ग लिख सकता हूं:

class Deleter<T extends Deletable> {
   void delete(T t) {
      t.delete();
   }
}

कोड में कहीं और मैं हमेशा क्लाइंट कोड की जरूरतों को पूरा करने के लिए सबसे छोटी संभव जिम्मेदारी मांगूंगा। इसलिए अगर मुझे केवल हटाने की आवश्यकता है File, तो मैं अभी भी एक Deletableनहीं, एक के लिए पूछूंगा File

क्या यह सिद्धांत सामान्य ज्ञान है और पहले से ही एक स्वीकृत नाम है? क्या यह विवादास्पद है? क्या पाठ्य पुस्तकों में इसकी चर्चा है?


1
लूज कपलिंग हो सकता है? या संकीर्ण इंटरफेस?
tdammers

जवाबों:


16

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


4

वादिम के बहुत अच्छे उत्तर पर विस्तार करने के लिए, मैं "नहीं, वास्तव में नहीं" के साथ "यह विवादास्पद है" सवाल का जवाब देगा।

सामान्य तौर पर, इंटरफ़ेस पृथक्करण एक अच्छी बात है, इसमें शामिल विभिन्न वस्तुओं के "कारणों को बदलने" की कुल संख्या को कम करके। मुख्य सिद्धांत यह है, जब कई तरीकों के साथ एक इंटरफ़ेस को बदलना होगा, इंटरफ़ेस विधियों में से एक में एक पैरामीटर जोड़ने के लिए कहें, तो इंटरफ़ेस के सभी उपभोक्ताओं को कम से कम recompiled होना चाहिए, भले ही उन्होंने उस पद्धति का उपयोग न किया हो जो बदल गया हो। "लेकिन यह सिर्फ एक recompile है!", मैंने सुना है आप कहते हैं; यह सच हो सकता है, लेकिन ध्यान रखें कि आम तौर पर, जो कुछ भी आप recompile करते हैं, उसे सॉफ्टवेयर पैच के हिस्से के रूप में बाहर धकेल दिया जाना चाहिए, चाहे वह बाइनरी में कितना भी महत्वपूर्ण क्यों न हो। इन नियमों को मूल रूप से 90 के दशक में शुरू किया गया था, जब आपकी डेस्कटॉप में औसत डेस्कटॉप वर्कस्टेशन फोन की तुलना में कम शक्तिशाली था, 14.4k बॉड डायल-अप ब्लेज़िन था, और 3.5 "1.44MB" फ्लॉपीज़ "प्राथमिक हटाने योग्य मीडिया थे। यहां तक ​​कि 3 जी / 4 जी के वर्तमान युग में, वायरलेस इंटरनेट उपयोगकर्ताओं के पास अक्सर सीमा के साथ डेटा योजनाएं होती हैं, इसलिए जब एक नवीनीकरण जारी किया जाता है, तो कम बायनेरिज़ को डाउनलोड किया जाना चाहिए, बेहतर।

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

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

इंटरफ़ेस पृथक्करण उन वर्गों पर आधारित होना चाहिए जो इंटरफ़ेस पर निर्भर हैं:

  • यदि इंटरफ़ेस पर केवल एक वर्ग निर्भर है, तो अलग न करें। यदि वर्ग इंटरफ़ेस विधियों में से एक या अधिक का उपयोग नहीं करता है, और यह इंटरफ़ेस का एकमात्र उपभोक्ता है, तो संभावना है कि आपको उन तरीकों को पहले स्थान पर उजागर नहीं करना चाहिए।

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

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


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

सामान्य प्रकार के मापदंडों को कई इंटरफेसों के कार्यान्वयन सहित मानदंडों के साथ परिभाषित किया जा सकता है, लेकिन आप सही हैं कि एक स्थिर प्रकार की आवश्यकता वाले भाव आमतौर पर एक से अधिक निर्दिष्ट करने का समर्थन नहीं कर सकते हैं। यदि कोई आवश्यकता है कि एक स्थिर प्रकार IFoo और IBAR दोनों को लागू करता है, और आप उन दोनों इंटरफेस को नियंत्रित करते हैं, तो इसे लागू करने IBaz : IFoo, IBarऔर इसके बजाय इसे लागू करने के लिए एक अच्छा विचार हो सकता है ।
कीथ्स

यदि क्लाइंट कोड को किसी ऐसी चीज की आवश्यकता हो सकती है जिसका उपयोग किया जा सकता है IFooऔर IBar, एक समग्र IFooBarको परिभाषित करना एक अच्छा विचार हो सकता है, लेकिन यदि इंटरफेस को बारीक रूप से विभाजित किया जाता है, तो दर्जनों अलग-अलग इंटरफ़ेस प्रकारों की आवश्यकता होती है। निम्नलिखित सुविधाओं के संग्रह पर विचार कर सकते हैं: गणना करें, गणना करें, nth तत्व पढ़ें, nth तत्व लिखें, nth तत्व से पहले सम्मिलित करें, nth तत्व हटाएं, नया आइटम (नए संग्रह का विस्तार और वापसी सूचकांक), और जोड़ें। नौ तरीके: ECRWIDNA। मैं शायद दर्जनों प्रकारों का वर्णन कर सकता हूं जो स्वाभाविक रूप से कई अलग-अलग संयोजनों का समर्थन करेंगे।
सुपरकैट

उदाहरण के लिए, ECRW का समर्थन करता है। एक सरणी सूची ECRWIDNA का समर्थन करेगी। एक थ्रेड-सुरक्षित सूची ECRWNA का समर्थन कर सकती है [हालांकि आम तौर पर केवल सूची को पूर्व-आबाद करने के लिए उपयोगी होगी]। केवल पढ़ने के लिए सरणी आवरण ECR का समर्थन कर सकता है। एक सहसंयोजक सूची इंटरफ़ेस ईसीआरडी का समर्थन कर सकता है। एक गैर-जेनेरिक इंटरफ़ेस प्रकार-सुरक्षित समर्थन C या CD प्रदान कर सकता है। यदि स्वैप एक विकल्प था, तो कुछ प्रकार सीएस का समर्थन कर सकते हैं, लेकिन डी (जैसे सरणियों) का नहीं, जबकि अन्य सीडीएस का समर्थन करेंगे। क्षमताओं के प्रत्येक आवश्यक संयोजन के लिए अलग इंटरफ़ेस प्रकारों को परिभाषित करने की कोशिश एक बुरा सपना होगा।
सुपरकैट

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