जब कोई आइटम हटाने के लिए निर्दिष्ट न हो तो सेवा को अपवाद या वापस फेंक देना चाहिए


12

मेरे पास कोड का एक टुकड़ा है जिसे निम्न रूप में दर्शाया जा सकता है:

public class ItemService {

    public void DeleteItems(IEnumerable<Item> items)
    {
        // Save us from possible NullReferenceException below.
        if(items == null)
            return;

        foreach(var item in items)
        {
            // For the purpose of this example, lets say I have to iterate over them.
            // Go to database and delete them.
        }
    }
}

अब मैं सोच रहा हूं कि क्या यह सही तरीका है या मुझे अपवाद छोड़ देना चाहिए। मैं अपवाद से बच सकता हूं, क्योंकि वापसी एक खाली संग्रह पर पुनरावृत्ति करने के समान होगी, जिसका अर्थ है, किसी भी महत्वपूर्ण कोड को वैसे भी निष्पादित नहीं किया जाता है, लेकिन दूसरी तरफ मैं संभवतः कोड में समस्याओं को छिपा रहा हूं, क्योंकि कोई भी कॉल क्यों करना चाहता है पैरामीटर के DeleteItemsसाथ null? यह संकेत दे सकता है कि कोड में कहीं और समस्या है।

यह एक ऐसी समस्या है जो मेरे पास आमतौर पर सेवाओं में विधियों के साथ होती है, क्योंकि उनमें से अधिकांश कुछ करते हैं और एक परिणाम नहीं देते हैं, इसलिए यदि कोई अमान्य जानकारी देता है तो सेवा करने के लिए कुछ भी नहीं है, इसलिए यह वापस आ जाता है।


2
यह सिर्फ मेरे व्यक्ति की राय है, लेकिन मैंने हमेशा इसे सबसे अधिक समझदार पाया है कि एक विधि को एक अपवाद फेंकना चाहिए जब यह अनपेक्षित (असाधारण) कुछ करता है। आपके मामले में, मैं किसी अमान्य / 0 आइटम को हटाने का प्रयास करने पर InvalidOperationException को फेंक दूंगा।
फाल्गुनिल


1
@gnat मेरा प्रश्न विशेष रूप से सेवाओं के बारे में है, क्योंकि उनका उपयोग कैसे किया जाता है और उनका उद्देश्य क्या है। यह "डुप्लिकेट" केवल सामान्य मामलों के बारे में बात करता है और मुख्य उत्तर यहां तक ​​कि मेरे सटीक तरीके के संदर्भ में भी विरोधाभासी है।
एफसीएन

2
क्या अशक्त के बजाय अशक्त होना संभव है? क्या आप इसे अलग तरीके से संभालेंगे?
JAD

13
@Falgantil मैं एक अपवाद के योग्य होने के लिए अशक्त देख सकता हूं, लेकिन मुझे लगता है कि एक खाली सूची पर एक अपवाद को फेंकना बेतुका है।
केविन

जवाबों:


58

ये दो अलग-अलग सवाल हैं।

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

क्या आपको खाली संग्रह स्वीकार करना चाहिए? मेरी राय में: हाँ, बिल्कुल। यह गणितीय रूप से सही काम करने की तुलना में सभी कॉलर्स को गैर-खाली संग्रह तक सीमित करने का अधिक प्रयास है - भले ही यह कुछ डेवलपर्स को आश्चर्यचकित करता हो जो शून्य की अवधारणा के साथ iffy हैं।


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

2
... आपको केवल स्केच मापदंडों के कारण उठाए गए अपवादों को तुरंत पकड़ना चाहिए, अगर आप जानते हैं कि आप जिस चीज से गुजर रहे हैं वह किसी अपेक्षित मामले में शून्य है, और आप सक्रिय रूप से उस फ़ंक्शन को चाहते हैं जिसे आप इसे मान्य करने के लिए बुला रहे हैं। जैसे कि किलियन उत्तर में कहता है, आपकी सामान्य नीति हर जगह शून्य पर प्रतिबंध लगाने की हो सकती है, यह स्पष्ट रूप से अनुमति नहीं है। तब आप उच्च-स्तरीय आपदा-वसूली कोड को छोड़कर कहीं भी NullReferenceExceptionया नहीं पकड़ेंगे AhaINoticedYouPassingInNullException। और उस अपवाद हैंडलर को संभवतः बग रिपोर्ट बनाना चाहिए :-)
स्टीव जेसप

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

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

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

9

अशक्त मान

जैसा कि @KilianFoth ने पहले ही कहा, अपनी सामान्य नीति से चिपके रहें। यदि वह nullएक खाली सूची के लिए "आशुलिपि" के रूप में माना जाता है, तो उस तरह से करें।

यदि आपके पास nullमूल्यों पर एक सुसंगत नीति नहीं है , तो मैं निम्नलिखित की सिफारिश करूंगा:

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

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

खाली सूची

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

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


1

एक अपवाद को फेंक दें और कॉलिंग कोड में नल को संभालें।

एक डिज़ाइन नियम के रूप में पैरामीटर मानों के रूप में अशक्त से बचने की कोशिश करें। यह सामान्य रूप से NullPointerException को कम कर देगा, क्योंकि नल वास्तव में अपवाद होंगे।

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


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

