क्या कार्यों को शून्य या एक खाली वस्तु वापस करनी चाहिए?


209

फ़ंक्शन से डेटा वापस करते समय सबसे अच्छा अभ्यास क्या है । क्या किसी नल या खाली वस्तु को वापस करना बेहतर है? और एक को दूसरे पर क्यों करना चाहिए?

इस पर विचार करो:

public UserEntity GetUserById(Guid userId)
{
     //Imagine some code here to access database.....

     //Check if data was returned and return a null if none found
     if (!DataExists)
        return null; 
        //Should I be doing this here instead? 
        //return new UserEntity();  
     else
        return existingUserEntity;
}

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


4
मुझे लगता है कि आपका मतलब है if (!DataExists)
सारा वेसल्स

107
यह एक वास्तुशिल्प प्रश्न है और पूरी तरह से उचित है। ओपी का प्रश्न उस व्यावसायिक समस्या के बावजूद मान्य है जिसे हल करने का प्रयास किया जा रहा है।
जोसेफ फेरिस

2
इस प्रश्न का पहले ही पर्याप्त उत्तर दिया जा चुका है। मुझे लगता है कि यह एक बहुत ही दिलचस्प सवाल है।
जॉन स्किपिओन

'getUser ()' को अशक्त होना चाहिए। 'getCurrentUserInfo ()' या 'getCurrentPien ()', OTOH, से अधिक चौकाने वाले प्रश्न होंगे - उन्हें गैर-अशक्त उत्तर देने वाली वस्तु को वापस करना चाहिए, भले ही कोई भी व्यक्ति जो / या लॉग इन है,
थॉमस डब्ल्यू

2
नहीं @Bergi दूसरे एक डुप्लिकेट है। मेरा पहले पूछा गया था, अक्टूबर में, दूसरे को 3 पतंगे बाद में दिसंबर में पूछा गया था। साथ ही अन्य एक संग्रह के बारे में बात करता है जो थोड़ा अलग है।
7wp

जवाबों:


207

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

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

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


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

130
@ क्रिस: मैं असहमत हूं। यदि कोड स्पष्ट रूप से दस्तावेज देता है कि वापसी मूल्य शून्य है, तो यह पूरी तरह से स्वीकार्य है कि यदि कोई परिणाम आपके मानदंडों से मेल नहीं खाता है, तो वह अशक्त है। एक अपवाद को फेंकना आपकी अंतिम पसंद होना चाहिए, न कि आपका पहला।
1892 में माइक हॉफर

12
@ क्रिस: आप यह किस आधार पर तय करते हैं? समीकरण में लॉगिंग जोड़ना निश्चित रूप से अत्यधिक लगता है। उपभोगकर्ता कोड को यह तय करने दें कि क्या - अगर कुछ भी - बिना उपयोगकर्ता के मामले में किया जाना चाहिए। मेरी पिछली टिप्पणी के रूप में, मान को लौटाए जाने के साथ कोई समस्या नहीं है जिसे सार्वभौमिक रूप से "कोई डेटा नहीं" के रूप में परिभाषित किया गया है।
एडम रॉबिन्सन

17
मैं थोड़ा चकित हूं कि एक Microsoft डेवलपर का मानना ​​है कि "लौटने वाला अशक्त" समस्या को निगलने के लिए समान है। यदि मेमोरी कार्य करती है, तो फ्रेमवर्क में टन विधियाँ हैं जहाँ विधियों को वापस कर दिया जाता है यदि कॉलर के अनुरोध से मेल नहीं खाता है। कि "समस्या निगल रहा है?"
माइक हॉफ़र

5
अंतिम लेकिन कम से कम ऐसा नहीं होगा bool GetUserById(Guid userId, out UserEntity result)- जिसे मैं "अशक्त" रिटर्न-वैल्यू के लिए पसंद करूंगा, और जो अपवाद को फेंकने के रूप में चरम पर नहीं है। यह सुंदर- nullमुक्त कोड की तरह अनुमति देता है if(GetUserById(x,u)) { ... }
मार्सेल जैकवर्थ

44

यह इस बात पर निर्भर करता है कि आपके मामले के लिए सबसे अधिक समझ में क्या आता है।

क्या यह अशक्त करने के लिए समझ में आता है, उदाहरण के लिए "ऐसा कोई उपयोगकर्ता मौजूद नहीं है"?

या क्या यह डिफ़ॉल्ट उपयोगकर्ता बनाने के लिए समझ में आता है? यह सबसे अधिक समझ में आता है जब आप सुरक्षित रूप से मान सकते हैं कि यदि कोई उपयोगकर्ता मौजूद नहीं है, तो कॉलिंग कोड एक के लिए मौजूद है जब वे इसके लिए पूछते हैं।

या क्या यह एक अपवाद (एक ला "FileNotFound") को फेंकने के लिए समझ में आता है अगर कॉलिंग कोड एक अमान्य आईडी वाले उपयोगकर्ता की मांग कर रहा है?

हालांकि - चिंताओं / एसआरपी के दृष्टिकोण के एक अलगाव से, पहले दो अधिक सही हैं। और तकनीकी रूप से पहला सबसे सही है (लेकिन केवल एक बाल द्वारा) - GetUserById केवल एक चीज के लिए जिम्मेदार होना चाहिए - उपयोगकर्ता को प्राप्त करना। अपने स्वयं के "उपयोगकर्ता मौजूद नहीं है" मामले को संभालकर कुछ और वापस करना एसआरपी का उल्लंघन हो सकता है। bool DoesUserExist(id)यदि आप अपवाद फेंकना चुनते हैं, तो एक अलग चेक में अलग करना उचित होगा।

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

