2008-12-09 11 views
38

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

क्या यह सही है और क्या यह एक नियम है जिसका हमेशा पालन किया जाना चाहिए?

कारण मैं पूछता हूं कि मैंने हाल ही में 100 अलग-अलग वस्तुओं के साथ एक सिस्टम पर काम किया है। कुछ साझा आम इंटरफेस लेकिन अधिकांश लोग आश्चर्य नहीं करते हैं कि क्या उन वर्गों में प्रत्येक संपत्ति और फ़ंक्शन को मिरर करना चाहिए?

मैं सी # और डॉट नेट 2.0 का उपयोग कर रहा हूं हालांकि मुझे विश्वास है कि यह प्रश्न कई भाषाओं में फिट होगा।

+0

सही से, आपको चाहिए। बाईं ओर, आपके पास एक जनरेटर होना चाहिए जो आपके लिए "बॉयलरप्लेट" करता है। – Pacerier

उत्तर

52

यह उन वस्तुओं के लिए उपयोगी है जो वास्तव में एक सेवा - प्रमाणीकरण, भंडारण इत्यादि प्रदान करते हैं। सरल प्रकारों के लिए जिनके पास कोई और निर्भरता नहीं है, और जहां कभी भी कोई वैकल्पिक कार्यान्वयन नहीं होता है, मुझे लगता है कि इसका उपयोग करना ठीक है ठोस प्रकार

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

13

वास्तव में नहीं। सेवा घटक (वर्ग जो आपके आवेदन के लिए चीजें करता है) इंटरफेस के लिए एक अच्छा फिट है, लेकिन एक नियम के रूप में, मैं बुनियादी इकाई वर्गों के लिए इंटरफेस रखने से परेशान नहीं होगा।

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

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

8

मैं केवल इंटरफेस का उपयोग करता हूं जहां अमूर्तता का स्तर आवश्यक था - यानी आपको पॉलिमॉर्फिक व्यवहार का उपयोग करने की आवश्यकता है। सामान्य उदाहरण निर्भरता इंजेक्शन होंगे या जहां आपके पास कहीं भी फैक्ट्री-प्रकार का परिदृश्य होगा, या आपको "एकाधिक विरासत" प्रकार का व्यवहार स्थापित करने की आवश्यकता है।

मेरे मामले में, मेरी विकास शैली के साथ, यह अक्सर होता है (मैं यूआई नियंत्रण के अलावा अन्य चीजों के लिए गहरी विरासत पदानुक्रमों पर एकत्रीकरण का पक्ष लेता हूं), लेकिन मैंने बहुत अच्छे ऐप्स देखे हैं जो बहुत कम उपयोग करते हैं। यह सब निर्भर करता है ...

ओह हाँ, और यदि आप इंटरफेस में भारी रूप से जाते हैं - वेब सेवाओं से सावधान रहें। यदि आपको किसी वेब सेवा के माध्यम से अपनी ऑब्जेक्ट विधियों का पर्दाफाश करने की आवश्यकता है तो वे वास्तव में वापस नहीं आ सकते हैं या इंटरफ़ेस प्रकार नहीं ले सकते हैं, केवल ठोस प्रकार (जब तक कि आप अपने सभी क्रमिकरण/deserialization को हाथ से लिखने के लिए नहीं जा रहे हैं)। हां, जिसने मुझे बड़ा समय बिगाड़ दिया है ...

3

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

उदाहरण के लिए मेरे सीएएम आवेदन में मेरे पास एक कटिंगपैथ पॉइंट्स के संग्रह से जुड़ा हुआ है। आईपॉइंटलिस्ट इंटरफेस रखने का कोई मतलब नहीं है क्योंकि कटिंगपैथ हमेशा मेरे आवेदन में अंक शामिल होंगे।

