क्या प्रोग्रामिंग कन्वेंशन में संगतता को बढ़ावा दिया जाना चाहिए?


14

क्लास डिजाइन करते समय व्यवहार में स्थिरता को सामान्य प्रोग्रामिंग अभ्यास के अनुकूल होना चाहिए? एक विशिष्ट उदाहरण देने के लिए:

एक सामान्य सम्मेलन यह है: यदि कोई वर्ग किसी वस्तु का मालिक है (जैसे उसने इसे बनाया है) तो यह एक बार पूरा होने के बाद इसे साफ करने के लिए जिम्मेदार है। एक विशिष्ट उदाहरण .NET में होगा कि यदि आपका वर्ग किसी IDisposableवस्तु का मालिक है तो उसे अपने जीवन के अंत में इसका निपटान करना चाहिए। और अगर आप इसके मालिक नहीं हैं तो इसे मत छुइए।

अब अगर हम StreamWriter.NET में क्लास को देखते हैं तो हम डॉक्यूमेंट में पा सकते हैं कि यह अंतर्निहित स्ट्रीम को बंद कर देता है जब इसे बंद / डिस्पोज किया जा रहा है। यह उन मामलों में आवश्यक है जहां StreamWriterफ़ाइल नाम में पास करके त्वरित किया जाता है क्योंकि लेखक अंतर्निहित फ़ाइल स्ट्रीम बनाता है और इसलिए इसे बंद करने की आवश्यकता है। हालाँकि एक बाहरी धारा में भी गुजर सकता है जिसे लेखक भी बंद कर देता है।

इसने मुझे कई बार परेशान किया है (हाँ मुझे पता है कि आप एक नॉन-क्लोजिंग रैपर बना सकते हैं, लेकिन यह बात नहीं है) लेकिन जाहिर है कि माइक्रोसॉफ्ट ने यह निर्णय लिया है कि यह हमेशा स्ट्रीम को बंद करने के लिए अधिक सुसंगत है, जहां से यह आया है।

जब मैं अपनी एक कक्षा में इस तरह के पैटर्न पर आ ownsFooBarजाता हूं, तो मैं आमतौर पर एक ध्वज बनाता हूं जो उन मामलों में झूठे हो जाता है जहां FooBarनिर्माणकर्ता के माध्यम से इंजेक्शन लगाया जाता है और अन्यथा सच है। इस तरह इसे साफ करने की जिम्मेदारी कॉल करने वाले को दी जाती है, जब वह स्पष्ट रूप से उदाहरण को पास करता है।

अब मैं सोच रहा हूँ कि क्या हो सकता है कि संगति सर्वोत्तम अभ्यास के पक्ष में हो (या शायद मेरा सबसे अच्छा अभ्यास उतना अच्छा नहीं है)? इसके लिए कोई तर्क / विरोध?

स्पष्टीकरण के लिए संपादित करें

"सुसंगतता" से मेरा मतलब है: वर्ग का सुसंगत व्यवहार हमेशा स्वामित्व लेना (और धारा को बंद करना) बनाम "सर्वोत्तम अभ्यास" केवल किसी वस्तु का स्वामित्व लेने के लिए यदि आपने इसे बनाया है या स्वामित्व को स्पष्ट रूप से स्थानांतरित किया है।

एक उदाहरण के लिए जहां यह लागू हो रहा है:

मान लें कि आपके पास दो दी गई कक्षाएं हैं (कुछ 3 पार्टी लाइब्रेरी से) जो इसके साथ कुछ करने के लिए एक स्ट्रीम स्वीकार करते हैं, जैसे कुछ डेटा बनाना और संसाधित करना:

 public class DataProcessor
 {
     public Result ProcessData(Stream input)
     {
          using (var reader = new StreamReader(input))
          {
              ...
          }
     }
 }

 public class DataSource
 {
     public void GetData(Stream output)
     {
          using (var writer = new StreamWriter(output))
          {
               ....
          }
     }
 }

अब मैं इसे इस तरह उपयोग करना चाहता हूं:

 Result ProcessSomething(DataSource source)
 {
      var processor = new DataProcessor();
      ...
      var ms = new MemoryStream();
      source.GetData(ms);
      return processor.ProcessData(ms);
 }

यह Cannot access a closed streamडेटा प्रोसेसर में एक अपवाद के साथ विफल हो जाएगा । यह थोड़ा सा निर्मित है लेकिन इस बिंदु को स्पष्ट करना चाहिए। इसे ठीक करने के विभिन्न तरीके हैं लेकिन फिर भी मुझे लगता है कि मुझे कुछ ऐसा काम करना चाहिए जो मुझे नहीं करना चाहिए।


