क्या फ़ंक्शन / विधियों से NULL या रिक्त मान वापस करना बेहतर है, जहाँ रिटर्न मान मौजूद नहीं है?


135

मैं यहां एक सिफारिश की तलाश कर रहा हूं। मैं इस बात से जूझ रहा हूं कि क्या NULL या किसी रिक्त मान को किसी विधि से वापस करना बेहतर है जब रिटर्न मान मौजूद नहीं है या निर्धारित नहीं किया जा सकता है।

एक उदाहरण के रूप में निम्नलिखित दो तरीके अपनाएं:

string ReverseString(string stringToReverse) // takes a string and reverses it.
Person FindPerson(int personID)    // finds a Person with a matching personID.

में ReverseString(), मैं कहूंगा कि एक खाली स्ट्रिंग लौटाओ क्योंकि वापसी प्रकार स्ट्रिंग है, इसलिए कॉलर उम्मीद कर रहा है। इसके अलावा, इस तरह, कॉल करने वाले को यह देखने के लिए जांच नहीं करनी होगी कि क्या NULL वापस किया गया था या नहीं।

में FindPerson(), NULL लौटाना एक बेहतर फिट की तरह लगता है। भले ही NULL या कोई खाली व्यक्ति ऑब्जेक्ट ( new Person()) लौटाया जाए या नहीं , कॉल करने वाले को यह देखने के लिए जांचना होगा कि व्यक्ति ऑब्जेक्ट कुछ करने से पहले NULL या खाली है (जैसे कॉलिंग UpdateName())। तो क्यों न केवल NULL को यहाँ लौटाएँ और फिर कॉलर को केवल NULL की जाँच करनी है।

क्या कोई और इससे संघर्ष करता है? किसी भी मदद या अंतर्दृष्टि की सराहना की है।


2
यह अलग-अलग होगा। आप यह भी तर्क दे सकते हैं कि विधि को उन मूल्यों को रोकना चाहिए जो गलत हैं, उदाहरण के लिए, आपके स्ट्रिंगट्रोवर्स पैरामीटर को खाली या अशक्त माना जा रहा है। यदि आपने वह चेक किया (अपवाद को वापस फेंक दिया), तो यह हमेशा शून्य के अलावा कुछ और लौटाएगा।
एरोन मैकिवर

फाउलर POEAA - पी। 496 आधार पैटर्न - विशेष मामला (अशक्त वस्तु) बलोच प्रभावी जावा, द्वितीय संस्करण आइटम 43: खाली सरणियाँ या संग्रह लौटाएं, नल नहीं
बोरिस ट्रेखोव

1
@ बोरिस मैंने आपकी टिप्पणी नहीं देखी। मैंने वास्तव में विशेष केस को एक उत्तर के रूप में पोस्ट किया है।
थॉमस ओवेन्स

@ थोमस मुझे इसमें कोई समस्या नहीं दिखती :)। सवाल के लिए यह वैसे भी सामान्य ज्ञान की बात है।
बोरिस ट्रेखोव

एक दिलचस्प टिप्पणी यह ​​है कि ओरेकल डेटाबेस में NULL और खाली स्ट्रिंग समान हैं
वूहोइनटेड

जवाबों:


77

StackOverflow ने इस प्रश्नोत्तर में इस सटीक विषय के बारे में अच्छी चर्चा की है । टॉप रेटेड प्रश्न में, क्रोनोज़ नोट्स:

यदि आप कोई डेटा उपलब्ध नहीं है, तो यह इंगित करने के लिए कि आप कोई डेटा उपलब्ध कराना चाहते हैं, तो रिटर्निंग नल आमतौर पर सर्वोत्तम विचार है।

एक खाली वस्तु का तात्पर्य डेटा वापस कर दिया गया है, जबकि अशक्त लौटने से स्पष्ट रूप से संकेत मिलता है कि कुछ भी वापस नहीं किया गया है।

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

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