सभी दृष्टिकोण स्वीकार्य हैं - यह सिर्फ एपीआई / एप्लिकेशन के बड़े संदर्भ के आधार पर निर्भर करता है।


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

(मैं अनुमान लगा रहा हूं कि इस तरह की परिस्थिति में एक अपवाद को फेंकने के विचार पर आपत्ति थी।)
जैकब मैटीसन

1
अपने अंतिम बिंदु तक सहमत हैं। एक मूल्य को लौटाते हुए SRP का कोई उल्लंघन नहीं है जिसे सार्वभौमिक रूप से "कोई डेटा नहीं" के रूप में परिभाषित किया गया है। यह बताते हुए कि एसक्यूएल डेटाबेस को एक त्रुटि वापस करना चाहिए यदि कोई क्लॉज कोई परिणाम नहीं देता है। हालांकि एक अपवाद एक वैध डिजाइन विकल्प है (हालांकि एक ऐसा जो मुझे एक उपभोक्ता के रूप में परेशान करेगा), यह पतले लौटने की तुलना में कोई "अधिक सही" नहीं है। और नहीं, मैं नहीं हूँ DV।
एडम रॉबिन्सन

@JacobM हम अपवादों को फेंकते हैं जब हम एक फाइलसिस्टम पथ की मांग करते हैं जो मौजूद नहीं है, वापस नहीं आता है, लेकिन डेटाबेस से नहीं। तो स्पष्ट रूप से दोनों उपयुक्त हैं, जो कि मुझे मिल रहा है - यह सिर्फ निर्भर करता है।
रेक्स एम

2
@Charles: आप इस सवाल का जवाब दे रहे हैं "कुछ बिंदु पर एक अपवाद को फेंक दिया जाना चाहिए", लेकिन सवाल यह है कि "इस फ़ंक्शन को अपवाद को फेंक देना चाहिए"। सही उत्तर "शायद" है, "हाँ" नहीं।
एडम रॉबिन्सन

30

व्यक्तिगत रूप से, मैं NULL का उपयोग करता हूं। यह स्पष्ट करता है कि लौटने के लिए कोई डेटा नहीं है। लेकिन ऐसे मामले हैं जब एक अशक्त वस्तु उपयोगी हो सकती है।


बस एक उत्तर के रूप में इसे जोड़ने के बारे में। NullObjectPattern या विशेष केस पैटर्न। फिर आप प्रत्येक मामले के लिए एक लागू कर सकते हैं, NoUserEntitiesFound, NullUserEntities आदि
डेविड

27

यदि आपकी वापसी प्रकार एक सरणी है तो एक खाली सरणी वापस लौटाएं अन्यथा रिक्त करें।


क्या किसी सूची में 0 आइटम इस समय अप्रकाशित सूची के समान हैं?
एंथनीवजोन

3
किसी सूची में 0 आइटम समान नहीं हैं null। यह आपको foreachबिना किसी चिंता के बयानों और लाइनक प्रश्नों में इसका उपयोग करने की अनुमति देता है NullReferenceException
डारिन दिमित्रोव 19

5
मुझे आश्चर्य है कि यह अधिक नहीं उत्कीर्ण किया गया है। यह मेरे लिए एक बहुत ही उचित दिशानिर्देश की तरह लगता है।
शशि

खैर, खाली कंटेनर नल ऑब्जेक्ट पैटर्न का सिर्फ एक विशिष्ट उदाहरण है। जो उपयुक्त हो सकता है, हम नहीं बता सकते।
डेडुप्लिकेटर

जब डेटा उपलब्ध नहीं है तो एक खाली सरणी लौटना बस गलत है । उपलब्ध डेटा और कोई आइटम नहीं होने और डेटा उपलब्ध नहीं होने के बीच एक अंतर है। दोनों मामलों में एक खाली सरणी वापस करने से यह जानना असंभव हो जाता है कि कौन सा मामला है। यह कर सिर्फ इसलिए आप देखना हो डेटा भी मौजूद है मूर्खतापूर्ण से परे है बिना एक foreach उपयोग कर सकते हैं - फोन करने वाले चाहिए जाँच करने के लिए डेटा मौजूद है और एक NullReferenceException है कि क्या करता है, तो फोन करने वाले करता नहीं जांच है अच्छा है क्योंकि यह एक बग को उजागर करता है ..
मोनिका

12

आपको एक अपवाद फेंकना चाहिए (केवल) यदि कोई विशिष्ट अनुबंध टूट गया है।
आपके विशिष्ट उदाहरण में, किसी ज्ञात आईडी के आधार पर UserEntity के लिए पूछना, यह इस तथ्य पर निर्भर करेगा कि क्या लापता (हटाए गए) उपयोगकर्ता एक अपेक्षित मामला है। यदि ऐसा है, तो वापस लौटें nullलेकिन यदि यह अपेक्षित मामला नहीं है तो एक अपवाद फेंक दें।
ध्यान दें कि यदि फ़ंक्शन को कॉल UserEntity GetUserByName(string name)किया गया था, तो वह संभवत: फेंक नहीं देगा, लेकिन अशक्त हो जाएगा। दोनों मामलों में एक खाली UserEntity वापस करना अनपेक्षित होगा।

