2015-04-29 8 views
5

मैं जानना चाहता हूं कि ऐसे मामलों का उपयोग किया जा सकता है जहां सार्वजनिक क्षेत्र उचित हैं (परिवर्तनीय मूल्यों के लिए) या इसे हर कीमत से बचा जाना चाहिए और गेटर्स/सेटर्स का हमेशा उपयोग किया जाना चाहिए।क्या परिवर्तनीय सार्वजनिक क्षेत्रों के लिए उपयोग-मामले हैं?

मान लीजिए कि एक डीटीओ (डेटा ट्रांसफर ऑब्जेक्ट)/जावा बीन है जिसमें कोई तर्क नहीं है, केवल डेटा धारण करना (इसे जोड़ने के लिए प्रोटोकॉल का हिस्सा हो सकता है जो बदलता नहीं है, केवल बढ़ता है)। प्रभावी ढंग से कोई कार्यान्वयन विवरण नहीं है जो encapsulated होने के लिए मौजूद है क्योंकि कोई कार्यान्वयन नहीं है, बस डेटा। यह भी मान लें कि बीन वैलिडेशन फ्रेमवर्क का उपयोग एनोटेशन के माध्यम से ऑब्जेक्ट को सत्यापित करने के लिए किया जाता है, इसलिए लॉजिक को सत्यापित करने के लिए सेटर्स रखने का कोई उद्देश्य नहीं है।

सेटर्स और गेटर्स मुझे परेशान क्यों करेंगे?

सेटर्स/गेटर्स के बिना पढ़ना अधिक आसान है; खेतों, विशेष रूप से आंतरिक कक्षाओं के लिए (आपको अन्य क्षेत्रों तक पहुंचने के लिए सेटर्स और गेटर्स तक स्क्रॉल करने की आवश्यकता नहीं है)। ग्रोवी में user.getPassword() के बजाय user.password होने के अलावा यह और भी स्पष्ट है।

मुझे परियोजना लंबोक के बारे में पता है; लेकिन मेरे पास बीन सत्यापन से पहले से ही कई टिप्पणियां हैं।

तो सवाल स्पष्ट करने के लिए: क्या उपरोक्त परिदृश्य सार्वजनिक क्षेत्रों के लिए उचित हो सकता है या फिर भी सेटर्स/गेटर्स रखना बेहतर है? और क्यों?

+1

