क्या मुझे हर वर्ग को एक इंटरफ़ेस का पालन करना चाहिए?


10

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

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

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

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


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

जवाबों:


6

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

यह एक आधार वर्ग से बहुरूपता को विघटित करता है, और एक अनुबंध को लागू करके वर्ग श्रृंखला सीमाओं के बीच भी संभव बनाता है।

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

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


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

7

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


6

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

हम आम तौर पर "इंटरफ़ेस" का उपयोग करते हैं interface"कीवर्ड का उपयोग करके परिभाषित" एक जावा वर्ग "या" केवल सार्वजनिक, शुद्ध आभासी कार्यों के साथ एक सी ++ वर्ग। " ये उपयोगी सार हैं, क्योंकि वे इसके कार्यान्वयन से एक वर्ग के इंटरफ़ेस को कम कर देते हैं।

उस के साथ, उचित होने पर इंटरफेस का उपयोग करें।

  • क्या एक इंटरफ़ेस के लिए कई कार्यान्वयन होंगे? यदि ऐसा है, तो यह स्थिति एक इंटरफ़ेस में आम, सार्वजनिक-सामना करने के तरीकों को निकालने के लिए एक उम्मीदवार हो सकती है।

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

ऊपर दिए गए शब्दों को ध्यान से देखें: "एक उम्मीदवार हो सकता है," उपयोगी हो सकता है। कोई भी कठिन और तेज़ नियम नहीं है जो किसी भी स्थिति के लिए "हां" या "नहीं" कहता है।

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

interface I {
  int getA()
  int getB()
  ...
  int getY()
  int getZ()
}

class C : I {
  int getA() { ... }
  int getB() { ... }
  ...
  int getY() { ... }
  int getZ() { ... }
}

इंटरफेस का एक और कारण यह है कि यदि आपका परीक्षण तंत्र इसे आवश्यक बनाता है, जो आपकी भाषा और परीक्षण-रूपरेखा पर निर्भर हो सकता है। उम्मीद है कि आपको यह करने की आवश्यकता नहीं है, बेशक।
Darien

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

कुछ बेहतरीन सामान यहाँ। बस इसे इंगित करना: एक इंटरफ़ेस सार्वजनिक-सामना करने के तरीकों और एक वर्ग के डेटा सदस्यों से ज्यादा कुछ नहीं है । जबकि यह एक इंटरफ़ेस कार्यान्वयन के लिए सच है , यह निश्चित रूप से एक इंटरफ़ेस के लिए सही नहीं है जो कभी लागू नहीं होता है, हालांकि दी गई - यह एक कोड गंध के कुछ होगा।
रॉबी डे

@RobbieDee यह उदाहरण के लिए सच है जैसे जावा interface, यह सिर्फ इतना होता है कि जावा में सब कुछ interfaceइसका सार्वजनिक-सामना करने वाला इंटरफ़ेस (OO अवधारणा) भी है।

हर कोई! उत्तर के दूसरे और तीसरे वाक्य को लिखिए। इसे टुकड़े टुकड़े करें। इसे अपने बटुए में रखो। संदर्भ अक्सर।
राडारोब

5

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

बहुत सारे अच्छे कारण हैं कि आपको कक्षाओं के एक सेट को फेंकने के बजाय बड़े विकास के लिए इंटरफेस पर विचार करना चाहिए।

मॉकिंग फ्रेमवर्क

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

निर्भरता अन्तःक्षेपण

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


इन दृष्टिकोणों को संक्षेप में SOLID सिद्धांतों से डी में रखा गया है । इसका रगड़ है - अमूर्तता का उपयोग करें, न कि संघनन।

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


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

@kai "आप IoC कंटेनर का उपयोग किए बिना DI का उपयोग कर सकते हैं" । मुझे लगता है कि अधिक परिपक्व विकास दुकानें (और कर सकती हैं)। ओस्टेंसिक रूप से एक सरल अवधारणा के लिए कोड को प्रदूषित करने की कोई आवश्यकता नहीं है। जोएल एक समान दृश्य है।
रॉबी डे

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