क्या केवल वर्गीकरण के लिए इंटरफ़ेस का उपयोग करना बुरा है?


12

उदाहरण के लिए:

मैं वर्ग का कहना है कि A, B, C। मैं दो इंटरफेस है, की सुविधा देता है उन्हें फोन IAnimalऔर IDogIDogसे विरासत में मिला है IAnimalAऔर Bकर रहे हैं IDog, रों जबकि Cनहीं है, लेकिन यह एक है IAnimal

महत्वपूर्ण हिस्सा यह है कि IDogकोई अतिरिक्त कार्यक्षमता की आपूर्ति नहीं करता है। इसका उपयोग केवल अनुमति देने के लिए किया जाता है Aऔर कुछ विधियों के तर्क के रूप में पारित Bनहीं Cकिया जाता है।

क्या यह बुरा अभ्यास है?


8
IAnimalऔर IDogकर रहे हैं भयानक अनुलाप नाम!

5
@JarrodRoberson जब मैं सहमत होता हूं, अगर आप .Net दुनिया में काम करते हैं, तो आप इसके साथ फंस जाते हैं (या अगर आप इसे अलग तरीके से करते हैं तो स्थापित सम्मेलन के खिलाफ जा रहे हैं)।
डेनियल बी

2
@JarrodRoberson IMHO MyProject.Data.IAnimalऔर MyProject.Data.Animalसे बेहतर हैं MyProject.Data.Interfaces.Animalऔर MyProject.Data.Implementations.Animal
माइक कोडर

1
मुद्दा यह है कि अगर यह एक Interfaceया Implementationएक दोहरावदार उपसर्ग या एक नाम स्थान में है, तो भी परवाह करने का कोई कारण नहीं होना चाहिए , यह किसी भी तरह से एक मनोविज्ञान है और DRY का उल्लंघन करता है। Dogआप सभी का ध्यान रखना चाहिए। PitBull extends Dogया तो अतिरेक को लागू करने की आवश्यकता नहीं है, शब्द extendsमुझे बताता है कि मुझे अपने मूल टिप्पणी में पोस्ट किए गए लिंक को जानना होगा।

1
@ जारारोड: मुझे शिकायत करना बंद करो। .NET देव टीम को शिकायत करें। अगर मैं मानक के विपरीत जाता, तो मेरे साथी देवता मेरी हिम्मत से नफरत करते।
केंडल फ्रे

जवाबों:


13

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

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

मैं विश्वास के साथ कह सकता हूं कि यह बुरा व्यवहार नहीं है क्योंकि मैंने ऑर्चर्ड प्रोजेक्ट में "मार्कर इंटरफ़ेस" पैटर्न का भारी उपयोग देखा है

यहाँ ऑर्चर्ड परियोजना से नमूना लिया गया है।

public interface ISingletonDependency : IDependency {}

/// <summary>
/// Base interface for services that may *only* be instantiated in a unit of work.
/// This interface is used to guarantee they are not accidentally referenced by a singleton dependency.
/// </summary>
public interface IUnitOfWorkDependency : IDependency {}

/// <summary>
/// Base interface for services that are instantiated per usage.
/// </summary>
public interface ITransientDependency : IDependency {}

कृपया मार्कर इंटरफ़ेस देखें ।


