स्विच मामलों का उपयोग करते समय क्या डिफ़ॉल्ट मामले को जोड़ना आवश्यक है?


41

हाल ही में एक कोड की समीक्षा के दौरान मुझे defaultसभी फाइलों में मामलों को डालने के लिए कहा गया था switch, जहां ब्लॉक का उपयोग किया जाता है, भले ही इसमें कुछ करना न हो default। इसका मतलब है कि मुझे defaultमामला डालना है और इसमें कुछ नहीं लिखना है।

क्या यह सही काम है जिसे करना चाहिए? यह किस उद्देश्य की पूर्ति करेगा?


9
इसका आपके ऊपर ... मेरा मतलब है पर्यवेक्षक की कोड शैली।
एसडी

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

6
मैं और मेरे दोस्त इसे "डेवलपर अपवाद" मामला कहते हैं - जब कोड में कुछ ऐसा होता है जिसे आप जानते हैं कि ऐसा कभी नहीं होना चाहिए (तार्किक / कोड कारणों के कारण), तो हम एक "डेवलपर अपवाद" जोड़ते हैं जो फेंक दिया जाता है। इस तरह, अगर ऐसा कभी होता है, तो एक डेवलपर अपवाद को फेंक दिया जाता है और कम से कम हम जानते हैं कि चीजें कहां गलत हुईं।
मार्को

जवाबों:


31

ऐसा लगता है कि तीन मामले हैं जब एक defaultबयान आवश्यक नहीं है:

  1. कोई अन्य मामले नहीं बचे हैं, क्योंकि मूल्यों का एक सीमित सेट है जो प्रवेश करते हैं switch case। लेकिन यह समय के साथ बदल सकता है (जानबूझकर या दुर्घटनावश), और default caseयदि कुछ भी बदलता है तो अच्छा होगा _ आप उपयोगकर्ता को गलत मान के बारे में लॉग इन या चेतावनी दे सकते हैं।

  2. आप जानते हैं कि switch caseइसका उपयोग कैसे और कहां किया जाएगा और यह किन मूल्यों में प्रवेश करेगा। फिर, यह बदल सकता है और एक अतिरिक्त-प्रसंस्करण की आवश्यकता हो सकती है।

  3. अन्य मामलों में किसी विशेष प्रसंस्करण की आवश्यकता नहीं है। यदि यह मामला है, मुझे लगता है कि आपको एक जोड़ने के लिए कहा गया है default case, क्योंकि यह एक स्वीकृत कोडिंग शैली है, और यह आपके कोड को अधिक पठनीय बनाता है।

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


14
1 और 2 के मामले में, एक डिफ़ॉल्ट मामला एक त्रुटि होना चाहिए। यदि आपकी कोडिंग शैली हमेशा डिफ़ॉल्ट का उपयोग करती है, तो ऐसा करें, लेकिन इसे 1 और 2 में एक त्रुटि का उत्सर्जन करें। यह संभव है, इसे संकलन समय पर फेंकना चाहिए, लेकिन यह हमेशा संभव नहीं हो सकता है, अगर कभी जावा में। मुझे कम से कम लगता है कि उपयोगकर्ता के लिए यह संदेश प्राप्त करना महत्वपूर्ण है कि "आप इस मूल्य में गुजर कर अपने आप को पैर में गोली मार रहे हैं"
शहादत

11
एक डिफ़ॉल्ट मामला हमेशा एक अच्छा विचार होता है, क्योंकि, उदाहरण के लिए, एक एनुम के मामले में, यदि कोई एनम में एक नई प्रविष्टि जोड़ता है, तो आपके डिफ़ॉल्ट मामले को कुछ ऐसा करना चाहिए throw new IllegalStateException("Unrecognised case "+myEnum)जो आपको दिखाता है कि त्रुटि कहां और क्या है।
रिच

क्या इसका मतलब यह है कि आपके पास हमेशा एक elseखंड होना चाहिए, if/else ifभले ही आपको पता हो कि ऐसा नहीं होना चाहिए? मुझे एक अच्छा विचार नहीं लगता ...
jadkik94

2
यदि मैं अपने काम से एक उपाख्यान जोड़ सकता हूं: मेरे पास एक कारखाना विधि थी जो कुछ कक्षाओं को तत्काल करने के लिए एक एनुम का उपयोग करती थी। मैंने निर्देश छोड़ दिए थे कि जब भी आपने उस परियोजना में एक नया वर्ग जोड़ा तो आपको एनम और वैल्यू ओ स्विच में एक मान जोड़ना होगा। बेशक, एक हफ्ते बाद मैंने कोड को बंद कर दिया, यह काम करना बंद कर देता है, एक अपवाद के साथ जो कभी नहीं उठाया जाना चाहिए। मैं प्रोग्रामर के पास जाता हूं और उससे पूछता हूं: "क्या आपने स्विच में कोई मामला जोड़ा है?" और निश्चित रूप से पर्याप्त, वह नहीं था। उस दिन मैंने यह कहने के लिए अपवाद बदल दिया "यदि आपको यह संदेश मिलता है, तो कोड को छूने वाले अंतिम डेवलपर को दोष दें"।
Ziv

