ऑब्जेक्ट को एक ही विधि से दो बार पास करें या संयुक्त इंटरफ़ेस के साथ समेकित करें?


15

मेरे पास एक तरीका है जो डिजिटल बोर्ड से बात करने के बाद एक डेटा फ़ाइल बनाता है:

CreateDataFile(IFileAccess boardFileAccess, IMeasurer boardMeasurer)

यहां boardFileAccessऔर boardMeasurerकिसी Boardऑब्जेक्ट का एक ही उदाहरण है जो दोनों को लागू करता है IFileAccessऔर IMeasurerIMeasurerइस मामले में एक एकल विधि के लिए उपयोग किया जाता है जो एक साधारण माप बनाने के लिए सक्रिय बोर्ड पर एक पिन सेट करेगा। इस माप से डेटा का उपयोग करके बोर्ड पर स्थानीय रूप से संग्रहीत किया जाता है IFileAccessBoardएक अलग परियोजना में स्थित है।

मैं इस निष्कर्ष पर पहुंचा हूं कि CreateDataFileत्वरित माप करके एक काम कर रहा है और फिर डेटा को संग्रहीत कर रहा है, और दोनों को एक ही विधि में करना किसी और के लिए इस कोड का उपयोग करने के लिए अधिक सहज है, फिर माप करना और फ़ाइल में लिखना अलग विधि कॉल के रूप में।

मेरे लिए, एक ही वस्तु को एक विधि से दो बार पारित करना अजीब लगता है। मैं एक स्थानीय इंटरफेस बनाने पर विचार किया गया है IDataFileCreatorकि विस्तार होगा IFileAccessऔर IMeasurerऔर उसके बाद एक कार्यान्वयन एक युक्त है Boardउदाहरण है कि बस के लिए आवश्यक फोन करेगा Boardतरीकों। यह देखते हुए कि एक ही बोर्ड ऑब्जेक्ट को हमेशा माप और फ़ाइल लेखन के लिए उपयोग किया जाएगा, क्या एक ही वस्तु को दो बार एक विधि से पास करना एक बुरा अभ्यास है? यदि ऐसा है, तो एक स्थानीय इंटरफ़ेस का उपयोग कर रहा है और एक उपयुक्त समाधान लागू कर रहा है?


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

क्या यह कभी कयास लगाया जा सकता है कि आपकी फ़ाइल एक्सेस ऑब्जेक्ट और आपके सेमेस्टर ऑब्जेक्ट दो अलग-अलग ऑब्जेक्ट हो सकते हैं? मैं हाँ कहूँगा। यदि आप इसे अभी बदलते हैं, तो आपको इसे वापस संस्करण 2 में बदलना होगा जो पूरे नेटवर्क में माप लेने का समर्थन करता है।
user253751

2
हालांकि यहां एक और सवाल है - डेटा फ़ाइल पहुंच और माप ऑब्जेक्ट पहले स्थान पर समान क्यों हैं?
user253751

जवाबों:


40

नहीं, यह पूरी तरह से ठीक है। इसका सीधा सा मतलब है कि एपीआई आपके वर्तमान एप्लिकेशन के संबंध में अधिक इंजीनियर है ।

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


7

@ KilianFoth के जवाब से सहमत हूं कि यह पूरी तरह से ठीक है।

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

public object CreateDataFile<T_BoardInterface>(
             T_BoardInterface boardInterface
    )
    where T_BoardInterface : IFileAccess, IMeasurer
{
    return CreateDataFile(
                boardInterface
            ,   boardInterface
        );
}

कोई सामान्य कारण नहीं है कि तर्कों को अलग-अलग ऑब्जेक्ट्स की आवश्यकता होती है, और यदि किसी विधि को अलग-अलग होने के लिए तर्कों की आवश्यकता होती है, तो यह एक विशेष आवश्यकता होगी जिसका अनुबंध स्पष्ट होना चाहिए।


4