क्या विशेषताएँ / टिप्पणियां संकलन-समय जाँच (संदर्भ भाषा के रूप में C # का उपयोग करते हुए) का समर्थन करेंगी? मुझे पता है कि अगर ऑब्जेक्ट में विशेषता नहीं है तो मैं एक अपवाद फेंक सकता हूं, लेकिन इंटरफ़ेस पैटर्न संकलन समय पर त्रुटियों को पकड़ता है।
केंडल फ़्री

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

मैं उलझन में हूं। यह 'मार्कर इंटरफ़ेस' पैटर्न कंपाइल-टाइम चेक प्रदान करता है, जिसमें आप ए Cसे अपेक्षा करने वाले तरीके से पास नहीं हो सकते IDog
केंडल फ्रे

यदि आप इस पैटर्न का उपयोग कर रहे हैं, तो आप हिगली परावर्तक कार्य कर रहे हैं। मेरा मतलब है कि आप डायनामिक या स्टेटिकली टाइप चेक कर रहे हैं। मुझे यकीन है कि आप अपने उपयोग के मामले में कुछ गलत हैं, लेकिन मैंने यह नहीं देखा कि आप इसका उपयोग कैसे कर रहे हैं।
Freshblood

जैसा कि मैंने टेलस्टाइन के उत्तर पर टिप्पणी में किया था, मुझे इसका वर्णन करने दें। उदाहरण के लिए मेरे पास एक Kennelवर्ग है जो IDogएस की एक सूची संग्रहीत करता है ।
केंडल फ्रे

4

हां, यह लगभग हर भाषा में एक बुरा व्यवहार है।

प्रकार डेटा को एनकोड करने के लिए नहीं हैं; उन्हें यह साबित करने के लिए एक सहायता है कि आपका डेटा वह जाता है जहां उसे जाने की आवश्यकता होती है और ऐसा व्यवहार करता है जैसे उसे व्यवहार करने की आवश्यकता होती है। उप-प्रकार का एकमात्र कारण यह है कि यदि एक बहुरूपिक व्यवहार बदलता है (और हमेशा नहीं तो)।

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

[संपादित करें: स्पष्टीकरण]

मेरा मतलब है कि आप इंटरफ़ेस के आधार पर कुछ तर्क कर रहे हैं । कुछ तरीके केवल कुत्तों और अन्य किसी भी जानवर के साथ काम क्यों कर सकते हैं? यह अंतर एक निहित अनुबंध है क्योंकि कोई वास्तविक सदस्य नहीं है जो अंतर प्रदान करता है; सिस्टम में कोई वास्तविक डेटा नहीं है। एकमात्र अंतर इंटरफ़ेस है (इसलिए 'टाइपिंग नहीं' टिप्पणी), और इसका मतलब है कि प्रोग्रामर के बीच अंतर होगा। [/ संपादित करें]

कुछ भाषाएं ऐसे ट्रैक्ट मैकेनिज्म प्रदान करती हैं जहां यह बहुत बुरा नहीं है, लेकिन वे क्षमताओं पर ध्यान केंद्रित करते हैं, शोधन नहीं। मैं उनके साथ बहुत कम अनुभव करता हूं इसलिए वहां की सर्वोत्तम प्रथाओं से बात नहीं कर सकता। C ++ / Java / C # में ... अच्छा नहीं है।


मैं आपके बीच के दो पैराग्राफ से भ्रमित हूं। 'सब-टाइप' से आपका क्या तात्पर्य है? मैं इंटरफेस का उपयोग कर रहा हूं, जो अनुबंध हैं, कार्यान्वयन नहीं हैं, और मुझे यकीन नहीं है कि आपकी टिप्पणी कैसे लागू होती है। 'नो टाइपिंग' से आपका क्या तात्पर्य है? Ied निहित ’से आपका क्या तात्पर्य है? एक IDog वह सब कुछ कर सकता है जो एक IAnimal कर सकता है, लेकिन अधिक करने में सक्षम होने की गारंटी नहीं है।
केंडल फ्रे

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

@KendallFrey: या तो आप इंटरफ़ेस (खराब) से बाहर निकल रहे हैं, या आप एक कृत्रिम अंतर पैदा कर रहे हैं जो एक गलत अमूर्तता की खुशबू आ रही है।
तेलस्तीन

2
@ टेलस्टाइन - इंटरफ़ेस का उद्देश्य यह है कि मेटाडेटा प्रदान करना
Freshblood

1
@Telastyn: तो संकलन-समय जाँचने के लिए विशेषताएँ कैसे लागू होती हैं? AFAIK, C # में, विशेषताएँ केवल रनटाइम पर उपयोग की जा सकती हैं।
केंडल फ्रे

2

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

if(animal is IDog)
{
}
if(animal.Type == AnimalType.Dog)
{
}
if(animal.GetType().GetCustomAttributes(typeof(DogAttribute), false).Any())
{
}


var dogs1 = animals.OfType<IDog>();
var dogs2 = animals.Where(a => a.Type == AnimalType.Dog);
var dogs3 = animals.Where(a => a.GetType().GetCustomAttributes(typeof(DogAttribute), false).Any());


var dogsFromDb1 = session.Query<IDog>();
var dogsFromDb2 = session.Query<Animal>().Where(a => a.Type == AnimalType.Dog);
var dogsFromDb3 = session.Query<Animal>().Where(a => a.GetType().GetCustomAttributes(typeof(DogAttribute),false).Any());


public void DoSomething(IDog dog)
{
}
public void DoSomething(Animal animal)
{
    if(animal.Type != AnimalType.Dog)
    {
        throw new ArgumentException("This method should be used for dogs only.");
    }
}
public void DoSomething(Animal animal)
{
    if(!animal.GetType().GetCustomAttributes(typeof(DogAttribute), false).Any())
    {
        throw new ArgumentException("This method should be used for dogs only.");
    }
}

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

मेरे पास सिमिलर उपयोग का मामला है, लेकिन अधिकांश .net devs इसके खिलाफ दृढ़ता से सलाह देते हैं, लेकिन मैं विशेषताओं का उपयोग नहीं करने जा रहा हूँ
गोरिल्लाएप

-1

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

उदाहरण के लिए, मान लीजिए कि मेरे पास इंटरफेस है:

इंटरफ़ेस IMaybeMutableFoo {
  बार थिंग {प्राप्त; सेट;} // और अन्य गुण भी
  बूल IsMutable;
  IImmutableFoo AsImmutable ();
}
इंटरफ़ेस IImmutableFoo: IMaybeMutableFoo {};

के कार्यान्वयन से IImmutableFoo.AsImmutable()ही वापस लौटने की उम्मीद की जाएगी; एक उत्परिवर्तनीय वर्ग कार्यान्वयन IMaybeMutableFoo.AsImmutable()से डेटा के स्नैपशॉट युक्त एक नई गहरी-अपरिवर्तनीय वस्तु की वापसी की उम्मीद होगी। एक रूटीन जो IMaybeMutableFooओवरलोड की पेशकश में रखे गए डेटा के स्नैपशॉट को स्टोर करना चाहता है :

सार्वजनिक शून्य StoreData (IImmutableFoo ThingToStore)
{
  // संदर्भ को संग्रहीत करना पर्याप्त होगा, क्योंकि थिंगटॉस्टोर को अपरिवर्तनीय माना जाता है
}
सार्वजनिक शून्य StoreData (IMaybeMutableFoo ThingToStore)
{
  StoreData (ThingToStore.AsImmutable ()); // अधिक विशिष्ट अधिभार को बुलाओ
}

ऐसे मामलों में जहां संकलक को पता नहीं है कि संग्रहित होने वाली चीज एक है IImmutableFoo, यह कॉल करेगा AsImmutable()। यदि आइटम पहले से ही अपरिवर्तनीय है, तो फ़ंक्शन को जल्दी से लौटना चाहिए, लेकिन इंटरफ़ेस के माध्यम से फ़ंक्शन कॉल में अभी भी समय लगता है। यदि कंपाइलर जानता है कि आइटम पहले से ही है IImmutableFoo, तो यह अनावश्यक फ़ंक्शन कॉल को छोड़ सकता है।


Downvoter: टिप्पणी करने के लिए देखभाल? कुछ नया जोड़ने के बिना एक इंटरफ़ेस विरासत में मिला है, लेकिन इसका मतलब यह नहीं है कि यह एक अच्छा (और IMHO underused) तकनीक है।
सुपरकैट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.