स्ट्रिंग, सरणियों और संग्रह के लिए स्थिति आमतौर पर अलग होती है। मुझे याद है कि कुछ दिशानिर्देश फॉर्म एमएस हैं जो विधियों nullको एक 'खाली' सूची के रूप में स्वीकार करना चाहिए, लेकिन शून्य-लंबाई के बजाय वापसी संग्रह null। तार के लिए भी यही। ध्यान दें कि आप खाली सारणी घोषित कर सकते हैं:int[] arr = new int[0];


खुशी है कि आपने उल्लेख किया है कि तार अलग हैं, क्योंकि Google ने मुझे यह दिखाया था जब मैं यह तय कर रहा था कि क्या एक खाली स्ट्रिंग वापस करना है।
नूमेनन

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

1
आप बिंदु और संदर्भ को याद करने लगते हैं। .Wher(p => p.Lastname == "qwerty")एक खाली संग्रह लौटना चाहिए, नहीं null
हेनक होल्टरमैन

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

11

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

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

यदि कोई लापता उपयोगकर्ता ठीक है, (इस फ़ंक्शन को कॉल करने के संभावित सामान्य परिणामों में से एक है) तो एक अशक्त वापसी करें ...।

संपादित करें: (एक अन्य उत्तर में एडम से टिप्पणी को संबोधित करने के लिए)

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

लेकिन अगर आवेदन के भीतर सभी प्रक्रियाओं के लिए एक उपयोगकर्ता की आवश्यकता होती है, तो भी मैं इस पद्धति में अपवाद को फेंक दूंगा ...


-1 से डाउनवॉटर, +1 से चार्ल्स - यह पूरी तरह से एक व्यावसायिक प्रश्न है और इसके लिए कोई सर्वोत्तम अभ्यास नहीं है।
ऑस्टिन सलोनन

यह धाराओं को पार कर रहा है। व्यापार तर्क द्वारा संचालित "त्रुटि स्थिति" है या नहीं। कैसे संभालना है कि एक आवेदन वास्तुकला निर्णय है। व्यापार तर्क यह बताने के लिए नहीं जा रहा है कि एक अशक्त लौटाया जाए, बस यह कि आवश्यकताओं को संतुष्ट किया जाए। यदि व्यवसाय विधि रिटर्न प्रकार तय कर रहा है, तो वे कार्यान्वयन के तकनीकी पहलू में भी शामिल हैं।
जोसेफ फेरिस

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

10

मैं व्यक्तिगत रूप से अशक्त हो जाएगा, क्योंकि मैं कैसे DAL / रिपोजिटरी परत से कार्य करने की उम्मीद करूंगा।

यदि यह मौजूद नहीं है, तो ऐसी किसी भी चीज़ को वापस न करें जो किसी वस्तु को सफलतापूर्वक लाने के रूप में माना जा सकता है, nullयहाँ खूबसूरती से काम करता है।

सबसे महत्वपूर्ण बात यह है कि आपके DAL / Repos Layer में निरंतरता हो, इस तरह से आप भ्रमित न हों कि इसका उपयोग कैसे करें।


7

मैं इसके लिए अभिमुख हूं

  • return nullयदि ऑब्जेक्ट आईडी मौजूद नहीं है, तो यह पहले से ज्ञात नहीं है कि क्या इसका अस्तित्व होना चाहिए
  • throwयदि ऑब्जेक्ट आईडी मौजूद नहीं है, तो यह मौजूद होना चाहिए

मैं इन तीन प्रकार के तरीकों के साथ इन दो परिदृश्यों को अलग करता हूं। प्रथम:

Boolean TryGetSomeObjectById(Int32 id, out SomeObject o)
{
    if (InternalIdExists(id))
    {
        o = InternalGetSomeObject(id);

        return true;
    }
    else
    {
        return false;
    }
}

दूसरा:

SomeObject FindSomeObjectById(Int32 id)
{
    SomeObject o;

    return TryGetObjectById(id, out o) ? o : null;
}

तीसरा:

SomeObject GetSomeObjectById(Int32 id)
{
    SomeObject o;

    if (!TryGetObjectById(id, out o))
    {
        throw new SomeAppropriateException();
    }

    return o;
}

आपका मतलब outनहीं हैref
मैट एलेन

@ मैट: हाँ, सर, मैं सबसे निश्चित रूप से करता हूँ! फिक्स्ड।
जोहान जेरेल

2
वास्तव में, यह केवल एक आकार-फिट-सभी जवाब है, और इसलिए पूरी तरह से और पूरी तरह से सच है! :) हाँ, यह उन मान्यताओं पर निर्भर करता है जिनके आधार पर विधि को लागू किया जाता है ... इसलिए पहले इन मान्यताओं को स्पष्ट करें और फिर ऊपर के सही संयोजन को चुनें। यहाँ तक पहुँचने के लिए बहुत नीचे स्क्रॉल करना पड़ा :) +100
yair

यह उपयोग करने के लिए पैटर्न लगता है, सिवाय इसके कि यह async विधियों का समर्थन नहीं करता है। मैंने इस उत्तर को संदर्भित किया और टुपल लिटरल्स के साथ एक async समाधान जोड़ा -> यहाँ
ttugates

