2012-10-05 19 views
5

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

चर में नाम भंडारण:

foo(Bar bar){ 
    String name = bar.getName(); 
    logger.info("I am working with "+name); 
    this.doSomethingWith(name); 
} 

) या getName (बुला दो बार:

foo(Bar bar){ 
    logger.info("I am working with "+bar.getName()); 
    this.doSomethingWith(bar.getName()); 
} 

मैं समझता हूँ, कि पहले परिदृश्य में, मैं एक नया स्ट्रिंग पैदा करेगा, एक मूल्य निर्दिष्ट इसके लिए और फिर इस मान को दो बार पुनः प्राप्त करें। इस तरह मैं अधिक मेमोरी संसाधनों का उपयोग कर रहा हूं, सही?

दूसरे परिदृश्य में, क्या मैं ऑब्जेक्ट बार को दो बार एक्सेस कर रहा हूं और फिर इसे दो बार एक्सेस कर रहा हूं। मुझे लगता है कि यह एक ड्रवाई दृष्टिकोण नहीं है। लेकिन दूसरी तरफ मैं स्मृति में खुद को दोहराना नहीं कर रहा हूं, सही?

कौन सा दृष्टिकोण बेहतर है?

+0

पहली विधि में आप _not_ एक नई स्ट्रिंग बना रहे हैं। तो दोनों विधियों को एक ही स्मृति खपत के साथ खत्म होना चाहिए। – Fildor

+0

यह देखने के लिए कि क्या आपकी समस्या वास्तव में एक मुद्दा है, एक डीकंपेलर के साथ जेनरेट बाइट कोड की जांच करना उचित हो सकता है; 'जावैक' इस उपयोग के मामले को पहचान सकता है और इसे किसी एक तरीके से अनुकूलित कर सकता है या कोई फर्क नहीं पड़ता कि आप जावा में इसे किस तरह लिखते हैं। – akaIDIOT

उत्तर

1

व्यक्तिगत रूप से, मैं दूसरा दृष्टिकोण पसंद करता हूं। वास्तव में, जब भी आवश्यक हो, मैं आमतौर पर अस्थायी चर बना देता हूं।

मार्टिन फाउलर (http://en.wikipedia.org/wiki/Martin_Fowler) भी इस दिशानिर्देश का पालन करता है। उन्होंने अपनी पुस्तक के भीतर संबंधित है कि मैं पढ़ा है:

http://www.amazon.fr/Refactoring-Improving-Design-Existing-Code/dp/0201485672

अपनी पुस्तक में इस विषय के विषय में एक नि: शुल्क उद्धरण यहाँ है:

http://sourcemaking.com/refactoring/replace-temp-with-query

कुछ लोगों को अस्थायी चर को हटाने के लोगों का तर्क था सकता है प्रदर्शन मुद्दे का नेतृत्व करें।

के रूप में मार्टिन Fowler का कहना है:

आप इस मामले में प्रदर्शन के बारे में चिंतित हो सकता है। अन्य प्रदर्शन समस्याओं के साथ, इस पल के लिए स्लाइड करें। दस में से नौ बार, इससे कोई फर्क नहीं पड़ता। जब कोई फर्क पड़ता है, तो आप ऑप्टिमाइज़ेशन के दौरान समस्या को ठीक कर देंगे।आपके कोड को बेहतर ढंग से फैक्टर करने के साथ, आप अक्सर अधिक शक्तिशाली अनुकूलन ढूंढेंगे, जिन्हें आप रीफैक्टरिंग के बिना चूक गए होंगे। यदि बदतर खराब हो जाता है, तो अस्थायी वापस रखना बहुत आसान है।

लेकिन वैसे भी, यह स्वाद का विषय है। कुछ लोग पहले दृष्टिकोण को और अधिक पठनीय पाते हैं, दूसरे दूसरे। मैं वास्तव में दूसरा पसंद करता हूं क्योंकि मुझे अस्थायी चर से कोई वास्तविक मूल्यों के लिए लाइन जोड़ने से नफरत है :)

+0

यह मार्टिन फाउलर दृष्टिकोण ... अद्भुत है! – user1581900

+0

@ user1581900 आपको अपनी पुस्तक पढ़नी चाहिए, मुझे यह पसंद आया :) रॉबर्ट सी मार्टिन को "क्लीन कोड" पुस्तक के लिए भी देखें :) – Mik378

1

आपका Bar अपरिवर्तनीय वर्ग (अधिकांश मामलों के लिए) होना चाहिए। अपरिवर्तनीय कक्षा के लिए ये दृष्टिकोण समान हैं, इसलिए आप जो भी चाहें चुनते हैं।

कोई वास्तविक समस्या तब होगी जब Bar उत्परिवर्तनीय है, इसलिए bar.name का मान 2 रीड के बीच बदल सकता है। लेकिन यह मामला डोमेन ऑब्जेक्ट (जो ऐसा प्रतीत होता है) के रूप में Bar का उपयोग कर प्रस्तुत करेगा। आप foo() के शीर्ष पर bar की स्थानीय प्रति बनाकर ऐसे मामलों के आसपास काम कर सकते हैं। फिर, फिर, एक बार जब आपके पास मूल bar की स्थानीय प्रतिलिपि हो, तो आप जिस भी तरीके से अधिक पसंद कर सकते हैं उसे चुन सकते हैं।

तो, यह स्वाद का विषय है। हां, आप पहले मामले में स्थानीय संदर्भ के लिए स्मृति की एक छोटी सी बिट बर्बाद कर सकते हैं, लेकिन संभवतः, JVM इसे बाइट-कोड स्तर पर दूसरे तरीके की तरह बनाने के लिए अनुकूलित करेगा।

3

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

बाद वाले विकल्प में थ्रेड सुरक्षा के कुछ मुद्दे भी हैं जहां getName() का परिणाम आमंत्रण के बीच बदल सकता है। यद्यपि संभवतः असंभव है, यह ऐसा कुछ है जिसे आप ध्यान में रखना चाहते हैं।

इस बात को ध्यान में रखते हुए, मैं पहले विकल्प की सिफारिश करता हूं, भले ही यह अधिक "बात करने वाला" हो।

नोट: यह भी संभव है कि getName() गणना द्वारा उत्पन्न किया गया है, इस मामले में आप वास्तव में पहले की तुलना में अधिक स्मृति का उपयोग करके दूसरी विधि के साथ समाप्त हो जाएंगे।

+0

तो पहले परिदृश्य में स्ट्रिंग नाम और bar.getName() स्मृति में समान स्ट्रिंग को इंगित करता है। अगर मैं bar.name बदलता हूं, तो मैं वास्तव में इसे बदल नहीं रहा हूं, लेकिन इसे किसी अन्य स्ट्रिंग पर इंगित करता हूं, जबकि स्ट्रिंग नाम अभी भी पुराने मान को इंगित करेगा? – user1581900

+1

यह सही है। यही कारण है कि java.lang.String में सभी विधियों को उस ऑब्जेक्ट को संशोधित करने के बजाय एक नया स्ट्रिंग लौटाता है जिसे वे बुलाया जा रहा है। –

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

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