प्रतिबिंब के साथ जेनेरिक सेटर और गेट्टर बनाना एक बुरा विचार क्यों है?


49

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

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


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

2
आप कैसे इन गेटर्स का उपभोग करेंगे और जावा जैसी स्थिर भाषा में बसेंगे? यह मुझे नॉन-स्टार्टर की तरह लगता है।
एबेन स्कोव पेडरसन

@EsbenSkovPedersen आप उन्हें ज्यादा एक तरह का उपभोग होता Mapहै getऔर putहै, जो काम करने के एक बहुत भद्दा तरीका है।
7

2
IIRC, लोम्बोक संकलित समय पर गेटर्स / सेटर को संश्लेषित करता है, जैसा कि उपयुक्त एनोटेशन द्वारा निर्धारित किया गया है, इसलिए वे: प्रतिबिंब के प्रदर्शन का जुर्माना नहीं करते हैं, सांख्यिकीय रूप से विश्लेषण किया जा सकता है / इनलेट किया जा सकता है, (IntelliJ के पास लोम्बोक के लिए एक प्लगइन है)
अलेक्जेंडर

जवाबों:


117

सामान्य रूप में प्रतिबिंब के चढ़ाव

परावर्तन को स्ट्रेट-लाइन कोड की तुलना में समझना कठिन है।

मेरे अनुभव में, प्रतिबिंब जावा में एक "विशेषज्ञ-स्तरीय" विशेषता है। मेरा तर्क है कि अधिकांश प्रोग्रामर कभी भी प्रतिबिंब का सक्रिय रूप से उपयोग नहीं करते हैं (अर्थात परावर्तन का उपयोग करने वाले पुस्तकालयों की गिनती नहीं होती है)। यह इन प्रोग्रामरों के लिए समझने के लिए कठिन कोड का उपयोग करता है।

परावर्तन कोड स्थिर विश्लेषण के लिए दुर्गम है

मान लीजिए कि getFooमेरी कक्षा में एक गटर है और मैं इसका नाम बदलना चाहता हूं getBar। अगर मैं बिना किसी प्रतिबिंब का उपयोग करता हूं, तो मैं कोड बेस को केवल खोज सकता हूं getFooऔर हर स्थान को ढूंढूंगा जो कि गेट्टर का उपयोग करता है इसलिए मैं इसे अपडेट कर सकता हूं, और यहां तक ​​कि अगर मुझे एक भी याद आती है, तो कंपाइलर शिकायत करेगा।

लेकिन अगर वह जगह जो गटर का उपयोग करती है, कुछ है callGetter("Foo")और callGetterकरती है getClass().getMethod("get"+name).invoke(this), तो उपरोक्त विधि इसे नहीं ढूंढेगी, और कंपाइलर शिकायत नहीं करेगा। केवल जब कोड वास्तव में क्रियान्वित किया जाता है यदि आप एक मिल जाएगा NoSuchMethodException। और उस दर्द की कल्पना करें, यदि आप उस अपवाद (जिसे ट्रैक किया गया है) को निगल जाते हैं callGetterक्योंकि "इसका उपयोग केवल हार्ड-कोडेड स्ट्रिंग्स के साथ किया जाता है, यह वास्तव में नहीं हो सकता है"। (कोई भी ऐसा नहीं करेगा, कोई बहस कर सकता है; सिवाय इसके कि ओपी ने अपने एसओ उत्तर में ठीक यही किया। यदि क्षेत्र का नाम बदल दिया जाता है, तो जेनेरिक सेटर के उपयोगकर्ता कभी भी नोटिस नहीं करेंगे, सिवाय सेटर के बेहद अस्पष्ट बग के अलावा चुपचाप कुछ भी नहीं। यदि वे भाग्यशाली हैं, तो पाने वाले के उपयोगकर्ता, अनदेखे अपवाद के कंसोल आउटपुट को नोटिस कर सकते हैं।]

रिफ्लेक्शन कोड कंपाइलर द्वारा टाइप-चेक नहीं किया जाता है