6

फिर भी एक अन्य दृष्टिकोण में कॉलबैक ऑब्जेक्ट या प्रतिनिधि को पास करना शामिल है जो मूल्य पर काम करेगा। यदि कोई मान नहीं मिला है, तो कॉलबैक नहीं कहा जाता है।

public void GetUserById(Guid id, UserCallback callback)
{
    // Lookup user
    if (userFound)
        callback(userEntity);  // or callback.Call(userEntity);
}

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

public void GetUserById(Guid id, UserCallback callback, NotFoundCallback notFound)
{
    // Lookup user
    if (userFound)
        callback(userEntity);  // or callback.Call(userEntity);
    else
        notFound(); // or notFound.Call();
}

किसी एकल ऑब्जेक्ट का उपयोग करने वाला एक ही दृष्टिकोण ऐसा लग सकता है:

public void GetUserById(Guid id, UserCallback callback)
{
    // Lookup user
    if (userFound)
        callback.Found(userEntity);
    else
        callback.NotFound();
}

एक डिजाइन के नजरिए से, मैं वास्तव में इस दृष्टिकोण को पसंद करता हूं, लेकिन कॉल साइट को उन भाषाओं में बल्कियर बनाने का नुकसान है जो आसानी से क्लास के कार्यों का समर्थन नहीं करते हैं।


दिलचस्प। जब आपने प्रतिनिधियों के बारे में बात करना शुरू किया, तो मैंने तुरंत सोचना शुरू कर दिया कि क्या लैम्बडा के भावों का उपयोग यहां किया जा सकता है।
7wp

हाँ! जैसा कि मैं इसे समझता हूं, C # 3.0 और ऊपर का लंबो सिंटैक्स मूल रूप से अनाम प्रतिनिधियों के लिए वाक्य रचना चीनी है। इसी तरह जावा में, अच्छे लैम्ब्डा या अनाम प्रतिनिधि सिंटैक्स के बिना, आप बस एक अनाम वर्ग बना सकते हैं। यह थोड़ा बदसूरत है, लेकिन वास्तव में आसान हो सकता है। मुझे लगता है कि इन दिनों, मेरे C # उदाहरण में Func <UserEntity> या किसी नामित प्रतिनिधि के बजाय ऐसा कुछ इस्तेमाल किया जा सकता था, लेकिन अंतिम C # प्रोजेक्ट जो मैं अभी भी कर रहा था, संस्करण 2 का उपयोग कर रहा था
मार्क

+1 मुझे यह तरीका पसंद है। हालांकि एक समस्या यह है कि यह पारंपरिक नहीं है और कोडबेस के लिए प्रवेश की बाधा को थोड़ा बढ़ाता है।
टिमोक्सले

4

हम CSLA.NET का उपयोग करते हैं, और यह विचार करता है कि एक असफल डेटा भ्रूण को एक "खाली" ऑब्जेक्ट वापस करना चाहिए। यह वास्तव में काफी कष्टप्रद है, क्योंकि यह जाँचने की परंपरा की मांग करता है कि क्या obj.IsNewइससे अधिक कठोर है obj == null

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

व्यक्तिगत रूप से, मुझे लगता nullहै कि अधिक सुरुचिपूर्ण है।

यह एक बहुत ही सामान्य मामला है, और मुझे आश्चर्य है कि यहां के लोग इसे देखकर आश्चर्यचकित हैं: किसी भी वेब एप्लिकेशन पर, डेटा को अक्सर एक querystring पैरामीटर का उपयोग करके लाया जाता है, जिसे जाहिर तौर पर मंगवाया जा सकता है, इसलिए यह आवश्यक है कि डेवलपर हैंडल "के प्रमाण को न पाए।" "।

आप इसे संभाल सकते हैं:

अगर (User.Exists (id)) {
  this.User = User.Fetch (id);
} अन्य {
  Response.Redirect ( "~ / notfound.aspx");
}

... लेकिन यह हर बार डेटाबेस के लिए एक अतिरिक्त कॉल है, जो उच्च-ट्रैफ़िक पृष्ठों पर एक समस्या हो सकती है। जहाँ तक:

this.User = User.Fetch (id);

अगर (यह। == नल) {
  Response.Redirect ( "~ / notfound.aspx");
}

... केवल एक कॉल की आवश्यकता है।


4

मैं पसंद करता हूं null, क्योंकि यह अशक्त-संचालक ऑपरेटर ( ??) के साथ संगत है ।


4

मैं कहूंगा कि एक खाली वस्तु के बजाय वापसी।

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

यह वह नियम है जिसका मैं आमतौर पर पालन करता हूं:

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

आप इनमें से किसी भी मामले में अपवाद क्यों फेंकेंगे? कभी-कभी उपयोगकर्ता डेटाबेस में मौजूद नहीं होते हैं, और हम उम्मीद करते हैं कि ऐसा न हो। यह असाधारण व्यवहार नहीं है।
१18

3

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

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


+1 मैं उसी तर्क पर सवाल कर रहा था जो आप यहां कह रहे हैं, यही वजह है कि मैंने यह देखने के लिए यह सवाल पोस्ट किया कि इस बारे में अन्य लोगों की क्या राय होगी
7wp

3

