क्लास और इंटरफ़ेस फ़ाइलों को व्यवस्थित करने के लिए सबसे अच्छा कैसे?


17

ठीक है .. सभी चर्चा के बाद मैं अपने प्रश्न को थोड़ा बेहतर तरीके से बदल रहा हूं ताकि मैं एक ठोस उदाहरण को प्रतिबिंबित कर सकूं।


मेरे पास दो कक्षाएं हैं ModelOneऔर ModelTwo, ये कक्षाएं समान प्रकार की कार्यक्षमता का प्रदर्शन करती हैं, लेकिन एक दूसरे से असंबंधित हैं। हालाँकि मेरे पास एक तीसरा वर्ग CommonFuncहै जिसमें कुछ सार्वजनिक कार्यक्षमता शामिल है जो कि दोनों में लागू की गई है ModelOneऔर ModelTwoप्रति के रूप में फैली हुई है DRY। दो मॉडलों को ModelMainकक्षा के भीतर त्वरित किया जाता है (जो स्वयं उच्च स्तर पर त्वरित होता है - लेकिन मैं इस स्तर पर रोक रहा हूं)।

IoC कंटेनर जो मैं उपयोग कर रहा हूं वह Microsoft एकता है । मैं इसमें एक विशेषज्ञ होने का दिखावा नहीं करता, लेकिन मेरी यह समझ है कि आप कंटेनर के साथ इंटरफ़ेस और क्लास का टपल रजिस्टर करते हैं और जब आप एक ठोस वर्ग चाहते हैं तो आप IoC कंटेनर से पूछते हैं कि जो वस्तु किसी विशिष्ट इंटरफ़ेस से मेल खाती है। इसका तात्पर्य यह है कि हर उस वस्तु के लिए जिसे मैं यूनिटी से इंस्टेंट करना चाहता हूं, एक मिलान इंटरफ़ेस होना चाहिए। क्योंकि मेरी प्रत्येक कक्षा अलग (और गैर-अतिव्यापी) कार्यक्षमता करती है, इसका अर्थ है कि इंटरफ़ेस और कक्षा 1 के बीच 1: 1 का अनुपात है । हालाँकि इसका मतलब यह नहीं है कि मैं अपने लिखे हुए प्रत्येक वर्ग के लिए एक इंटरफ़ेस लिख रहा हूँ।

इस प्रकार कोड वार मैं 2 के साथ समाप्त होता है :

public interface ICommonFunc 
{ 
}

public interface IModelOne 
{ 
   ICommonFunc Common { get; } 
   .. 
}

public interface IModelTwo
{ 
   ICommonFunc Common { get; } 
   .. 
}

public interface IModelMain 
{ 
  IModelOne One { get; } 
  IModelTwo Two { get; } 
  ..
}

public class CommonFunc : ICommonFunc { .. }

public class ModelOne : IModelOne { .. }

public class ModelTwo : IModelTwo { .. }

public class ModelMain : IModelMain { .. }

सवाल यह है कि मेरे समाधान को कैसे व्यवस्थित किया जाए। क्या मुझे क्लास और इंटरफ़ेस को एक साथ रखना चाहिए? या मुझे कक्षाओं और इंटरफेस को एक साथ रखना चाहिए? ईजी:

विकल्प 1 - वर्ग नाम से संगठित

MySolution
  |
  |-MyProject
  |   |
      |-Models
      |   |
          |-Common
          |   |
          |   |-CommonFunc.cs
          |   |-ICommonFunc.cs
          |
          |-Main
          |   |
          |   |-IModelMain.cs
          |   |-ModelMain.cs
          |
          |-One
          |   |
          |   |-IModelOne.cs
          |   |-ModelOne.cs
          |
          |-Two
              |
              |-IModelTwo.cs
              |-ModelTwo.cs
              |

विकल्प 2 - कार्यक्षमता द्वारा व्यवस्थित (अधिकतर)

MySolution
  |
  |-MyProject
  |   |
      |-Models
      |   |
          |-Common
          |   |
          |   |-CommonFunc.cs
          |   |-ICommonFunc.cs
          |
          |-IModelMain.cs
          |-IModelOne.cs
          |-IModelTwo.cs
          |-ModelMain.cs
          |-ModelOne.cs
          |-ModelTwo.cs
          |

विकल्प 3 - अलग करने वाला इंटरफ़ेस और कार्यान्वयन

MySolution
  |
  |-MyProject
      |
      |-Interfaces
      |   |
      |   |-Models
      |   |   |
      |       |-Common
      |       |   |-ICommonFunc.cs
      |       |
      |       |-IModelMain.cs
      |       |-IModelOne.cs
      |       |-IModelTwo.cs
      |
      |-Classes
          | 
          |-Models
          |   |
              |-Common
              |   |-CommonFunc.cs
              |
              |-ModelMain.cs
              |-ModelOne.cs
              |-ModelTwo.cs
              |

विकल्प 4 - कार्यक्षमता के उदाहरण को और आगे ले जाना