यह मूल रूप से उपरोक्त का एक बड़ा उप-बिंदु है। प्रतिबिंब कोड सभी के बारे में है Object। रनटाइम पर प्रकारों की जाँच की जाती है। त्रुटियों की खोज यूनिट परीक्षणों द्वारा की जाती है, लेकिन केवल तभी जब आपके पास कवरेज हो। ("यह सिर्फ एक गटर है, मुझे इसकी जांच करने की आवश्यकता नहीं है।") मूल रूप से, पायथन पर जावा का उपयोग करके आप लाभ खो देते हैं, आपको पहले स्थान पर प्राप्त हुआ।

अनुकूलन के लिए परावर्तन कोड अनुपलब्ध है

हो सकता है कि सिद्धांत रूप में नहीं, लेकिन व्यवहार में, आपको एक JVM नहीं मिलेगा जो इनलाइन या इनलाइन कैश बनाता है Method.invoke। इस तरह के अनुकूलन के लिए सामान्य विधि कॉल उपलब्ध हैं। जो उन्हें बहुत तेज बनाता है।

प्रतिबिंब कोड सामान्य रूप से धीमा है

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

सामान्य रूप से सामान्य गेट्टर / सेटर के नीचे

यह सिर्फ एक बुरा विचार है, क्योंकि आपकी कक्षा में अब कोई एनकैप्सुलेशन नहीं है। इसका हर क्षेत्र सुलभ है। आप उन सभी को सार्वजनिक कर सकते हैं।


8
आपने सभी प्रमुख बिंदुओं को मारा। बहुत सही जवाब है। मैं समझा सकता हूं कि गेटर्स और सेटर सार्वजनिक क्षेत्रों की तुलना में मामूली बेहतर हैं लेकिन बड़ा मुद्दा सही है।
जिमीजैम्स

2
यह भी ध्यान देने योग्य है कि गेटर्स / सेटर आसानी से एक आईडीई द्वारा उत्पन्न किए जा सकते हैं।
stiemannkj1 19

26
एक उत्पादन-आकार परियोजना में +1 डिबगिंग प्रतिबिंब तर्क को संयुक्त राष्ट्र द्वारा यातना के रूप में मान्यता दी जानी चाहिए और इसे अवैध कर दिया जाना चाहिए।
अहाता

4
"इन प्रोग्रामर्स के लिए समझना कठिन है।" - इन प्रोग्रामर्स के लिए इसे समझना काफी कठिन है, लेकिन हर किसी के लिए इसे समझना कठिन है, चाहे वह कितना भी दक्ष क्यों न हो।
बार्टोज़केपी

4
"प्रतिबिंब विश्लेषण स्थिर विश्लेषण के लिए दुर्गम है" - यह। फिर से सक्रिय करने के लिए महत्वपूर्ण है। और जैसा कि स्थैतिक-विश्लेषण उपकरण अधिक शक्तिशाली होते हैं (उदाहरण के लिए नवीनतम टीम फाउंडेशन सर्वर में कोड खोज), कोड लिखना जो उन्हें सक्षम बनाता है और भी अधिक मूल्यवान हो जाता है।
दान जे

11

क्योंकि पास-थ्रू गेटटर / सेटर एक एबोमिनेशन हैं जो कोई मूल्य नहीं प्रदान करते हैं। वे कोई भी एनकैप्सुलेशन प्रदान नहीं करते हैं क्योंकि उपयोगकर्ता गुणों के माध्यम से वास्तविक मूल्यों पर प्राप्त कर सकते हैं। वे YAGNI हैं क्योंकि शायद ही कभी आप अपने क्षेत्र के भंडारण के कार्यान्वयन को बदलने के लिए जा रहे हैं।