28

क्या यह सही थिओन्ग है? यह किस उद्देश्य की पूर्ति करेगा?

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

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

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


1
एक क्या है assert?
FLY

1
@FLY यह जावा में एक कीवर्ड है और आमतौर पर C, C ++ आदि में एक मैक्रो है। किसी भी तरह, एक परख का उपयोग यह परीक्षण करने के लिए किया जाता है कि कुछ धारणा सही है और फेंक दें और अपवाद करें या अन्यथा त्रुटि का कारण बनें।
कालेब

मैंने अपनी पिछली टिप्पणी विकिपीडिया के लिंक के साथ संपादित की है
FLY

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

12

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


1
+1 संकलन-समय पर समस्या को पकड़ने के लिए और रन-टाइम पर नहीं।
सिल्वेनड

मुझे आश्चर्य है कि कैसे पूरी तरह से भ्रामक जवाब मतदान और स्वीकार किया जाता है। क्विक गॉगलिंग से पता चलता है कि जावा कंपाइलर में इस तरह की चेतावनी होती है। पृथ्वी पर आप रनटाइम पर त्रुटि की प्रतीक्षा क्यों करेंगे, दोस्तों?
आर्टुर

मुझे इस व्यवहार के बारे में पता नहीं था। मेरा ideone कोड नमूना ideone.com/WvytWq अन्यथा सुझाव देता है। यदि आप कहते हैं कि यह सच है, तो मान लें कि यदि कोई व्यक्ति किसी एन्यूमरेशन प्रकार में मान जोड़ता है, लेकिन आप अपने कोड को फिर से जमा नहीं करते हैं?
एमोरी


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

9

कई मायनों में, यह सवाल वही है जो अक्सर पूछे जाने वाले प्रश्न के रूप में / एक सीढ़ी के अंत में एक खंड की आवश्यकता होती है जो हर विकल्प को कवर करता हैelseifelse if

इसका उत्तर है, वाक्यात्मक रूप से बोलना, नहीं, तुम नहीं। लेकिन फिर भी ...

एक defaultखंड (कम से कम) दो कारणों से हो सकता है:

  1. एक त्रुटि हैंडलर के रूप में - यकीन है, यहाँ कभी नहीं मिलना चाहिए! एक दावा है कि बनाया जा सकता है, लेकिन अगर यह करता है तो क्या होगा? डेटा भ्रष्टाचार, या इससे भी बदतर, कोई डेटा सत्यापन कार्यक्रम की विफलता के लिए मार्ग नहीं हैं यदि ठीक से फंसे नहीं हैं। इस मामले में, यह एक खाली खंड नहीं होना चाहिए!
  2. डिज़ाइन / कोड कवरेज - फ्लो-चार्ट के सबसे सरल रूप में भी, अगर-स्टेटमेंट से दो रूट हैं, और हमेशा otherwiseएक केस से। स्रोत कोड में इन्हें शामिल नहीं करने का कोई कारण नहीं है।

मेरा दर्शन हमेशा काफी सरल है - दो विकल्पों में से सबसे खराब स्थिति का आकलन करें, और सबसे सुरक्षित के लिए जाएं। खाली elseया defaultखंड के मामले में , सबसे खराब स्थिति विकल्प हैं:

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

Overdramatic? हो सकता है ... लेकिन फिर भी मेरे सॉफ्टवेयर में गलत होने पर लोगों को मारने की क्षमता है। मैं बल्कि वह जोखिम नहीं लेना चाहता।


एक तरफ के रूप में, MISRA-C दिशानिर्देश {संबद्धता के लिए प्रोफ़ाइल देखें} defaultहर के लिए एक खंड सुझाते हैंswitch


एक सीढ़ी के अंत में ही नहीं। सवाल यह है: मैं एक की जरूरत है elseएक के बाद if। लेकिन जैसा कि आपने कहा, नहीं, यह नहीं है।
ott--

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

अच्छा बिंदु, @emory - यह बहुत स्पष्ट नहीं था, यह था ... संपादित :) :)
एंड्रयू

6

जावा आपको 'डिफ़ॉल्ट' स्टेटमेंट देने के लिए बाध्य नहीं करता है, लेकिन हर समय एक कोड रखने के लिए अच्छा अभ्यास है, भले ही कोड कभी भी नहीं पहुंचा जा सकता (अभी)। यहाँ कुछ कारण हैं:

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