हालांकि मैं मशीन के साथ संवाद करने के लिए इंटरफ़ेस IMotionController का उपयोग करता हूं क्योंकि हम अपने स्वयं के प्रशंसा सेट और संचार की विधि के साथ कई अलग-अलग प्रकार की काटने की मशीन का समर्थन करते हैं। तो उस स्थिति में इसे एक इंटरफेस के पीछे रखना समझ में आता है क्योंकि एक इंस्टॉलेशन किसी अन्य मशीन की तुलना में एक अलग मशीन का उपयोग कर सकता है।

हमारे आवेदन 80 के दशक के मध्य से बनाए रखा गया है और 90 के उत्तरार्ध में ऑब्जेक्ट उन्मुख डिजाइन में गया है। मैंने पाया है कि जो कुछ मैंने मूल रूप से सोचा था उससे अधिक परिवर्तन हो सकता था और इंटरफेस का उपयोग बढ़ गया है। उदाहरण के लिए यह होता था कि हमारे ड्रॉइंगपैथ में अंक शामिल थे। लेकिन अब इसमें इकाइयों (splines, arcs, ec) शामिल हैं, इसलिए यह एक EntityList की ओर इशारा किया गया है जो ऑब्जेक्टिटी इंटेलिजेंस को कार्यान्वित करने का ऑब्जेक्ट का संग्रह है।

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

ध्यान दें कि हमारे सिस्टम में ड्रॉइंगपैथ को निम्न स्तर के काटने वाले पथ पर प्रस्तुत किया जाता है जो हमेशा बिंदु खंडों की श्रृंखला होती है।

1

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

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

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

5

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

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

+1

इंटरफेस विरासत की अनुमति है। क्या यह वही काम नहीं करेगा? –

+0

आप एक बहुत अच्छा मुद्दा बनाते हैं, शॉन, लेकिन मेरे पास टॉम के समान प्रश्न है। क्या हुआ होगा अगर उन्होंने 'आईएसट्रीम 2: आईएसट्रीम' प्रकाशित किया था? बड़ी गड़बड़ी? क्या आप विस्तार से समझा सकते हैं? – toddmo

2

मैंने हाल ही में एक परियोजना पर 'इंटरफ़ेस को कोड' की सलाह लेने की कोशिश की। इंटरफ़ेस (बड़े I) कार्यान्वयन में एक बार सटीक रूप से प्रत्येक वर्ग के सार्वजनिक इंटरफ़ेस (छोटे i) का अंतिम परिणाम डुप्लिकेशंस था। यह अभ्यास में सुंदर व्यर्थ है। - और यदि आपके कोड है

Print() 
Draw() 
Save() 
Serialize() 
Update() 

... आदि आदि इसका मतलब यह है वर्गों जिसका प्राथमिक भूमिका डाटा स्टोर करने के लिए है कि:

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

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

+1

इंटरफेस संज्ञा, संज्ञा वाक्यांश या विशेषण होना चाहिए जो व्यवहार का वर्णन करते हैं; क्रिया नहीं एक क्रिया एक क्रिया है; इंटरफेस क्रिया नहीं हैं। क्रियाएं और क्रिया वाक्यांश विधियों के लिए हैं। आपके उदाहरण होना चाहिए: प्रिंट करने योग्य, Drawable, Savable, Serializable, और अद्यतन करने योग्य। –

+1

@FrederikKrautwald आपने मेरे बिंदु को गलत समझा है। सूचीबद्ध क्रियाओं में उन पर कोष्ठक हैं, जो दर्शाते हैं कि वे विधियां हैं। वे जिन इंटरफेस से संबंधित हैं, उनके नाम नहीं हैं। तो मेरा जवाब वास्तव में आपके द्वारा अभी जो कहा गया है, उसके विपरीत नहीं है, जो मुझे लगता है कि यह काफी सही है। –

+0

मुझे खेद है। मैंने गलत समझा, "अपने इंटरफ़ेस कार्यान्वयन को क्रियाओं तक सीमित करें।" –

संबंधित मुद्दे