अंगूठे का नियम: हमेशा सबसे अधिक प्रतिबंधक संशोधक के साथ शुरू करें, केवल तभी बदलें जब आप * * *: [* [सबसे प्रतिबंधित पहुंच स्तर का उपयोग करें जो किसी विशेष सदस्य के लिए समझ में आता है। निजी का उपयोग करें जब तक आपके पास कोई अच्छा कारण न हो नहीं। *] (http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html) " – Maroun

+1

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

+0

@MarounMaroun अंगूठे के इन नियमों के पीछे कारण हैं; और मैं पूरी तरह से आपके साथ सहमत हूं, परिदृश्यों में जहां आपके पास encapsulate करने के लिए तर्क है। – m3th0dman

उत्तर

1

वर्तमान राय यह है कि आपको में व्यवहार्य सार्वजनिक फ़ील्ड नहीं होना चाहिए।

यह Principle of least astonishment से दो अलग-अलग दिशाओं से निकला है।

सबसे पहले, यह सामान्य अभ्यास है कि सभी फ़ील्ड केवल गेटर्स और सेटर्स के माध्यम से पहुंच के साथ निजी हों। वहां बहुत सारे कोड हैं जो यह आश्चर्यजनक है जब आप उस कोड में आते हैं जो नहीं करता है।

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

हालांकि - शुद्ध डेटा स्थितियां जैसे कि आप वर्णन करते हैं कि यह फ़ील्ड को सार्वजनिक बनाने के लिए और यहां तक ​​कि दुर्लभ, अंतिम नहीं है।

मैं अपने पिटारे में एक वर्ग Pair जो सार्वजनिक क्षेत्रों हैं:

public class Pair<P, Q> { 

    // Exposing p & q directly for simplicity. They are final so this is safe. 

    public final P p; 
    public final Q q; 

    public Pair(P p, Q q) { 
     this.p = p; 
     this.q = q; 
    } 
+0

पहले तर्क के लिए स्वीकृत; वास्तव में महान। दूसरी तर्क क्षेत्र पर इंजेक्शन चुनते समय हमेशा निर्भरता-इंजेक्शन ढांचे (सीडीआई, वसंत, गुइस इत्यादि - '@ इंजेक्ट ',' @ ऑटोवायर') की वजह से नहीं होती है; वे प्रतिबिंब का उपयोग करते हैं और सेटर्स से बचते हैं। – m3th0dman

+0

किसके बारे में वर्तमान राय? एक्सेसर्स/म्यूटेटर पर बहस है। मैं इसे सुलझाने पर विचार नहीं करता हूं। मैं व्यक्तिगत रूप से उन्हें लिखता हूं, लेकिन मुझे लगता है कि आपका जवाब dogmatic है। –

0

उपरोक्त परिदृश्य सार्वजनिक क्षेत्रों के लिए उचित हो सकता है या यह अभी भी बेहतर setters/टिककर खेल है?

यह परिदृश्य प्रतीत होता है कि आप गेटर्स और सेटर्स के माध्यम से स्क्रॉल करके परेशान हैं। यह मेरी किताब में एक अच्छा कारण नहीं है, लेकिन यदि आप इन वर्गों को पैकेज-निजी या निजी घोंसले वाले वर्गों को रख सकते हैं, तो यह यहोशू ब्लोच द्वारा ठीक है क्योंकि संभावित भविष्य में बदलाव का दायरा है।

प्रभावी जावा मद 14: सार्वजनिक कक्षाएं, उपयोग एक्सेसर तरीकों, नहीं सार्वजनिक क्षेत्रों

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

हालांकि, अगर एक वर्ग पैकेज-निजी है या एक निजी नेस्टेड वर्ग है, वहाँ अपने डेटा फ़ील्ड उजागर साथ स्वाभाविक गलत कुछ भी नहीं है - यह सोचते हैं कि वे वर्ग द्वारा प्रदान की अमूर्त का वर्णन करने का एक पर्याप्त काम करते हैं।

व्यक्तिगत तौर पर मैं कर रहा हूँ एक छोटे से सख्त और अंगूठे का नियम मैं पालन क्षेत्रों संकलन इकाई बाहर दिखाई नहीं होना चाहिए है। उदाहरण के लिए:

public class Outer { 
    private int fieldMustBePrivate; 

    public class PublicNested { 
     private int fieldMustBePrivate; 
    } 

    private class PrivateNested { 
     int fieldOkToBePackagePrivate; 
    } 

    public void exampleUsage() { 
     PrivateNested privateNested = new PrivateNested(); 
     privateNested.fieldOkToBePackagePrivate = 123; 
    } 
} 
+0

जैसा कि मैंने कहा है, encapsulation के बारे में बात करना कोई मतलब नहीं है क्योंकि दिए गए वर्गों में कोई तर्क नहीं है जिसे encapsulated किया जा सकता है। केवल एक डेटा है जो सार्वजनिक प्रोटोकॉल का हिस्सा है, इसलिए कुछ भी छिपाने का कोई कारण नहीं है। – m3th0dman

+0

मैंने इसे एक बार उल्लेख किया और मैंने इसे बाहर निकाला है, क्योंकि यह मुख्य बिंदु नहीं था। – weston

+0

जावा में आखिरी सार्वजनिक एपीआई क्या थी जिसका उपयोग आपने उत्परिवर्तनीय सार्वजनिक क्षेत्रों में किया था? – weston

1

एक आम मामले कुछ समय कार्यान्वयन या निष्पादन के बीच में, आप पाते हैं कि, कि तुम्हारा रिकॉर्ड एक खाली उपयोगकर्ता नाम के साथ समाप्त होता है।

अब, आप या तो:

  • खोज सभी स्थानों संपत्ति जहां यह एक अशक्त सौंपा जा रहा है खोजने के लिए असाइन किया गया है थे। यह 20 स्थान हो सकता है, और संभवतः, यह user.userName = null नहीं होगा लेकिन String userName = null; ..... user.userName = userName होगा।

  • अपनी setUserName() विधि में एक चेक जोड़ें जो एक अपवाद लॉन्च करने का प्रयास करते समय अपवाद लॉन्च करता है। आपको पूरा स्टैकट्रैक मिलता है, और प्रोग्राम का संचालन से पहले आपके दृढ़ता परत पर खराब डेटा पेश करने से पहले बंद कर दिया गया है।

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

मैं सेटर्स के साथ रहूंगा।

इसके अतिरिक्त, कुछ (कई) ढांचे गुणों तक पहुंचने के लिए सेटर्स और गेटर्स के उपयोग में भरोसा करते हैं।

+0

मैं पहले से ही क्षेत्र इंजेक्शन के साथ निर्भरता इंजेक्शन ढांचे (उदाहरण के लिए सीडीआई, वसंत, गुइस) का उपयोग करता हूं; ये सेटर्स से भी बचते हैं। साथ ही, समस्या पर हाथ कक्षाएं प्रोटोकॉल का हिस्सा हैं, इसलिए डेटा को पूरे संदेश के लिए किसी प्रकार के ढांचे/उपकरण द्वारा स्वचालित रूप से सेट किया जाता है। इसकी तुलना आरईएसटी जेएसओएन एपीआई के साथ की जा सकती है; जब आप HTTP पर उपयोगकर्ता का विवरण प्राप्त करते हैं तो आप स्पष्ट रूप से उपयोगकर्ता फोन के लिए सेटटर को कॉल नहीं करते हैं लेकिन फोन नंबर जैक्सन/जीसन द्वारा निर्धारित किया जाता है या आप जिस लाइब्रेरी का उपयोग पूरे JSON को POJO में परिवर्तित करने के लिए करते हैं। – m3th0dman

0

हाँ, वहाँ रहे हैं:

  • प्रदर्शन
  • कोड संक्षिप्तता

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

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

दूसरे उपयोग के मामले, कोड ब्रेवटी, गेटर और सेटर जो कुछ भी नहीं करते हैं (वे कोई सत्यापन नहीं करते हैं, कोई सिंक्रनाइज़ेशन नहीं, कोई प्रतिलिपि नहीं, कुछ भी नहीं) वास्तव में अनिवार्य हैं और हम उन्हें कोड करते हैं क्योंकि यह जावा में सम्मेलन है। लेकिन वे कोई उद्देश्य नहीं देते हैं। अन्य लोग (उदा .: Google) इस सम्मेलन का अंधाधुंध पालन नहीं करते हैं।

नई भाषाएं आमतौर पर इन विधियों के निर्माण को स्वचालित करने के लिए कुछ तंत्र प्रदान करती हैं, या इन्हें पूरी तरह से छोड़ देती हैं, जो सदस्य पहुंच संशोधक पर निर्भर करता है ताकि वे encapsulation प्रदान कर सकें। उदाहरण के लिए, C#'s properties स्वचालित गेटर/सेटर्स प्रदान करते हैं लेकिन आपके कोड को उन्हें कॉल करने की अनुमति देते हैं जैसे कि वे सार्वजनिक सदस्य थे।

+1

मुझे नहीं लगता कि प्रदर्शन बिल्कुल एक मुद्दा है; आमतौर पर सरल तरीकों को संकलक द्वारा रेखांकित किया जाता है - http://en.wikipedia.org/wiki/Inline_expansion देखें। कोड ब्रेवटी के संबंध में, जावा में प्रोजेक्ट लॉमोकॉक है जो सी # गुणों की तरह काफी है (हालांकि यह जेडीके का हिस्सा नहीं है)। – m3th0dman

+0

जेआईटी कंपाइलर एक मानक जेवीएम में भारी इनलाइनिंग करने की संभावना है। लेकिन जावा एमई के पुराने केवीएम की तरह कोई जेआईटी नहीं है, और मुझे आश्चर्य है कि नया जावाएमई एम्बेडेड इसका समर्थन करता है या नहीं। –

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

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