हालांकि, एसओ उत्तर में पोस्टर के रूप में उल्लेख किया गया है, नल को संभवतः वापस किया जाना चाहिए यदि कोई वस्तु अपेक्षित है ताकि डेटा के वापस होने के बारे में कोई संदेह न हो।

अंत में, चीजों को करने का कोई सबसे अच्छा तरीका नहीं है। एक टीम की सहमति का निर्माण अंततः आपकी टीम की सर्वोत्तम प्रथाओं को संचालित करेगा।


8
व्यक्तिगत रूप से, मैं उन कार्यों के लिए खाली स्ट्रिंग्स को वापस करना पसंद करता हूं जो स्ट्रिंग की वापसी को कम करते हैं जो त्रुटि से निपटने की मात्रा को कम करने के लिए होती है। इस तर्क को कभी नहीं समझा। अशक्त जांच क्या है, अधिकांश <10 वर्णों पर? हम इस तरह से क्यों काम कर रहे हैं?
एरोन मैकिवर

19
किसी ने नहीं कहा कि यह झुकने वाला श्रम था। लेकिन यह है श्रम। यह एक विशेष मामले को कोड में जोड़ता है जिसका अर्थ है परीक्षण करने के लिए एक और शाखा। साथ ही, यह कोड के प्रवाह को बाधित करता है। for x in list_of_things() {...}यकीनन इसके बाद ग्रो करने की जल्दी हैl = list_of_things(); if l != null {...}
ब्रायन ओकले 20

5
@ ब्रायन: मूल्यों की एक खाली सूची और एक रिक्त स्ट्रिंग के बीच एक बड़ा अंतर है। एक स्ट्रिंग शायद ही कभी पात्रों की एक सूची का प्रतिनिधित्व करता है।
केविन क्लाइन