क्या आप को ध्यान में रखना होगा कि क्यों सचित्र व्यवहार से आपको दर्द होता है? क्या आप उसी धारा का अन्यत्र उपभोग करना चाहेंगे? क्यों?
जॉब

@ जोब: मैंने अपना प्रश्न स्पष्ट किया है
क्रिसवे

जवाबों:


9

मैं इस तकनीक का भी उपयोग करता हूं, मैं इसे 'हैंडऑफ' कहता हूं, और मेरा मानना ​​है कि यह एक पैटर्न की स्थिति के योग्य है। जब कोई वस्तु निर्माण समय पैरामीटर के रूप में एक डिस्पोजेबल ऑब्जेक्ट बी को स्वीकार करती है, तो वह 'हैंडऑफ' नामक एक बूलियन को भी स्वीकार करती है, (जो गलत को परिभाषित करता है) और अगर यह सच है, तो ए कैस्केड का निपटान बी के निपटान के लिए।

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


नोट: मैंने अपने ब्लॉग पर एक पोस्ट में इस पैटर्न की औपचारिक परिभाषा लिखी है: michael.gr: "हैंडऑफ़" पैटर्न
माइक नाइस

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

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

एक ही आइटम को फिर से आपूर्ति करना आम तौर पर अवैध होना चाहिए जब तक कि वस्तु अपरिवर्तनीय नहीं होती है, वास्तव में किसी भी संसाधन को नहीं रखती है, और अगर यह निपटाया जाता है तो परवाह नहीं करता है। उदाहरण के लिए, यदि Disposeसिस्टम ब्रश के लिए अनुरोधों को अनदेखा किया गया था , तो एक "color.CreateBrush 'विधि अपने अवकाश पर हो सकती है या तो एक नया ब्रश बना सकती है (जिसे निपटान की आवश्यकता होगी) या सिस्टम ब्रश (जो निपटान को अनदेखा करेगा) को वापस करने के लिए सबसे सरल तरीका है। एक वस्तु का पुन: उपयोग अगर यह निपटान के बारे में परवाह है, लेकिन पुन: उपयोग की अनुमति दें यदि यह नहीं है, तो इसे निपटाना है।
सुपरकैट

3

मुझे लगता है कि तुम सही हो, ईमानदार हो। मुझे लगता है कि Microsoft ने स्ट्रीमवर्टर वर्ग के साथ गड़बड़ की, विशेष रूप से, आपके द्वारा वर्णित कारणों के लिए।

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


2

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

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

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


मैंने अपने प्रश्न को स्पष्ट किया - स्थिरता के साथ मेरा मतलब हमेशा स्वामित्व लेने के व्यवहार से था।
क्रिसवे

2

सावधान रहे। आप "स्थिरता" के रूप में जो सोचते हैं वह सिर्फ आदतों का एक यादृच्छिक संग्रह हो सकता है।

"सुसंगतता के लिए उपयोगकर्ता इंटरफेस का समन्वय", SIGCHI बुलेटिन 20, (1989), 63-65। क्षमा करें, कोई लिंक नहीं है, यह एक पुराना लेख है। "... 15 विशेषज्ञों की दो-दिवसीय कार्यशाला स्थिरता की परिभाषा का उत्पादन करने में असमर्थ थी।" हां, यह "इंटरफ़ेस" के बारे में है, लेकिन मेरा मानना ​​है कि यदि आप थोड़ी देर के लिए "स्थिरता" के बारे में सोचते हैं, तो आप पाएंगे कि आप इसे परिभाषित नहीं कर सकते हैं, या तो।


आप सही हैं, यदि विशेषज्ञ अलग-अलग मंडलियों से एक साथ आते हैं, लेकिन कोड विकसित करते समय, मुझे कुछ मौजूदा पैटर्न (या यदि आप चाहें तो आदत) का पालन करना आसान लगा, जो मेरी टीम पहले से ही परिचित है। उदाहरण के लिए, हमारे दूसरे दिन का एक व्यक्ति हमारे पास मौजूद कुछ अतुल्यकालिक ऑपरेशनों के बारे में पूछताछ कर रहा था और जब मैंने उसे बताया कि वे Win32 ओवरलैप्ड I / O के समान व्यवहार करते हैं, तो 30 सेकंड में उसने पूरे इंटरफ़ेस को समझा ... इस मामले में दोनों खुद और वह एक ही सर्वर बैक एंड Win32 बैकग्राउंड से आए थे। संगति फूटी! :)
DXM

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