मैं इस निष्कर्ष पर पहुंचा हूं कि CreateDataFileत्वरित माप करके एक काम कर रहा है और फिर डेटा को संग्रहीत कर रहा है, और दोनों को एक ही विधि में करना किसी और के लिए इस कोड का उपयोग करने के लिए अधिक सहज है, फिर माप करना और फ़ाइल में लिखना अलग विधि कॉल के रूप में।

मुझे लगता है कि यह वास्तव में आपकी समस्या है। विधि एक काम नहीं कर रही है। यह दो, अलग-अलग ऑपरेशन कर रहा है जिसमें विभिन्न उपकरणों में I / O शामिल है , दोनों ही यह अन्य वस्तुओं के लिए ऑफ-लोडिंग हैं:

  • एक माप प्राप्त करें
  • उस परिणाम को किसी फ़ाइल में सहेजें

ये दो अलग-अलग I / O ऑपरेशन हैं। विशेष रूप से, पहले वाला किसी भी तरह से फ़ाइल सिस्टम को म्यूट नहीं करता है।

वास्तव में, हमें ध्यान देना चाहिए कि एक निहित मध्य कदम है:

  • एक माप प्राप्त करें
  • एक ज्ञात प्रारूप में माप को क्रमबद्ध करें
  • किसी फ़ाइल में क्रमबद्ध माप सहेजें

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

एक उदाहरण के रूप में, आप इस तरह के संचालन को अलग कर सकते हैं।

IMeasurer माप लाने का एक तरीका है:

public interface IMeasurer
{
    IMeasurement Measure(int someInput);
}

आपका माप प्रकार बस कुछ सरल हो सकता है, जैसे stringया decimal। मैं जोर देकर कह रहा हूं कि आपको इसके लिए एक इंटरफेस या क्लास की जरूरत नहीं है, लेकिन यह यहां के उदाहरण को और सामान्य बनाता है।

IFileAccess फ़ाइलों को सहेजने के लिए कुछ विधि है:

interface IFileAccess
{
    void SaveFile(string fileContents);
}

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

interface IMeasurement
{
    // As part of the type
    string Serialize();
}

// Utility method. Makes more sense if the measurement is not a custom type.
public static string SerializeMeasurement(IMeasurement m)
{
    return ...
}

यह स्पष्ट नहीं है कि आपके पास यह क्रमांकन ऑपरेशन अभी तक अलग है या नहीं।

इस तरह का अलगाव आपके एपीआई को बेहतर बनाता है। यह कॉलर को यह तय करने देता है कि उन्हें क्या और कब की जरूरत है, बजाय इसके कि आपके आई / ओ को प्रदर्शन करने के बारे में आपके पूर्व विचार पर मजबूर किया जाए। कॉलर्स के पास किसी भी वैध ऑपरेशन को करने के लिए नियंत्रण होना चाहिए , चाहे आपको लगता है कि यह उपयोगी है या नहीं।

एक बार जब आप प्रत्येक ऑपरेशन के लिए अलग-अलग कार्यान्वयन करते हैं, तो आपकी CreateDataFileविधि केवल एक शॉर्टहैंड बन जाती है

fileAccess.SaveFile(SerializeMeasurement(measurer.Measure()));

विशेष रूप से, आपके द्वारा यह सब करने के बाद आपका तरीका बहुत कम मूल्य जोड़ता है। कोड की उपरोक्त पंक्ति आपके कॉलर्स को सीधे उपयोग करने के लिए मुश्किल नहीं है, और आपकी विधि विशुद्ध रूप से सुविधा के लिए है। यह होना चाहिए और कुछ वैकल्पिक है । और यह एपीआई के लिए व्यवहार करने का सही तरीका है।


एक बार जब सभी संबंधित भागों को हटा दिया जाता है और हमने स्वीकार कर लिया है कि यह विधि सिर्फ एक सुविधा है, हमें आपके प्रश्न को फिर से लिखना होगा:

