2013-08-09 9 views
8

मेरे पास एक कोड है जो एक इनपुट के रूप में एक द्विपक्षीय ग्राफ लेता है और "1" में मूल्य के साथ एक नक्शा देता है जो "सेट 1 में नोड्स" और कुंजी "2" की सूची है जिसका मान "सेट 2 में नोड्स" की सूची है । अब, मानचित्र mutable है। सिद्धांत में मुझे मानचित्र लौटने के लिए रक्षात्मक प्रति का उपयोग करना चाहिए। लेकिन, इस मामले में यह वास्तव में आवश्यक है? यह एक ओवरकिल दिखाई देता है।क्या रक्षात्मक प्रतियां हमेशा की जानी चाहिए?

पूर्व:

class BiPartite { 

    Graph graph; 
    Map bipartite 

    Bipartite(graph) { 
     this.graph = graph; 
    } 

    void calcBipartite() { 
    // calculate map 
    } 

    Map getMap() { 
    // should i make defensive copy ? Appears overkill. 
    } 
} 
+0

यदि आप जिस मूल्य को वापस कर रहे हैं वह एक व्युत्पन्न जानकारी है जिसे फ्लाई पर गणना की जाती है, तो रक्षात्मक प्रतियां बनाने की कोई आवश्यकता नहीं है। क्या आप हर बार विधि कहने पर GetMap के वापसी मूल्य की गणना कर रहे हैं? – HariKrishnan

+4

चेतावनी दीजिये कि कॉलर के पास पहले से ही इस ऑब्जेक्ट के आंतरिक मानों तक बाहरी पहुंच है क्योंकि आप 'ग्राफ़' की प्रतिलिपि नहीं बनाते हैं, मानते हैं कि' ग्राफ़ 'उत्परिवर्तनीय है। – jpmc26

उत्तर

6

यह निर्भर करता है :)

  • आप अपने वर्ग के हिसाब से दस्तावेज़ कर सकते हैं, यह निर्दिष्ट है कि लौटे मानचित्र द्विपक्षीय वस्तु की परिवर्तनशील राज्य पर एक परिवर्तनशील प्रत्यक्ष दृश्य है। हालांकि मैं इसकी सिफारिश नहीं करता।
  • आप Collections.unmodifiableMap(map)getMap()और दस्तावेज़ में आंतरिक मानचित्र को लपेट सकते हैं जो यह बायपार्टाइट ऑब्जेक्ट के उत्परिवर्तनीय स्थिति को दर्शाता है। यह तब तक एक वैध दृष्टिकोण हो सकता है जब तक कि बायपार्टाइट ऑब्जेक्ट थ्रेडसेफ नहीं माना जाता है। यदि ग्राहक लौटा मानचित्र को स्थिर स्नैफॉट के रूप में रखना चाहता है, तो वह इसे स्वयं कॉपी कर सकती है। यदि इसकी आवश्यकता नहीं है, तो वह फास्ट रैपिंग ऑपरेशन से लाभ उठा सकती है।
  • आप हमेशा एक पूर्ण प्रतिलिपि वापस कर सकते हैं। यदि आप वास्तव में BiPartite ऑब्जेक्ट थ्रेडसेफ बनाते हैं तो इससे अधिक समझदारी होगी। उस स्थिति में आपको आंतरिक मानचित्र के सभी परिचालनों को भी सिंक्रनाइज़ करना होगा (नक्शा प्रतिलिपि संचालन सहित!)।

मूल रूप से यह नीचे उबलता है: इस बारे में सोचें कि बायपार्टाइट वर्ग और इसकी विधियों का उपयोग कैसे किया जाना चाहिए, इसके लिए उपयुक्त कार्यान्वयन चुनें और कक्षा के व्यवहार और इसके पीछे तर्क दोनों को स्पष्ट रूप से दस्तावेज करें।

1

हाँ तुम, क्योंकि अन्यथा ग्राहक अपने वर्ग की निजी क्षेत्र अपने वर्ग को गलत तरीके से व्यवहार करते हैं बनाने को बदल सकते हैं चाहिए।

1

यह आपके कोड के सम्मेलनों पर निर्भर करता है। मैं जो कुछ भी रखना चाहता हूं उसे कॉपी करने के एक सम्मेलन का पालन करता हूं। यानी यह कॉलर्स जिम्मेदारी है।

यह अधिक कुशल है, लेकिन अगर आप नहीं जानते कि कॉलर इस सम्मेलन का पालन करेगा तो मजबूत नहीं है।

5

हां, आपको एक रक्षात्मक प्रति वापस करनी चाहिए।

return Collections.unmodifiableMap(bipartite); 
+0

हां, यही मेरा मतलब था। – Joni

+0

कृपया ध्यान दें कि 'संग्रह .unmodifiableMap() 'एक प्रतिलिपि नहीं है - सभी लेखन कार्यों के साथ केवल एक दृश्य अक्षम है। (मूल) उत्तर पढ़ना दोनों को भ्रमित करना आसान है। – creinig

+1

मेरी राय में, एक प्रतिलिपि दृश्य एक प्रति से बेहतर विकल्प है। यह कॉलर के हाथों में प्रदर्शन विचारों को छोड़ देता है; वे यह तय कर सकते हैं कि उन्हें प्रतिलिपि बनाने और उस समय की जगह बनाने की आवश्यकता है जो प्रतिलिपि लागत बनाते हैं। यदि नहीं, तो वे अनिवार्य रूप से एक सस्ती प्रति है। – jpmc26

2

शब्द "हमेशा" जब पैटर्न और अच्छा प्रोग्रामिंग प्रथाओं समझा शायद ही कभी उचित है: आप संसाधनों के उपयोग के बारे में चिंतित हैं, तो आप एक नक्शा अपने निजी नक्शे का एक unmodifiable दृष्टिकोण यह है कि लौट सकते हैं। यह सब संदर्भ पर निर्भर करता है।

आपके मामले में BiPartite#getMap विधि, और कक्षा स्वयं, "पैकेज निजी" हैं इसलिए ग्राहक (आपके कोड के उपयोगकर्ता) सीधे इसका उपयोग करने में सक्षम नहीं होंगे। यदि आप जानते हैं कि आपने उस पैकेज की सीमाओं के बाहर उस मानचित्र को कभी भी स्टोर या वापस नहीं किया है तो यह कहना सुरक्षित है कि आपको रक्षात्मक प्रतिलिपि बनाने की आवश्यकता नहीं है।

0

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

यदि आप अपने कोड के मिस्बेहेविंग क्लाइंट से बचाना चाहते हैं तो आपको केवल विधि calcBipartite() को बेनकाब करना चाहिए और इसे एक नए गणना वाले मानचित्र को वापस करने देना चाहिए। क्लाइंट जो विधि का उपयोग करता है, यह तय करना है कि बनाई गई वस्तु का उपयोग कैसे किया जाता है और कितनी बार calcBipartite() कहा जाता है।

यदि आप अपने कोड का एकमात्र ग्राहक हैं तो आपको न तो प्रतिलिपि बनाना चाहिए और न ही लपेटना चाहिए।

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