3
@kevin cline: बेशक। लेकिन एक स्ट्रिंग के मामले में, आप चाहते हैं कि स्ट्रिंग एक लॉग में दिखाई दे या नहीं, यह शून्य है या नहीं। यह जाँचने के बाद कि क्या यह अशक्त है तो आप एक खाली स्ट्रिंग प्रिंट कर सकते हैं वास्तविक इरादे को बाधित करता है। या शायद यह डेटाबेस फ़ील्ड की तरह कुछ है जिसमें उपयोगकर्ता द्वारा योगदान की गई सामग्री है जिसे आप एक वेब पेज पर जोड़ना चाहते हैं। यह करने के लिए आसान emit(user.hometown)हैif user.hometown == null { emit("") else {emit(user.hometown)}
ब्रायन ओकले

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

82

मेरे द्वारा लिखे गए सभी कोड में, मैं nullएक फ़ंक्शन से लौटने से बचता हूं । मैंने उसे क्लीन कोड में पढ़ा ।

उपयोग करने nullमें समस्या यह है कि इंटरफ़ेस का उपयोग करने वाला व्यक्ति यह नहीं जानता nullहै कि क्या संभावित परिणाम है, और क्या उन्हें इसके लिए जांच करनी है, क्योंकि इसका not nullसंदर्भ प्रकार है।

F # में आप एक optionप्रकार लौटा सकते हैं , जो हो सकता है some(Person)या none, इसलिए यह कॉलर के लिए स्पष्ट है कि उन्हें जांचना होगा।

अनुरूप C # (विरोधी) पैटर्न Try...विधि है:

public bool TryFindPerson(int personId, out Person result);

अब मुझे पता है कि लोगों ने कहा है कि वे पैटर्न से नफरत करते हैं Try...क्योंकि आउटपुट पैरामीटर होने से शुद्ध फ़ंक्शन के विचार टूट जाते हैं, लेकिन यह वास्तव में इससे अलग नहीं है:

class FindResult<T>
{
   public FindResult(bool found, T result)
   {
       this.Found = found;
       this.Result = result;
   }

   public bool Found { get; private set; }
   // Only valid if Found is true
   public T Result { get; private set;
}

public FindResult<Person> FindPerson(int personId);

... और ईमानदार होने के लिए आप यह मान सकते हैं कि प्रत्येक .NET प्रोग्रामर Try...पैटर्न के बारे में जानता है क्योंकि यह .NET फ्रेमवर्क द्वारा आंतरिक रूप से उपयोग किया जाता है। इसका मतलब है कि उन्हें यह समझने के लिए प्रलेखन को पढ़ने की ज़रूरत नहीं है कि यह क्या करता है, जो मेरे लिए कुछ शुद्धतावादी कार्यों के दृष्टिकोण से चिपके रहने की तुलना में अधिक महत्वपूर्ण है (यह समझना कि resultएक outपैरामीटर है, पैरामीटर नहीं ref)।

इसलिए मैं आपके साथ जाऊंगा TryFindPersonक्योंकि आपको लगता है कि इसे खोजने में असमर्थ होना पूरी तरह से सामान्य है।

अगर, दूसरी तरफ, कोई तार्किक कारण नहीं है कि कॉलर कभी भी ऐसा प्रदान करेगा personIdजो अस्तित्व में नहीं था, तो मैं शायद ऐसा करूंगा:

public Person GetPerson(int personId);

... और फिर मैं एक अपवाद फेंक देता अगर यह अमान्य था। Get...उपसर्ग फोन करने वाले को पता है कि यह सफल चाहिए निकलता है।


28
यदि आप पहले से ही ऐसा नहीं करते थे, तो मैं इस सवाल का जवाब क्लीन कोड के संदर्भ में दूंगा। मुझे यह मंत्र पसंद है: "अगर आपका फंक्शन क्या है तो इसका नाम क्या है, यह एक अपवाद है।" मुउच हर दर्जन लाइनों या तो नल के लिए जाँच करने से बेहतर है ....
ग्राहम

13
मैंने लोगों के ज्ञान के बारे में कुछ भी मानना ​​छोड़ दिया है।
कैफीक नेक

5
"अशक्त का उपयोग करने के साथ समस्या यह है कि इंटरफ़ेस का उपयोग करने वाला व्यक्ति यह नहीं जानता कि क्या अशक्त परिणाम संभव है, और क्या उन्हें इसके लिए जांच करनी है, क्योंकि कोई अशक्त संदर्भ प्रकार नहीं है।" चूंकि संदर्भ प्रकार अशक्त हो सकते हैं, क्या आप हमेशा यह नहीं मान सकते हैं कि अशक्त परिणाम संभव है?
टॉमी कार्लाइल

4
यदि कोई फ़ंक्शन पॉइंटर (C / C ++) या किसी ऑब्जेक्ट (Java) का संदर्भ देता है, तो मैं हमेशा मानता हूं कि यह अशक्त हो सकता है।
जियोर्जियो

7
"अशक्त का उपयोग करने के साथ समस्या यह है कि इंटरफ़ेस का उपयोग करने वाला व्यक्ति यह नहीं जानता कि क्या अशक्त परिणाम संभव है, और क्या उन्हें इसके लिए जांच करनी है, [...]" यदि कोई विधि अशक्त वापस आ सकती है, तो यह स्पष्ट रूप से होना चाहिए एपीआई अनुबंध के हिस्से के रूप में उल्लेख किया गया है।
Zsolt Török

28

आप पैटरन्स ऑफ़ एंटरप्राइज एप्लीकेशन आर्किटेक्चर से मार्टिन फाउलर के विशेष केस पैटर्न की कोशिश कर सकते हैं :

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

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

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

अशक्त, या कुछ अजीब मान लौटने के बजाय, एक विशेष केस लौटाएं जिसमें वही इंटरफ़ेस है जो कॉलर को उम्मीद है।


मैं इस परिदृश्य में भाग गया, लेकिन सॉफ्टवेयर जारी होने के बाद ही। मेरे परीक्षण डेटा ने इसे कभी ट्रिगर नहीं किया, इसलिए यह नीले रंग से थोड़ा बाहर था और डिबग करने के लिए दर्द था। हालाँकि मैंने इसे विशेष केस पैटर्न के साथ हल नहीं किया है, लेकिन इसके बारे में पता होना अच्छा है।
samis

14

मुझे लगता है कि ReverseString()उलटा स्ट्रिंग वापस आ जाएगा और यह एक IllegalArgumentExceptionअगर में पारित कर दिया फेंक देंगे Null

मुझे लगता है कि NullObject पैटर्नFindPerson() का पालन करना चाहिए या कुछ न पाने के बारे में एक अनियंत्रित अपवाद उठाना चाहिए अगर आपको हमेशा कुछ खोजने में सक्षम होना चाहिए।

से निपटने के Nullलिए कुछ है जो बचा जाना चाहिए। Nullभाषाओं में होने को आविष्कारक द्वारा बिलियन डॉलर मिस्टेक कहा गया है !

मैं इसे अपनी अरबों डॉलर की गलती कहता हूं। यह 1965 में अशक्त संदर्भ का आविष्कार था। उस समय, मैं ऑब्जेक्ट ओरिएंटेड भाषा (ALGOL W) में संदर्भ के लिए पहला व्यापक प्रकार का सिस्टम डिजाइन कर रहा था।

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

इससे असंख्य त्रुटियां, कमजोरियां और सिस्टम क्रैश हो गए हैं, जिसने पिछले चालीस वर्षों में संभवतः एक अरब डॉलर का दर्द और क्षति पहुंचाई है।

हाल के वर्षों में, Microsoft में PREIFT और PREIFT जैसे कई प्रोग्राम विश्लेषणियों का उपयोग संदर्भों की जांच करने के लिए किया गया है, और चेतावनी दी गई है कि अगर कोई जोखिम है तो वे गैर-अशक्त हो सकते हैं। Spec # जैसी हालिया प्रोग्रामिंग भाषाओं ने गैर-अशक्त संदर्भों के लिए घोषणाएं प्रस्तुत की हैं। यह समाधान है, जिसे मैंने 1965 में खारिज कर दिया था।

टोनी होरे


11

एक विकल्प लौटाएँ । NullPointerException के किसी भी जोखिम के बिना एक अलग अमान्य मान वापस करने के सभी लाभ (जैसे आपके संग्रह में खाली मान रखने में सक्षम होना)।


1
दिलचस्प। जावा में विकल्प कैसे लागू करें? और C ++ में?
जियोर्जियो

1
@Giorgio, For Java, Google की ओर से Guava लाइब्रेरी, एक वर्ग है, जिसे वैकल्पिक कहा जाता है ।
ओटावियो मैसिडो

1
सी ++ के लिए, वहाँ हैboost::optional<T>
MSalters

8

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

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

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

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

फिर, इस तर्क के दोनों ओर ऐसे बिंदु हैं जिनसे मैं सहमत हो सकता था, लेकिन मुझे लगता है कि यह सबसे अधिक लोगों को सबसे अधिक समझ में आता है (कोड को अधिक बनाए रखने योग्य)।


अंतर है, "है FindPersonया GetPersonएक अशक्त वापसी या यदि कुंजी मौजूद नहीं है एक अपवाद फेंक?" एपीआई के एक उपयोगकर्ता के रूप में मुझे अभी पता नहीं है और मुझे दस्तावेज की जांच करनी है। दूसरी ओर, bool TryGetPerson(Guid key, out Person person)मुझे दस्तावेज़ीकरण की जांच करने की आवश्यकता नहीं है और मुझे पता है कि एक अपवाद एक गैर-असाधारण परिस्थिति में क्या मात्रा में नहीं फेंका गया है। यही बात मैं अपने उत्तर में बनाने की कोशिश कर रहा हूं।
स्कॉट व्हिटलॉक

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

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

6

यदि आइटम मौजूद है या नहीं, यह जानने की जरूरत है, तो अशक्त वापस लौटें। अन्यथा, अपेक्षित डेटा प्रकार वापस करें। यदि आप आइटमों की सूची लौटा रहे हैं तो यह विशेष रूप से सच है। यह आमतौर पर यह मान लेना सुरक्षित है कि यदि कॉलर सूची चाहता है, तो वे सूची पर पुनरावृति करना चाहते हैं। कई (सबसे? सभी?) भाषाएं विफल हो जाती हैं यदि आप अशक्त पर पुनरावृति करने की कोशिश करते हैं, लेकिन तब नहीं जब आप खाली सूची पर पुनरावृति करते हैं।

मुझे लगता है कि इस तरह के कोड का उपयोग करने की कोशिश करना निराशाजनक है, केवल इसे विफल करने के लिए:

for thing in get_list_of_things() {
    do_something_clever(thing)
}

जब कोई बात न हो तो मुझे केस के लिए एक विशेष केस जोड़ना होगा ।


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

5

यह विधि के शब्दार्थ पर निर्भर करता है। आप संभवतः निर्दिष्ट कर सकते हैं, आपकी विधि केवल "शून्य नहीं" स्वीकार करती है। जावा में आप घोषणा कर सकते हैं कि कुछ मेटाडेटा एनोटेशन का उपयोग करते हुए:

string ReverseString(@NotNull String stringToReverse)

आपको किसी तरह वापसी मूल्य निर्दिष्ट करना चाहिए। यदि आप घोषणा करते हैं, तो आप केवल नोटनल मानों को स्वीकार करते हैं, आप खाली स्ट्रिंग वापस करने के लिए बाध्य हैं (यदि इनपुट खाली स्ट्रिंग भी था)।

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

Person FindPerson(int personID)

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


3

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

if (someObject != null && someObject.someMethod () != whateverValue)

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

ऐसे मामलों में जहां वापसी का nullमतलब होता है ( findPerson ()उदाहरण के लिए विधि को कॉल करना ), मैं कम से कम एक विधि प्रदान करने की कोशिश करूंगा जो कि वस्तु मौजूद है ( personExists (int personId)उदाहरण के लिए), रिटर्न एक और उदाहरण जावा में containsKey ()एक विधि होगी Map)। यह कॉलर्स का कोड क्लीनर बनाता है, जैसा कि आप आसानी से देख सकते हैं कि एक संभावना है कि वांछित वस्तु उपलब्ध नहीं हो सकती है (व्यक्ति मौजूद नहीं है, कुंजी मानचित्र में मौजूद नहीं है)। यदि कोई संदर्भ nullमेरे विचार से कोड को बाधित करता है तो लगातार जाँच करना ।


3

null सबसे अच्छी बात है कि अगर और केवल तभी लौटाया जाए जब निम्नलिखित निम्नलिखित शर्तें लागू हों:

  • सामान्य ऑपरेशन में अशक्त परिणाम की उम्मीद है । यह उम्मीद की जा सकती है कि आप कुछ उचित परिस्थितियों में एक व्यक्ति को खोजने में सक्षम नहीं हो सकते हैं, इसलिए nPerson () रिटर्निंग नल ठीक है। हालांकि अगर यह वास्तव में अप्रत्याशित विफलता है (जैसे कि saveMyImportantData () नामक फ़ंक्शन में) तो आपको एक अपवाद फेंकना चाहिए। नाम में एक संकेत है - अपवाद असाधारण परिस्थितियों के लिए हैं!
  • null का अर्थ है "नहीं मिला / कोई मूल्य नहीं" । अगर तुम्हारा मतलब कुछ और है, तो कुछ और लौटाओ! इन्फिनिटी या NaN को लौटाने वाले अच्छे उदाहरण फ्लोटिंग पॉइंट ऑपरेशंस होंगे - ये विशिष्ट अर्थों के साथ मान हैं इसलिए यह बहुत भ्रमित हो जाता है यदि आप यहां वापस लौट आए।
  • फ़ंक्शन का अर्थ एकल मान वापस करना है , जैसे कि फ़ंडपर्सन ()। यदि यह एक संग्रह को वापस करने के लिए डिज़ाइन किया गया था जैसे कि findAllOldPeople () तो एक खाली संग्रह सबसे अच्छा है। इसका एक आधार यह है कि एक समारोह जो एक संग्रह लौटाता है उसे कभी भी अशक्त नहीं लौटना चाहिए

इसके अलावा, सुनिश्चित करें कि आप इस तथ्य का दस्तावेजीकरण करते हैं कि फ़ंक्शन शून्य हो सकता है।

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

अंत में, यदि आप इन नियमों को प्रश्न में सूचीबद्ध दो कार्यों पर लागू करते हैं:

  • फाइंडपर्सन - इस फ़ंक्शन के लिए यह उचित होगा कि यदि व्यक्ति नहीं मिला, तो वह अशक्त हो जाए
  • ReverseString - ऐसा लगता है कि यह एक परिणाम प्राप्त करने में विफल कभी नहीं होगा अगर एक स्ट्रिंग पारित कर दिया (चूंकि सभी तार उलट हो सकते हैं, जिसमें खाली स्ट्रिंग भी शामिल है)। इसलिए इसे कभी भी शून्य नहीं लौटना चाहिए। अगर कुछ गलत हो जाता है (स्मृति से बाहर?) तो इसे एक अपवाद फेंक देना चाहिए।

1

मेरी राय में, NULL को वापस करने, कुछ खाली परिणाम (जैसे कि खाली स्ट्रिंग या खाली सूची) लौटाने और एक अपवाद को फेंकने के बीच अंतर है।

मैं आम तौर पर निम्नलिखित दृष्टिकोण अपनाता हूं। मैं एक फ़ंक्शन या विधि f (v1, ..., vn) को एक फ़ंक्शन के अनुप्रयोग के रूप में मानता हूं

f : S x T1 x ... x Tn -> T

जहां यह एस "दुनिया का राज्य" T1, ..., Tn इनपुट पैरामीटर के प्रकार हैं, और T रिटर्न प्रकार है।

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

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

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

उदाहरण के लिए, मान लें कि मेरे पास एक ग्राहक वर्ग है और मैं एक विधि लागू करना चाहता हूं

Customer findCustomer(String customerCode)

अपने कोड द्वारा एप्लिकेशन डेटाबेस में एक ग्राहक की खोज करना। इस विधि में, मैं करूँगा

  • यदि कक्षा सफल है, तो कक्षा ग्राहक की एक वस्तु लौटाएं,
  • यदि कोई ग्राहक नहीं मिलता है, तो अशक्त वापस लौटें।
  • यदि डेटाबेस से कनेक्ट करना संभव नहीं है, तो एक अपवाद को फेंक दें।

अशक्त के लिए अतिरिक्त जांच, जैसे

Customer customer = findCustomer("...");
if (customer != null && customer.getOrders() > 0)
{
    ...
}

मैं जो कुछ कर रहा हूं उसके शब्दार्थ का एक हिस्सा हैं और मैं कोड को बेहतर तरीके से पढ़ने के लिए सिर्फ उन्हें "स्किप" नहीं करूंगा। मुझे नहीं लगता कि कोड को सरल बनाने के लिए हाथ में समस्या के शब्दार्थ को सरल बनाना एक अच्छा अभ्यास है।

बेशक, चूंकि नल के लिए चेक बहुत बार होता है, यह अच्छा है अगर भाषा इसके लिए कुछ विशेष वाक्यविन्यास का समर्थन करती है।

जब तक मैं अन्य सभी वस्तुओं से एक वर्ग की अशक्त वस्तु को अलग कर सकता हूं, तब तक मैं नल ऑब्जेक्ट पैटर्न (लाफ द्वारा सुझाए गए) का उपयोग करने पर भी विचार करूंगा।


0

संग्रह वापस करने के तरीके खाली लौट आने चाहिए, लेकिन अन्य अशक्त हो सकते हैं, क्योंकि संग्रह के लिए ऐसा हो सकता है कि आपके पास कोई वस्तु होगी, लेकिन इसमें कोई तत्व नहीं हैं, इसलिए कॉलर सिर्फ आकार के लिए मान्य होगा।


0

मेरे लिए यहां दो मामले हैं। यदि आप किसी प्रकार की सूची लौटा रहे हैं, तो आपको हमेशा सूची को वापस करना चाहिए चाहे कोई भी हो, यदि आपके पास इसमें डालने के लिए कुछ भी नहीं है तो खाली है।

एक ही मामला है जहाँ मुझे कोई बहस दिखाई देती है, जब आप किसी एक आइटम को वापस कर रहे हैं। मैं खुद को चीजों को तेजी से विफल बनाने के आधार पर ऐसी स्थिति में विफलता के मामले में अशक्त लौटने के लिए प्राथमिकता देना चाहता हूं।

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


0

Maybeटाइप कंस्ट्रक्टर के बारे में पहले से ही लोगों ने क्या कहा है :

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

अब, इसके बारे में क्या findCustomer(int id)? यह फ़ंक्शन उस ग्राहक का प्रतिनिधित्व करता है जिसके पास दी गई आईडी है। यह कुछ ऐसा है जो अस्तित्व में है या नहीं हो सकता है। लेकिन याद रखें, फ़ंक्शन का एकल रिटर्न मान है, इसलिए आप वास्तव में यह नहीं कह सकते हैं "यह फ़ंक्शन किसी ग्राहक को दिए गए आईडी के साथ देता है या यह रिटर्न देता है null

यह मेरा मुख्य मुद्दा है, nullएक अशक्त वस्तु को वापस करने और वापस करने के साथ । वे गुमराह कर रहे हैं। nullग्राहक नहीं है, और यह वास्तव में "ग्राहक की अनुपस्थिति" भी नहीं है। यह कुछ भी की अनुपस्थिति है। यह सिर्फ कुछ नहीं करने के लिए एक टाइपिंग पॉइंटर है। बहुत निम्न-स्तर और बहुत बदसूरत और बहुत त्रुटि-प्रवण। एक अशक्त वस्तु भी बहुत भ्रामक है यहाँ मुझे लगता है। एक अशक्त ग्राहक एक ग्राहक है। यह एक की अनुपस्थिति नहीं है, यह उस आईडी के साथ ग्राहक नहीं है जिसके लिए कहा गया है, इसलिए इसे वापस करना बस गलत है। यह वह ग्राहक नहीं है जिसके लिए मैंने पूछा था, लेकिन फिर भी आप दावा करते हैं कि आपने एक ग्राहक को लौटा दिया है। इसमें गलत आईडी है, स्पष्ट रूप से यह एक बग है। यह विधि के नाम और हस्ताक्षर द्वारा सुझाए गए अनुबंध को तोड़ता है। इसके लिए क्लाइंट कोड की आवश्यकता होती है कि वह आपके डिज़ाइन के बारे में बातें कर सके, या डॉक्यूमेंटेशन पढ़ सके।

इन दोनों मुद्दों को एक द्वारा हल किया जाता है Maybe Customer। अचानक, हम यह नहीं कह रहे हैं "यह फ़ंक्शन दिए गए आईडी के साथ ग्राहक का प्रतिनिधित्व करता है"। हम कह रहे हैं "यह फ़ंक्शन दिए गए आईडी के साथ ग्राहक का प्रतिनिधित्व करता है यदि यह मौजूद है । यह अब बहुत स्पष्ट और स्पष्ट है कि यह क्या करता है। यदि आप गैर-मौजूदा आईडी वाले ग्राहक से पूछते हैं, तो आपको प्राप्त होगा Nothing। यह कैसे बेहतर है। की तुलना में, nullन केवल एनपीई जोखिम के लिए। बल्कि इसलिए भी कि प्रकार Nothingकेवल इसलिए नहीं है Maybe। इसका Maybe Customerअर्थ अर्थ है। इसका विशेष रूप से अर्थ है "ग्राहक की अनुपस्थिति", यह दर्शाता है कि ऐसा ग्राहक मौजूद नहीं है।

अशक्त के साथ एक और समस्या यह है कि यह अस्पष्ट है। क्या यह है कि आपको ग्राहक नहीं मिला, या क्या कोई db कनेक्शन त्रुटि थी या क्या मुझे अभी उस ग्राहक को देखने की अनुमति नहीं है?

यदि आपके पास इसे संभालने के लिए कई त्रुटि मामले हैं, तो आप या तो उन संस्करणों के लिए अपवाद फेंक सकते हैं (या मैं इस तरह से पसंद करता हूं) आप एक वापसी कर सकते हैं Either CustomerLoadError Customer, या तो कुछ का प्रतिनिधित्व कर सकते हैं जो गलत हो गया है या ग्राहक लौटा है। इसके सभी फायदे हैं Maybe Customerजबकि आपको यह निर्दिष्ट करने की अनुमति देता है कि क्या गलत हो सकता है।

मुख्य बात यह है कि मैं समारोह में अनुबंध पर हस्ताक्षर करने के लिए है। चीजों को ग्रहण न करें, क्षणभंगुर सम्मेलनों पर भरोसा न करें, स्पष्ट रहें।


0

1) यदि फ़ंक्शन का शब्दार्थ यह है कि यह कुछ भी नहीं लौटा सकता है, तो इसके लिए कॉलर MUST परीक्षण करना होगा, अन्यथा वह उदा। अपना पैसा ले लो और इसे किसी को न दें।