आपके कॉल करने वालों के लिए सबसे आम उपयोग मामला क्या होगा?

यदि पूरे बिंदु को एक ही बोर्ड से मापने और लिखने के सामान्य उपयोग के मामले को थोड़ा अधिक सुविधाजनक बनाना है, तो यह Boardसीधे कक्षा पर उपलब्ध कराने के लिए एकदम सही समझ में आता है :

public class Board : IMeasurer, IFileAccess
{
    // Interface methods...

    /// <summary>
    /// Convenience method to measure and immediate record measurement in
    /// default location.
    /// </summary>
    public void ReadAndSaveMeasurement()
    {
        this.SaveFile(SerializeMeasurement(this.Measure()));
    }
}

यदि इससे सुविधा में सुधार नहीं होता है, तो मैं इस पद्धति से बिल्कुल नहीं परेशान होना चाहूंगा।


यह एक सुविधा पद्धति होने के नाते एक अन्य प्रश्न उठाती है।

क्या IFileAccessइंटरफ़ेस को माप प्रकार के बारे में जानना चाहिए और इसे कैसे क्रमबद्ध करना चाहिए? यदि हां, तो आप एक विधि जोड़ सकते हैं IFileAccess:

interface IFileAccess
{
    void SaveFile(string fileContents);
    void SaveMeasurement(IMeasurement m);
}

अब कॉलर बस यही करते हैं:

fileAccess.SaveFile(measurer.Measure());

जो प्रश्न में परिकल्पित होने के रूप में आपकी सुविधा पद्धति से कम और शायद अधिक स्पष्ट है।


2

एक एकल आइटम के पीड़ित होने पर उपभोग करने वाले ग्राहक को एक जोड़ी वस्तुओं से निपटना नहीं चाहिए। आपके मामले में, वे लगभग नहीं हैं, जब तक कि मंगलाचरण नहीं है CreateDataFile

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

हालांकि, एक और दृष्टिकोण जो कार्यान्वयन के लिए कम / विवश है, वह IFileAccessयह है कि इसे किसी IMeasurerरचना के साथ जोड़ा जाता है , ताकि उनमें से एक दूसरे से जुड़ा हो और संदर्भित हो। (यह कुछ हद तक उनमें से एक के अमूर्तता को बढ़ाता है क्योंकि यह अब युग्म के रूप में अच्छी तरह से प्रतिनिधित्व करता है।) फिर CreateDataFileसंदर्भों में से केवल एक को ले सकता है, कह सकता है IFileAccessऔर फिर भी दूसरे को आवश्यकतानुसार प्राप्त कर सकता है। एक वस्तु के रूप में आपका वर्तमान कार्यान्वयन कि औजार दोनों इंटरफेस होगा बस return this;रचना संदर्भ के लिए, यहाँ के लिए गेटर IMeasurerमें IFileAccess

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


एक और नोट पर, मैं पूछ सकता हूं कि कौन मालिक है CreateDataFile, और सवाल यह है कि यह तीसरा पक्ष कौन है। हम पहले से ही कुछ लेने वाली ग्राहक है आह्वान CreateDataFile, मालिक वस्तु / के वर्ग CreateDataFile, और IFileAccessऔर IMeasurer। कभी-कभी जब हम संदर्भ का एक बड़ा दृष्टिकोण लेते हैं, तो कभी-कभी बेहतर, संगठन दिखाई दे सकते हैं। प्रसंग अधूरा होने के कारण यहाँ करना कठिन है, इसलिए केवल विचार के लिए भोजन करें।


0

कुछ ने लाया है कि CreateDataFileबहुत ज्यादा कर रहा है। मैं सुझाव दे सकता हूं कि इसके बजाय Boardबहुत अधिक कर रहा है, क्योंकि किसी फ़ाइल तक पहुंचना बाकी बोर्ड से अलग चिंता की तरह लगता है।

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

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

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


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