इस मामले में सबसे अच्छा एक मामले में "अशक्त" वापस लौटाएं ऐसा कोई उपयोगकर्ता नहीं है। साथ ही अपने तरीके को स्थिर बनाएं।

संपादित करें:

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


क्या मैं पूछ सकता हूं कि मैं अपनी पद्धति को स्थिर क्यों बनाना चाहूंगा? क्या होगा अगर मैं डिपेंडेंसी इंजेक्शन का उपयोग करना चाहता हूं?
7wp

ठीक है अब मुझे आपका तर्क मिल गया। लेकिन मैं रिपॉजिटरी पैटर्न के साथ रहता हूं, और मुझे अपनी रिपॉजिटरी के लिए निर्भरता इंजेक्शन का उपयोग करना पसंद है इसलिए मैं स्थैतिक तरीकों का उपयोग नहीं कर सकता। लेकिन null लौटाने के सुझाव के लिए +1 :)
7wp

3

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

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


+1 मुझे समस्या का वैकल्पिक दृष्टिकोण पसंद है। तो मूल रूप से आप कह रहे हैं कि मैं जो भी दृष्टिकोण चुनता हूं वह तब तक ठीक होना चाहिए जब तक विधि पूरे अनुप्रयोग के अनुरूप हो?
7wp

1
यही मेरा विश्वास है। मुझे लगता है कि निरंतरता बेहद जरूरी है। यदि आप कई स्थानों पर कई तरीके से काम करते हैं, तो यह नए बग के लिए एक उच्च जोखिम का परिचय देता है। हम व्यक्तिगत रूप से डिफ़ॉल्ट ऑब्जेक्ट दृष्टिकोण के साथ चले गए हैं, क्योंकि यह सार पैटर्न के साथ अच्छी तरह से काम करता है जो हम अपने डोमेन मॉडल में उपयोग करते हैं। हमारे पास एक एकल सामान्य विस्तार विधि है जिसे हम सभी डोमेन ऑब्जेक्ट्स के खिलाफ परीक्षण कर सकते हैं ताकि हमें यह पता चल सके कि यह आबादी है या नहीं, ताकि हम यह जान सकें कि किसी भी DO को objectname.IsDefault () के कॉल के साथ परीक्षण किया जा सकता है - किसी भी समानता की जाँच से सीधे बचना ।
जोसेफ फेरिस

3

हमारी व्यावसायिक वस्तुओं में हमारे पास 2 मुख्य तरीके हैं:

संदर्भ में चीजों को सरल रखने के लिए या आप सवाल करते हैं:

// Returns null if user does not exist
public UserEntity GetUserById(Guid userId)
{
}

// Returns a New User if user does not exist
public UserEntity GetNewOrExistingUserById(Guid userId)
{
}

विशिष्ट विधियों को प्राप्त करते समय पहली विधि का उपयोग किया जाता है, दूसरी विधि का उपयोग विशेष रूप से वेब पृष्ठों पर संस्थाओं को जोड़ने या संपादित करते समय किया जाता है।

यह हमें उस संदर्भ में दोनों दुनिया के सर्वश्रेष्ठ होने में सक्षम बनाता है जहां उनका उपयोग किया जाता है।


3

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

जावा का उपयोग करते हुए, हमें assert exists(object) : "You shouldn't try to access an object that doesn't exist";किसी भी विधि की शुरुआत में जोड़ने के लिए कहा जाता है जो अशक्त हो सकता है, "पूर्व शर्त" (मैं नहीं जानता कि अंग्रेजी में शब्द क्या है) को व्यक्त करने के लिए।

IMO यह वास्तव में उपयोग करने के लिए आसान नहीं है, लेकिन यही मैं उपयोग कर रहा हूं, कुछ बेहतर के लिए इंतजार कर रहा है।


1
आपके उत्तर के लिए धन्यवाद। लेकिन मैं जाँच के विचार को नापसंद करता हूँ अगर वह मौजूद है। कारण यह है कि डेटाबेस के लिए एक अतिरिक्त क्वेरी उत्पन्न करता है। एक एप्लिकेशन में एक दिन में लाखों लोगों द्वारा एक्सेस किया जा रहा है, जिसके परिणामस्वरूप नाटकीय प्रदर्शन हानि हो सकती है।
7wp

1
एक लाभ यह है कि अस्तित्व के लिए जाँच उचित रूप से सार है: यदि (userExists) थोड़ा अधिक पठनीय है, समस्या डोमेन के करीब है, और इससे कम 'कम्प्यूटरी': if (user == null)
timoxley

और मैं तर्क दूंगा कि 'अगर (x == null)' एक दशकों पुराना पैटर्न है, जिसे आपने पहले नहीं देखा है, तो आपने बहुत लंबे समय तक कोड नहीं लिखा है (और आपको इसकी आदत होनी चाहिए जैसी कि यह है कोड की लाखों)। "Computery"? हम डेटाबेस एक्सेस के बारे में बात कर रहे हैं ...
लॉयड सार्जेंट

3

यदि उपयोगकर्ता का नहीं पाया जा रहा मामला अक्सर पर्याप्त होता है, और आप परिस्थितियों के आधार पर विभिन्न तरीकों से उससे निपटना चाहते हैं (कभी-कभी एक अपवाद को फेंकते हुए, कभी-कभी एक खाली उपयोगकर्ता को प्रतिस्थापित करते हुए) आप F # के Optionया Haskell के Maybeप्रकार के करीब कुछ का उपयोग कर सकते हैं , जो स्पष्ट रूप से 'कुछ पाया' से 'कोई मूल्य नहीं' मामले को अलग करता है। डेटाबेस एक्सेस कोड इस तरह दिख सकता है:

public Option<UserEntity> GetUserById(Guid userId)
{
 //Imagine some code here to access database.....

 //Check if data was returned and return a null if none found
 if (!DataExists)
    return Option<UserEntity>.Nothing; 
 else
    return Option.Just(existingUserEntity);
}

और इस तरह इस्तेमाल किया जा सकता है:

Option<UserEntity> result = GetUserById(...);
if (result.IsNothing()) {
    // deal with it
} else {
    UserEntity value = result.GetValue();
}

दुर्भाग्य से, हर कोई अपने स्वयं के इस तरह के रोल करने के लिए लगता है।


2

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


2

संग्रह प्रकारों के लिए मैं एक खाली संग्रह लौटाऊंगा, अन्य सभी प्रकारों के लिए मैं एक ऑब्जेक्ट को वापस करने के लिए NullObject पैटर्न का उपयोग करना पसंद करता हूं जो कि लौटने वाले प्रकार के समान इंटरफ़ेस को लागू करता है। पैटर्न के बारे में जानकारी के लिए लिंक टेक्स्ट देखें

NullObject पैटर्न का उपयोग करना यह होगा: -

public UserEntity GetUserById(Guid userId)

{// डेटाबेस तक पहुंचने के लिए यहां कुछ कोड की कल्पना करें .....

 //Check if data was returned and return a null if none found
 if (!DataExists)
    return new NullUserEntity(); //Should I be doing this here instead? return new UserEntity();  
 else
    return existingUserEntity;

}

class NullUserEntity: IUserEntity { public string getFirstName(){ return ""; } ...} 

2

दूसरों ने जो कुछ कहा है, उसे पूरी तरह से करने के लिए ...

अपवाद असाधारण परिस्थितियों के लिए हैं

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

दूसरी ओर, अगर मुझे उम्मीद थी कि मेरा पैरामीटर प्राथमिक कुंजी को प्रतिबिंबित करेगा और मुझे केवल एक पंक्ति वापस मिलनी चाहिए , अगर मुझे एक से अधिक वापस मिला तो मैं एक अपवाद फेंक दूंगा। ० नल को वापस करना ठीक है, २ नहीं है।

अब, अगर मेरे पास कुछ लॉगिन कोड होता है जो एक LDAP प्रदाता के खिलाफ जाँच करता है तो अधिक विवरण प्राप्त करने के लिए DB के खिलाफ जाँच करता है और मुझे उम्मीद है कि हर समय सिंक में होना चाहिए, मैं तब अपवाद को टॉस कर सकता हूं। जैसा कि अन्य लोगों ने कहा, यह व्यावसायिक नियम हैं।

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


2

मेरे छद्म php / कोड को क्षमा करें।

मुझे लगता है कि यह वास्तव में परिणाम के इच्छित उपयोग पर निर्भर करता है।

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

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

उदाहरण:

function saveTheRow($prim_key, $data) {
    $row = getRowByPrimKey($prim_key);

    // Populate the data here

    $row->save();
}

यहां हम देख सकते हैं कि एक ही श्रृंखला के संचालन इस प्रकार के सभी रिकॉर्डों में हेरफेर करते हैं।

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

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

उदाहरण:

function displayData($row_id) {
    // Logging of the error would happen in this function
    $row = getRow($row_id);
    if($row === null) {
        // Handle the error here
    }

    // Do stuff here with data
}

function getRow($row_id) {
 $row = null;
 try{
     if(!$db->connected()) {
   throw excpetion("Couldn't Connect");
  }

  $result = $db->query($some_query_using_row_id);

  if(count($result) == 0 ) {
   throw new exception("Couldn't find a record!");
  }

  $row = $db->nextRow();

 } catch (db_exception) {
  //Log db conn error, alert admin, etc...
  return null; // This way I know that null means an error occurred
 }
 return $row;
}

यही मेरा सामान्य नियम है। यह अब तक अच्छा काम किया है।


2

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

हो सकता है कि नल-वापसी के तरीकों से फेंकने के तरीकों को अलग करने के लिए एक अच्छा तरीका है अपनी टीम में एक कन्वेंशन ढूंढना: वे विधियाँ जो कहती हैं कि "प्राप्त" कुछ अपवाद को फेंक देना चाहिए अगर पाने के लिए कुछ भी नहीं है। वे विधियाँ जो अशक्त हो सकती हैं, को अलग नाम दिया जा सकता है, शायद "ढूँढें ..." के बजाय।


+1 मुझे प्रोग्रामर को संकेत देने के लिए एक समान नामकरण सम्मेलन का उपयोग करने का विचार पसंद है कि उस फ़ंक्शन का उपभोग कैसे किया जाए।
7wp

1
अचानक मैं पहचानता हूं कि यह वही है जो LINQ करता है: पहले विचार (...) बनाम FirstOrDefault (...)
मार्क विटके

2

यदि दी गई वस्तु कुछ ऐसी है, जो इससे अधिक पुनरावृत्त हो सकती है, तो मैं एक खाली वस्तु लौटाऊंगा, ताकि मुझे पहले अशक्त के लिए परीक्षण न करना पड़े।