2) अपने कार्यों को करने के लिए अच्छा है कि शब्दार्थ हमेशा कुछ (या फेंक) लौटाता है।

एक लकड़हारे के साथ , यह लकड़हारा लौटने के लिए समझ में आता है जो लकड़हारा परिभाषित नहीं होने पर लॉग नहीं करता है। संग्रह लौटाते समय, यह लगभग कभी भी समझ में नहीं आता ("निम्न पर्याप्त स्तर पर छोड़कर), जहां संग्रह स्वयं ही डेटा है, न कि इसमें क्या है) कुछ भी नहीं लौटाने के लिए, क्योंकि एक खाली सेट एक सेट है, कुछ भी नहीं।

एक व्यक्ति के उदाहरण के साथ, मैं "हाइबरनेट" तरीके (बनाम लोड, IIRC प्राप्त करता हूं, लेकिन वहाँ दो कार्यों के आलसी लोडिंग के लिए प्रॉक्सी ऑब्जेक्ट द्वारा जटिल है), एक जो अशक्त और दूसरा जो वापस फेंकता है।


-1
  • यदि आवेदन डेटा उपलब्ध होने की अपेक्षा करता है, तो NULL को लौटाया जाना चाहिए, लेकिन डेटा उपलब्ध नहीं है। उदाहरण के लिए, एक सेवा जो शहर को नहीं मिली है, तो zipcode के आधार पर CITY लौटाती है। कॉलर तब नल को संभालने या उड़ाने का निर्णय ले सकता है।

  • यदि दो संभावनाएँ हैं तो खाली सूची को लौटाया जाना चाहिए। उपलब्ध डेटा या कोई डेटा उपलब्ध नहीं है। उदाहरण के लिए एक सेवा जो CITY (s) को लौटाती है यदि जनसंख्या निश्चित संख्या से अधिक है। यह एक खाली सूची वापस कर सकता है यदि कोई डेटा जो दिए गए मानदंडों को पूरा नहीं करता है।


-2

वस्तु-उन्मुख दुनिया में NULL का लौटना एक भयानक डिजाइन है। संक्षेप में, NULL उपयोग की ओर जाता है:

  • तदर्थ त्रुटि से निपटने (अपवादों के बजाय)
  • अस्पष्ट शब्दार्थ
  • तेजी से असफल होने के बजाय धीमा
  • कंप्यूटर सोच बनाम वस्तु सोच
  • उत्परिवर्तनीय और अपूर्ण वस्तुएं

विस्तृत विवरण के लिए इस ब्लॉग पोस्ट को देखें : http://www.yegor256.com/2014/05/13/why-null-is-bad.html

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