एक अप्रत्याशित मूल्य (यदि आप किसी एनम पर स्विच नहीं कर रहे हैं) को पकड़ने के लिए - जो इसमें पारित हो जाता है - यह उदाहरण के लिए, आपकी अपेक्षा से अधिक या कम हो सकता है।

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

यहां तक ​​कि अगर आप डिफ़ॉल्ट में कुछ भी नहीं डालने का फैसला करते हैं (कोई अपवाद नहीं है, तो लॉगिंग, आदि) तब भी यह कहने के लिए एक टिप्पणी कि आपने इस तथ्य को डिफ़ॉल्ट माना है कि कभी भी आपके कोड की पठनीयता में मदद नहीं मिल सकती है; लेकिन यह व्यक्तिगत प्राथमिकता पर आता है।


2

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


0

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

यदि आप वास्तव में सुनिश्चित हैं कि आप किसी अन्य मामलों की परवाह नहीं करते हैं, तो डिफ़ॉल्ट: ब्रेक;

इसी तरह, आपको कभी भी उस प्रभाव के लिए एक टिप्पणी को जोड़ने के बिना एक nontrivial मामले के निर्माण के माध्यम से "ड्रॉप" नहीं करना चाहिए जिसे आप के माध्यम से छोड़ने का इरादा रखते हैं। जावा को डिजाइन चरण में यह गलत मिला।


-2

विचार करें

enum Gender
{
       MALE ,
       FEMALE ;
}

तथा

void run ( Gender g )
{
      switch ( g )
      {
           case MALE :
                 // code related to males
                 break ;
           default :
                 assert Gender . FEMALE . equals ( g ) ;
                 // code related to females
                 break ;
      }
}

मैं यह तर्क दूंगा कि यह MALE केस, FEMALE केस और एक डिफ़ॉल्ट केस के अपवाद से बेहतर है जो अपवाद को फेंकता है।

आपके परीक्षण चरण के दौरान, कंप्यूटर यह जांच करेगा कि क्या G FEMALE है। उत्पादन के दौरान, चेक को छोड़ दिया जाएगा। (हाँ एक microoptimization!)

इससे भी महत्वपूर्ण बात, आप 100% कोड कवरेज के अपने लक्ष्य को बनाए रखेंगे। यदि आपने एक डिफ़ॉल्ट मामला लिखा है जो एक अपवाद फेंकता है, तो आप इसे कभी कैसे परखेंगे?


1
1. microoptimalization की कोई आवश्यकता नहीं है - मृत कोड उन्मूलन का उपयोग पिछले 30 वर्षों से कंपाइलरों में किया जाता है और इसे JIT से समाप्त कर दिया जाएगा। 2. 100% कोड कवरेज आमतौर पर महत्वपूर्ण नहीं माना जाता है (एक तरफ 100% कवरेज सभी किनारे के मामलों को पकड़ नहीं सकता है, कोई अन्य परीक्षण सही प्रोग्राम पर assert_not_reached लाइनों को पकड़ेगा)। इस मामले में कोई डिफ़ॉल्ट मामला नहीं छोड़ने से कंपाइलर त्रुटि होगी। दूसरी तरफ - यदि आप मुखर काम करते हैं (आप समस्या को शिफ्ट करते हैं और एक ही लाइन 'यह नहीं होगा, मैं वादा करता हूं' के बजाय इसे 100% कवरेज से छिपा देगा तो आप कैसे जांच करेंगे।
मैकीज पाइचोटका

1
3. कब Gender . FEMALE . equals ( FEMALE ) ;मूल्यांकन करता है false? आपका मतलब था, Gender.FEMALE.equals (g)लेकिन जब से आप स्थिर हैं, तो आप सिर्फ लिख सकते हैं g == Gender.FEMALE। 4. (व्यक्तिगत राय) इस तरह के कोड को पढ़ने के लिए बहुत कठिन है और थोड़ा और भ्रामक त्रुटियों का उत्पादन करेगा।
मैकीज पीचोटका

@MaciejPiechotka जी के बारे में अच्छी पकड़। हां, माइक्रोएप्टिमाइजेशन एक नॉनबिनफिट है, लेकिन न तो यह एक खामी है। 100% कोड कवरेज एक लाभ है iff जो आपके लक्ष्यों में से एक है और आपका कोड कवरेज टूल एसेर्ट्स की जांच नहीं करता है (जो इसे नहीं करना चाहिए)।
एमोरी

फिर यह मेरा एक लक्ष्य क्यों होगा? 'दिलचस्प' भाग को सभी किनारे मामलों के लिए परीक्षण किया जाना चाहिए (भले ही वे कोड की रेखाओं के अनुसार हों) और 'बोरिंग' भागों को परीक्षण पर समय बचाने के लिए बस छोड़ दिया जा सकता है। IMHO कोड कवरेज परीक्षणों का खराब मीट्रिक है।
मैकिज पीचोटका
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.