MySolution
  |
  |-MyProject
  |   |
      |-Models
      |   |
          |-Components
          |   |
          |   |-Common
          |   |   |
          |   |   |-CommonFunc.cs
          |   |   |-ICommonFunc.cs
          |   |   
          |   |-IModelOne.cs
          |   |-IModelTwo.cs
          |   |-ModelOne.cs
          |   |-ModelTwo.cs
          |
          |-IModelMain.cs
          |-ModelMain.cs
          |

पथ में वर्ग नाम के कारण मुझे नापसंद विकल्प 1 पसंद है। लेकिन जैसा कि मैं अपने IoC पसंद / उपयोग (और यह बहस का विषय हो सकता है) की वजह से 1: 1 के अनुपात में चल रहा है, इससे फाइलों के बीच संबंध देखने में फायदे हैं।

विकल्प 2 मुझे अपील कर रहा है, लेकिन अब मैंने ModelMainऔर उप-मॉडल के बीच पानी को पिघला दिया है ।

विकल्प 3 कार्यान्वयन से इंटरफ़ेस परिभाषा को अलग करने के लिए काम करता है, लेकिन अब मेरे पास पथ नामों में ये कृत्रिम ब्रेक हैं।

विकल्प 4. मैंने विकल्प 2 लिया और मूल मॉडल से घटकों को अलग करने के लिए इसे ट्विक किया।

क्या एक को दूसरे पर तरजीह देने का अच्छा कारण है? या कोई अन्य संभावित लेआउट जो मैंने याद किया है?


1. फ्रैंक ने टिप्पणी की कि 1: 1 अनुपात में .h और .cpp फ़ाइलों के C ++ दिनों में वापस आ जाता है। मुझे पता है कि वह कहां से आ रहा है। एकता की मेरी समझ मुझे इस कोने में डालती है, लेकिन मुझे यह भी निश्चित नहीं है कि अगर आप भी Program to an interface एक और दिन के लिए चर्चा करते हैं, तो आप भी इससे बाहर निकल सकते हैं ।

2. मैंने प्रत्येक ऑब्जेक्ट के निर्माता का विवरण छोड़ दिया है। यह वह जगह है जहां IoC कंटेनर आवश्यकतानुसार वस्तुओं को इंजेक्ट करता है।


1
ओह। यह खुशबू आ रही है कि आपके पास 1: 1 इंटरफ़ेस / वर्ग अनुपात है। आप कौन से IoC कंटेनर का उपयोग कर रहे हैं? Ninject तंत्र प्रदान करता है जिसके लिए 1: 1 अनुपात की आवश्यकता नहीं होती है।
रबरडक

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

क्या आपको IBase की आवश्यकता है या आधार सार हो सकता है? जब यह पहले से ही IBase को लागू करता है तो IDerivedOne क्यों है? आपको IBase पर निर्भर होना चाहिए, व्युत्पन्न नहीं। मैं एकता के बारे में नहीं जानता, लेकिन अन्य आईओसी कंटेनर आपको "संदर्भ संवेदनशील" इंजेक्शन करने की अनुमति देते हैं। मूल रूप से जब Client1एक की जरूरत है IBase, यह एक प्रदान करता है Derived1। जब Client2एक की आवश्यकता होती है IBase, तो IoC एक प्रदान करता है Derived2
रबरडक

1
खैर, अगर आधार सार है, तो इसके लिए कोई कारण नहीं interfaceहै। एक interfaceवास्तव में सब आभासी सदस्यों के साथ सिर्फ एक अमूर्त वर्ग है।
रबरडक

1
रबरडक सही है। सतही इंटरफेस बस कष्टप्रद हैं।
फ्रैंक हिलमैन

जवाबों:


4

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

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

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


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

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

मैं VS का उपयोग कर रहा हूं। और हाँ मैं दर्द जानता हूँ। यह दृश्य स्रोत सुरक्षित फ़ाइल लेआउट की यादें वापस लाता है।
पीटर एम

1
@PeterM वर्ग अनुपात के लिए 1: 1 इंटरफ़ेस के संबंध में। कुछ टूल के लिए इसकी आवश्यकता होती है। मैं इसे उपकरण के दोष के रूप में देखता हूं - .net में किसी भी उपकरण में इस तरह के प्रतिबंधों की आवश्यकता नहीं होने के लिए पर्याप्त प्रतिबिंब क्षमता है।
फ्रैंक हिलमैन जूल

1

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

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


मैंने अपना कोड उदाहरण संशोधित किया है और
पीटर एम

1

हमेशा किसी भी डिजाइन प्रश्न के साथ, पहली बात यह निर्धारित करना है कि आपके उपयोगकर्ता कौन हैं। वे आपके संगठन का उपयोग कैसे करेंगे?

क्या वे कोडर हैं जो आपकी कक्षाओं का उपयोग करेंगे? फिर कोड से इंटरफेस को अलग करना सबसे अच्छा हो सकता है।

क्या वे आपके कोड के अनुरक्षक हैं? फिर इंटरफेस और कक्षाएं एक साथ रखें सबसे अच्छा हो सकता है।

बैठकर कुछ उपयोग-मामले बनाएं। तब सबसे अच्छा संगठन आपके सामने आ सकता है।


-2

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

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