जाँच करें पैरामीटर null के लिए @Nonnull के साथ एनोटेट?


19

हमने FindBugs का उपयोग करना शुरू कर दिया है और हमारे मापदंडों को @Nonnullउचित रूप से एनोटेट कर रहे हैं , और यह चक्र में कीड़े को इंगित करने के लिए बहुत अच्छा काम करता है। अब तक हमने nullअमरूद का उपयोग करने के लिए इन तर्कों की जाँच जारी रखी है checkNotNull, लेकिन मैं nullकेवल किनारों - स्थानों पर जाँच करना पसंद करूँगा जहाँ मूल्य की जाँच किए बिना आ सकता है null, उदाहरण के लिए, एक SOAP अनुरोध।

// service layer accessible from outside
public Person createPerson(@CheckForNull String name) {
    return new Person(Preconditions.checkNotNull(name));
}

...

// internal constructor accessed only by the service layer
public Person(@Nonnull String name) {
    this.name = Preconditions.checkNotNull(name);  // remove this check?
}

मैं समझता हूं कि अपने आप मूल्यों को @Nonnullअवरुद्ध नहीं करता nullहै।

हालांकि, यह देखते हुए कि फाइंडबग्स कहीं भी इंगित करेगा कि एक मान चिह्न को एक चिह्नित फ़ील्ड से एक में स्थानांतरित किया जाता है @Nonnull, क्या हम इन मामलों को पकड़ने के लिए इस पर निर्भर नहीं कर सकते (जो ऐसा करता है) इन मूल्यों की जांच किए बिना nullहर जगह वे चारों ओर से गुजरते हैं। प्रणाली? क्या मैं उपकरण पर भरोसा करना चाहता हूं और इन क्रिया जांचों से बचना चाहता हूं?

नीचे की रेखा: जबकि nullनीचे दिए गए दूसरे चेक को निकालना सुरक्षित लगता है , क्या यह बुरा अभ्यास है?

यह प्रश्न संभवत: शून्य के लिए एक चेक के समान है यदि वह अशक्त होने की उम्मीद नहीं करता है , लेकिन मैं @Nonnullएनोटेशन के संबंध में विशेष रूप से पूछ रहा हूं ।

जवाबों:


6

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

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

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

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

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

इसके अलावा, अनुबंधों का उपयोग स्थैतिक विश्लेषण के लिए किया जा सकता है, जो वास्तव में इसे चलाने के बिना स्रोत कोड के बारे में निष्कर्ष निकालने की कोशिश करता है।

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

JML जावा का एक विस्तार है जिसमें विनिर्देश विशेष जावा टिप्पणियाँ में अंतर्निहित है। इस दृष्टिकोण का एक फायदा यह है कि आप परिष्कृत विनिर्देश का उपयोग कर सकते हैं, यहां तक ​​कि एक विकास के दृष्टिकोण का उपयोग करते हुए जिसमें आप केवल कार्यान्वयन विवरण के बजाय विनिर्देश पर निर्भर होते हैं और विभिन्न उपकरणों का उपयोग करते हैं जो विनिर्देश का उपयोग करते हैं, जैसे कि उल्लेख रनटाइम-अभिकथन जाँच उपकरण, इकाई परीक्षण या प्रलेखन की स्वचालित पीढ़ी।

यदि आप @nonnull (हल्का) अनुबंध होने के बारे में मेरी बात साझा करते हैं, तो अतिरिक्त चेक नहीं जोड़ना आम बात होगी क्योंकि इस सिद्धांत के पीछे मूल विचार रक्षात्मक प्रोग्रामिंग से बचने का है।


2
यह वास्तव में मैं कैसे उपयोग कर रहा हूं @Nonnull: एक अनुबंध विनिर्देश के रूप में। मैं अनुबंध के पीछे रक्षात्मक जांचों को हटा रहा हूं और अब तक कोई परेशानी नहीं हुई है।
डेविड हरकनेस

4

ठीक है, विचार करें कि आप क्यों नहीं लिखते हैं

this.name = Preconditions.checkNotNull(name);  // Might be necessary
that.name = Preconditions.checkNotNull(this.name);  // Who knows?

प्रोग्रामिंग काला जादू नहीं है। चर अचानक अशक्त नहीं हो जाते हैं। यदि आप जानते हैं कि एक चर शून्य नहीं है, और आप जानते हैं कि यह परिवर्तित नहीं हुआ है, तो इसकी जांच करें।

यदि आप इसकी जांच करते हैं, तो भविष्य में कुछ प्रोग्रामर (संभवतः आप) यह पता लगाने में बहुत समय बिताएंगे कि चेक क्यों है। चेक एक कारण के लिए होना चाहिए, आखिरकार, तो आप क्या देख रहे हैं?


3
@Nonnullअनुबंध निर्दिष्ट कॉल पारित है कि नहीं करना चाहिए nullनिर्माता के लिए, और FindBugs स्थिर विश्लेषण का उपयोग करता है कॉल कि अनुमति दे सकते हैं पता लगाने के लिए null--specifically कॉल है कि मूल्यों में चिह्नित नहीं पारित @Nonnullखुद को। लेकिन nullFindBugs की चेतावनी को पारित करने और अनदेखा करने के लिए एक कॉलर स्वतंत्र है ।
डेविड हार्कस

प्रोग्रामिंग आदर्श रूप से काला जादू नहीं है। दुर्भाग्य से, caveats और आश्चर्य की बात है, खासकर जब कुछ संगोष्ठी कोड के साथ काम कर रहे हैं eats ~ ᕕ (ᕗ) ᐛ
टिम हार्पर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.