उदाहरण:

bool IsAdministrator(User user)
{
    var groupsOfUser = GetGroupsOfUser(user);

    // This foreach would cause a run time exception if groupsOfUser is null.
    foreach (var groupOfUser in groupsOfUser) 
    {
        if (groupOfUser.Name == "Administrators")
        {
            return true;
        }
    }

    return false;
}

2

मुझे किसी भी विधि से अशक्त नहीं लौटना पसंद है, बल्कि विकल्प कार्यात्मक प्रकार का उपयोग करना है। ऐसे तरीके जो बिना नतीजे के वापस आ सकते हैं, खाली विकल्प लौटा सकते हैं, बजाय शून्य के।

इसके अलावा, ऐसे तरीके जो बिना परिणाम लौटा सकते हैं, उनके नाम के माध्यम से इंगित करना चाहिए। मैं आमतौर पर यह बताने के लिए कि विधि खाली है (जैसे TryFindCustomer, TryLoadFile, आदि) वापस आ सकती है, यह जानने के लिए कि विधि के नाम की शुरुआत में ट्राई या ट्राईगेट या ट्राइफ़ंड डाल दें।

यह कॉलर को विभिन्न तकनीकों को लागू करने देता है, जैसे संग्रह पाइपलाइनिंग (मार्टिन फाउलर का संग्रह पाइपलाइन देखें) परिणाम पर ) देखें।

यहां एक और उदाहरण दिया गया है जहां null के बजाय रिटर्निंग ऑप्शन का उपयोग कोड जटिलता को कम करने के लिए किया जाता है: साइक्लोमैटिक कॉम्प्लेक्सिटी को कैसे कम करें: कार्यात्मक प्रकार


1
मैंने एक उत्तर लिखा है, मैं देख सकता हूं कि यह आपके जैसा है जैसा कि मैंने स्क्रॉल किया है, और मैं सहमत हूं, आप 0 या 1 तत्वों के साथ एक सामान्य संग्रह के साथ एक विकल्प प्रकार को लागू कर सकते हैं। अतिरिक्त लिंक के लिए धन्यवाद।
गेब्रियल पी।

1

अधिक मांस को पीसने के लिए: मान लीजिए कि मेरे DAL ने GetPersonByID के लिए NULL लौटाया, जैसा कि कुछ ने सलाह दी है। यदि इसे NULL प्राप्त होता है, तो मुझे (बल्कि पतले) BLL क्या करना चाहिए? उस NULL को पास करें और अंतिम उपभोक्ता को इसके बारे में चिंता करने दें (इस मामले में, ASP.Net पेज)? कैसे बीएलएल एक अपवाद फेंकने के बारे में?

BLL का उपयोग ASP.Net और Win App या किसी अन्य श्रेणी के पुस्तकालय द्वारा किया जा सकता है - मुझे लगता है कि अंत उपभोक्ता से आंतरिक रूप से "पता" की उम्मीद करना अनुचित है कि GetPersonByID एक शून्य देता है (जब तक कि अशक्त प्रकार का उपयोग नहीं किया जाता है, मुझे लगता है। )।

मेरा लेना (जो इसके लायक है) वह यह है कि यदि कुछ नहीं मिला तो मेरा DAL रिटर्न करता है। कुछ मामलों के लिए, यह ठीक है - यह 0 हो सकता है: कई चीजों की सूची, इसलिए किसी भी चीज का ठीक न होना (जैसे पसंदीदा किताबों की सूची)। इस मामले में, मेरा बीएलएल एक खाली सूची देता है। ज्यादातर एकल इकाई चीजों (जैसे उपयोगकर्ता, खाता, चालान) के लिए यदि मेरे पास एक नहीं है, तो यह निश्चित रूप से एक समस्या है और एक महंगा अपवाद है। हालांकि, एक अद्वितीय पहचानकर्ता द्वारा उपयोगकर्ता को पुनः प्राप्त करने के रूप में देखकर, जो पहले आवेदन द्वारा दिया गया है, हमेशा एक उपयोगकर्ता को वापस करना चाहिए, अपवाद एक "उचित" अपवाद है, क्योंकि यह असाधारण है। BLL (ASP.Net, f'rinstance) का अंतिम उपभोक्ता कभी भी चीजों को हंकी-डोरी होने की उम्मीद करता है, इसलिए एक सिंगल-ब्लॉक ब्लॉक में GetPersonBIDID पर हर एक कॉल को रैप करने के बजाय एक अनहेल्ड एक्सेप्शन हैंडलर का उपयोग किया जाएगा।

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

मैं इस पोस्ट का आनंद ले रहा हूं, "यह निर्भर करता है" परिदृश्यों के लिए बहुत अच्छे सुझाव दिए गए हैं :-)


और निश्चित रूप से, आज मैं एक ऐसे परिदृश्य में आया हूं, जहां मैं अपने BLL से NULL को वापस करने जा रहा हूं; ;-) ने कहा, मैं अभी भी एक अपवाद फेंक सकता हूं और अपने उपभोग वर्ग में कोशिश / पकड़ का उपयोग कर सकता हूं लेकिन मुझे अभी भी एक समस्या है : मेरा उपभोग करने वाला वर्ग कोशिश / कैच का उपयोग करना कैसे जानता है, इसी तरह वे NULL की जाँच करना कैसे जानते हैं?
माइक किंग्सकोट