0

सामान्यतया, अपवादों को फेंकना असाधारण स्थितियों के लिए आरक्षित होना चाहिए, अर्थात यदि कोड में वर्तमान संदर्भ में कार्रवाई का कोई उचित पाठ्यक्रम नहीं है।

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

आपके कोड का कोई संदर्भ नहीं है कि इसे क्या कह रहे हैं (जैसा कि यह नहीं होना चाहिए), और ऐसा कुछ भी नहीं है जो आप यथोचित रूप से शून्य मान के साथ कर सकते हैं। यह निश्चित रूप से एक उम्मीदवार होगा ArgumentNullException


"यदि कोड में वर्तमान संदर्भ में कार्रवाई का कोई उचित पाठ्यक्रम नहीं है"। लेकिन मेरी सोच यह है कि इसके पास उचित कार्रवाई है, जो कि शून्य है। यह बिल्कुल वैसा ही है जैसे खाली संग्रह को पास करते समय, इसलिए अगर मैं खाली संग्रह की अनुमति देता हूं तो मैं अनुमति क्यों नहीं दूंगा null
FCin

1
@FC एक खाली संग्रह के कारण आप जानते हैं कि यह खाली है। साथ nullआप कोई संग्रह है। यदि कॉलिंग कोड माना जाता है / विधि को संग्रह की आपूर्ति करने की उम्मीद है, तो कुछ गड़बड़ है, इसलिए आपको फेंक देना चाहिए। एक रिक्त संग्रह के रूप में एक अशक्त का इलाज करने का एकमात्र कारण यह है कि यदि आप कॉल संग्रह की अपेक्षा कर सकते हैं तो अशक्त संग्रह का उत्पादन कर सकते हैं। जैसा कि अन्य उत्तर में कहा गया है, ज्यादातर समय, कुछ होने के नाते nullएक विसंगति है। यदि आप इन्हें खाली संग्रह के समान मानते हैं, तो आप कोड में कहीं और समस्या की अनदेखी कर रहे हैं।
JAD

@FCin: यदि आप nullखाली का मतलब निकालते हैं, तो यह संदर्भ-विशिष्ट है। समान कोड बेस में कहीं और, आपके पास एक ऐसा पैरामीटर IEnumerableया IContainerपैरामीटर हो सकता है जो किसी प्रकार की फ़िल्टरिंग करता है, nullजिसका अर्थ "नो फिल्टर" (सब कुछ अनुमति दें) हो सकता है , जबकि एक खाली फ़िल्टर का अर्थ है कुछ भी नहीं होने देना। और दूसरी जगह पर, null"मैं नहीं जानता" का स्पष्ट अर्थ हो सकता है। तो, यह देखते हुए कि nullहमेशा हर जगह एक ही चीज का मतलब नहीं होता है, यह एक अच्छा विचार है कि इसके लिए किसी भी अर्थ का आविष्कार न करें जब तक कि यह अर्थ किसी के लिए आवश्यक या कम से कम उपयोगी न हो।
स्टीव जेसोप

0

यह प्रश्न अपवादों के बारे में नहीं लगता है, बल्कि nullएक मान्य तर्क होने के बारे में है।

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

चाहे आप अनुमति देना चाहते हों nullया नहीं, यह बहस का विषय है, जैसा कि उस बारे में Google के बहुत सारे और बहुत से हिट द्वारा दिखाया गया है। मतलब, आपको स्पष्ट जवाब नहीं मिलेगा, और यह उस जगह पर राय और परंपरा के अनुसार है जो आप काम कर रहे हैं।

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

इसलिए आपको यह तय करना होगा: क्या वास्तव में nullहैंडलिंग जैसी बड़ी नीति को लागू करना पुस्तकालय पद्धति का काम है ? खासकर अगर आपकी लाइब्रेरी का उपयोग अन्य लोग भी करते हैं (जिनकी अलग-अलग नीतियां हो सकती हैं)।

मैं शायद nullमानों की अनुमति देने , उनके शब्दार्थ (यानी null = empty arrayइस मामले में) को निर्धारित करने और दस्तावेज़ीकरण करने के पक्ष में गलत करूंगा , और जब तक कि आपके अन्य समान कोड ("पुस्तकालय" शैली कोड) का 99% इसे दूसरे तरीके से नहीं करता , तब तक अपवाद न फेंकें। 'गोल।


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

@SteveJessop, मैं वास्तव में नहीं जानता कि क्या आप मेरे जवाब की भावना के खिलाफ बहस कर रहे हैं, या क्या आप इसकी लाइन को जारी रख रहे हैं। उस ने कहा, मैं केवल निगलने का सुझाव नहीं दे रहा हूं null, लेकिन यह विधि के अनुबंध में खुले तौर पर यह घोषित करने के लिए है कि यह स्वीकार्य है (या, जो कुछ भी समाधान ओपी ऊपर आता है) के आधार पर, और फिर सवाल यह है कि क्या एक अपवाद फेंकना है (या नहीं) खुद को हल करता है।
एनोइ
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.