और क्योंकि यह रास्ता कम प्रदर्शन करने वाला है। C # में कम से कम, एक गेट्टर / सेटर एक CIL निर्देश के लिए सीधे इनलाइन करेगा। आपके उत्तर में, आप 3 फ़ंक्शन कॉल के साथ प्रतिस्थापित कर रहे हैं, जो बदले में मेटाडेटा को प्रतिबिंबित करने के लिए लोड करने की आवश्यकता है। मैंने आम तौर पर प्रतिबिंब लागत के लिए अंगूठे के नियम के रूप में 10x का उपयोग किया है, लेकिन जब मैंने डेटा की खोज की, तो पहले उत्तरों में से एक में यह उत्तर शामिल था जिसने इसे 1000x के करीब माना।

(और यह आपके कोड को डिबग करने के लिए कठिन बनाता है, और यह प्रयोज्य को हानि पहुँचाता है क्योंकि इसका दुरुपयोग करने के लिए और अधिक तरीके हैं, और यह स्थिरता को नुकसान पहुँचाता है क्योंकि आप अब उचित पहचानकर्ता के बजाय जादू के तार का उपयोग कर रहे हैं ...)


2
ध्यान दें कि प्रश्न जावा को टैग किया गया है, जिसमें बीन्स अवधारणा जैसी रमणीय बकवास है। बीन का कोई सार्वजनिक क्षेत्र नहीं है, लेकिन यह उन क्षेत्रों getX()और setX()विधियों को उजागर कर सकता है जो प्रतिबिंब के माध्यम से मिल सकते हैं। बीन्स आवश्यक रूप से अपने मूल्यों को एनकैप्सूलेट करने के लिए नहीं हैं, वे सिर्फ डीटीओ हो सकते हैं। तो जावा में, गेटर्स अक्सर एक आवश्यक दर्द होता है। C # प्रॉपर्टीज हर लिहाज से काफी, बहुत अच्छे हैं।
आमोन

11
C # प्रॉपर्टी के कपड़े पहने हुए गेटर्स / सेटर हैं, हालाँकि। लेकिन हां, बीन्स की अवधारणा एक आपदा है।
सेबस्टियन रेडल

6
@ वामन अधिकार, सी # ने एक भयानक विचार लिया और इसे लागू करना आसान है।
जिमीजैम

5
@JimmyJames यह वास्तव में एक भयानक विचार नहीं है; आप कोड परिवर्तन के बावजूद ABI संगतता बनाए रख सकते हैं। एक समस्या कई नहीं है, मुझे लगता है।
केसी

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

8

पहले से प्रस्तुत तर्कों के अलावा।

यह अपेक्षित इंटरफ़ेस प्रदान नहीं करता है।

उपयोगकर्ता foo.getBar () और foo.setBar (मान) को कॉल करने की अपेक्षा करते हैं, foo.get ("बार") और foo.set ("बार", मान) को नहीं

उपयोगकर्ताओं को उम्मीद है कि इंटरफ़ेस प्रदान करने के लिए आपको प्रत्येक संपत्ति के लिए एक अलग गेटटर / सेटर लिखना होगा। एक बार जब आप यह कर लेते हैं कि प्रतिबिंब का उपयोग करने का कोई मतलब नहीं है।


मुझे लगता है कि यह कारण अन्य उत्तरों में अन्य लोगों की तुलना में अधिक महत्वपूर्ण है।
एबेन स्कोव पेडरसन

-4

बेशक एक बुरा विचार नहीं है, यह सिर्फ एक सामान्य जावा दुनिया की तुलना में एक बुरा विचार है (जब आप केवल एक गेट्टर या सेटर चाहते हैं)। उदाहरण के लिए कुछ चौखटे (स्प्रिंग mvc) या लाइब्रारे पहले से ही इसे (jstl) उस तरह से उपयोग करते हैं, कुछ json o xml पार्सर इसका उपयोग कर रहे हैं, यदि आप एक DSL का उपयोग करना चाहते हैं तो आप इसका उपयोग करने जा रहे हैं। फिर यह आपके उपयोग की स्थिति पर निर्भर करता है।

एक तथ्य के रूप में कुछ भी सही या गलत नहीं है।

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