आप यह दस्तावेज कर सकते हैं कि एक विधि @throws doctag के माध्यम से एक अपवाद फेंकता है और आप इस तथ्य को दस्तावेज़ित करेंगे कि यह @return doctag में रिक्त हो सकता है।
टिमोक्सले

1

मुझे लगता है कि फ़ंक्शन को आपके कोड-बेस के स्वास्थ्य के लिए अशक्त नहीं होना चाहिए। मैं कुछ कारणों के बारे में सोच सकता हूं:

अशक्त संदर्भ का इलाज करने वाले गार्ड क्लॉज की एक बड़ी मात्रा होगी if (f() != null)

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

nullघूमने के बाद आपके कोड-बेस के बढ़ने पर समय-समय पर लगभग कुछ अप्रत्याशित NullRef अपवाद दिए जाएंगे।

कुछ समाधान हैं, tester-doer patternया option typeकार्यात्मक प्रोग्रामिंग से लागू करना है।


0

मैं जवाबों की संख्या पर (सभी वेब पर) हैरान हूं, जो कहते हैं कि आपको दो तरीकों की आवश्यकता है: एक "IsItThere ()" विधि और एक "GetItForMe ()" विधि और इसलिए यह एक दौड़ की स्थिति की ओर जाता है। एक फ़ंक्शन के साथ क्या गलत है जो अशक्त लौटाता है, इसे एक चर को निर्दिष्ट करता है, और एक परीक्षण में Null के लिए चर की जाँच करता है? मेरा पूर्व सी कोड के साथ peppered किया गया था

अगर (NULL! = (चर = फ़ंक्शन (तर्क ...))) {

तो आपको एक चर में मूल्य (या अशक्त) मिलता है, और परिणाम एक ही बार में। क्या इस मुहावरे को भुला दिया गया है? क्यों?


0

मैं यहां ज्यादातर पोस्टों से सहमत हूं, जो की ओर रुख करते हैं null

मेरा तर्क यह है कि गैर-अशक्त गुणों के साथ एक खाली वस्तु उत्पन्न करने से कीड़े हो सकते हैं। उदाहरण के लिए, एक int IDसंपत्ति वाली इकाई का प्रारंभिक मूल्य होगा ID = 0, जो पूरी तरह से वैध मूल्य है। उस वस्तु को, किसी परिस्थिति में, डेटाबेस में सहेजा जाना चाहिए, यह एक बुरी बात होगी।

एक पुनरावृत्ति के साथ किसी भी चीज के लिए मैं हमेशा खाली संग्रह का उपयोग करूंगा । कुछ इस तरह

foreach (var eachValue in collection ?? new List<Type>(0))

मेरी राय में कोड गंध है। संग्रह गुण कभी भी अशक्त नहीं होना चाहिए।

एक किनारे का मामला है String। बहुत से लोग कहते हैं, String.IsNullOrEmptyवास्तव में आवश्यक नहीं है, लेकिन आप हमेशा एक खाली स्ट्रिंग और अशक्त के बीच अंतर नहीं कर सकते। इसके अलावा, कुछ डेटाबेस सिस्टम (ओरेकल) उन दोनों के बीच अंतर नहीं करेगा ( ''संग्रहीत के रूप में DBNULL), इसलिए आप उन्हें समान रूप से संभालने के लिए मजबूर हैं। इसका कारण यह है, अधिकांश स्ट्रिंग मान या तो उपयोगकर्ता इनपुट से या बाहरी सिस्टम से आते हैं, जबकि न तो टेक्स्टबॉक्स और न ही अधिकांश एक्सचेंज स्वरूपों में ''और के लिए अलग-अलग प्रतिनिधित्व हैं null। इसलिए यदि उपयोगकर्ता कोई मूल्य निकालना चाहता है, तो भी वह इनपुट नियंत्रण को समाप्त करने से अधिक कुछ नहीं कर सकता है। इसके अलावा, अशक्त और गैर-अशक्त nvarcharडेटाबेस फ़ील्ड का अंतर संदिग्ध से अधिक है, यदि आपका DBMS अलंकृत नहीं है - एक अनिवार्य फ़ील्ड जो अनुमति देता है''अजीब है, आपका यूआई इसे कभी भी अनुमति नहीं देगा, इसलिए आपकी बाधाएं मैप नहीं होती हैं। तो यहाँ जवाब, मेरी राय में, उन्हें समान रूप से, हमेशा संभालना है।

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


0

एक अतुल्यकालिक TryGet पैटर्न:

तुल्यकालिक विधियों के लिए, मेरा मानना है कि @Johann गेरेल के जवाब है पैटर्न सभी मामलों में उपयोग करने के लिए।

हालाँकि outपैरामीटर के साथ TryGet पैटर्न Async विधियों के साथ काम नहीं करता है।

अब आप ऐसा कर सकते हैं C # 7 के टुपल साहित्य के साथ:

async Task<(bool success, SomeObject o)> TryGetSomeObjectByIdAsync(Int32 id)
{
    if (InternalIdExists(id))
    {
        o = await InternalGetSomeObjectAsync(id);

        return (true, o);
    }
    else
    {
        return (false, default(SomeObject));
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.