अगर-और सीढ़ी जो सभी स्थितियों को पकड़ने वाली है - क्या एक निरर्थक अंतिम खंड जोड़ा जाना चाहिए?


10

यह एक ऐसी चीज है जो मैं हाल ही में कर रहा हूं।

उदाहरण:

setCircle(circle, i, { current }) {
    if (i == current) {
        circle.src = 'images/25CE.svg'
        circle.alt = 'Now picking'
    } else if (i < current) {
        circle.src = 'images/25C9.svg'
        circle.alt = 'Pick failed'
    } else if (i > current) {
        circle.src = 'images/25CB.svg'
        circle.alt = 'Pick chance'
    }
}

अक्सर अगर / और सीढ़ी इस से अधिक जटिल है ...

अंतिम खंड देखें? यह बेमानी है। सीढ़ी को अंततः सभी संभावित स्थितियों को पकड़ना चाहिए। इस प्रकार इसे फिर से लिखा जा सकता है:

setCircle(circle, i, { current }) {
    if (i == current) {
        circle.src = 'images/25CE.svg'
        circle.alt = 'Now picking'
    } else if (i < current) {
        circle.src = 'images/25C9.svg'
        circle.alt = 'Pick failed'
    } else {
        circle.src = 'images/25CB.svg'
        circle.alt = 'Pick chance'
    }
}

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

तथापि:

  • स्पष्ट रूप से अंतिम थकाऊ स्थिति लिखना मेरा अपना विचार है, और मेरे अपने विचारों के साथ बुरे अनुभव हैं - आमतौर पर लोग मुझ पर चिल्लाते हैं कि मैं कितना भयानक काम कर रहा हूं - और (कभी-कभी) बाद में मुझे पता चलता है कि यह वास्तव में था इनकी;
  • एक संकेत क्यों यह एक बुरा विचार हो सकता है: जावास्क्रिप्ट पर लागू नहीं होता है, लेकिन अन्य भाषाओं में, कंपाइलर चेतावनी जारी करते हैं या फ़ंक्शन के अंत तक नियंत्रण के बारे में त्रुटियां भी बताते हैं। कुछ ऐसा करना, जो बहुत लोकप्रिय न हो या मैं इसे गलत कर रहा हो।
    • कंपाइलर शिकायतों ने मुझे कभी-कभी एक टिप्पणी में अंतिम स्थिति लिखी, लेकिन मुझे लगता है कि ऐसा करना कोड के विपरीत टिप्पणियों के बाद से भयानक है, वास्तविक कार्यक्रम शब्दार्थ पर कोई प्रभाव नहीं है:
    } else { // i > current
        circle.src = 'images/25CB.svg'
        circle.alt = 'Pick chance'
    }

क्या मैं कुछ भूल रहा हूँ? या मैंने जो वर्णन किया है क्या वह करना ठीक है या यह एक बुरा विचार है?


+1 @ क्रिस्टोफ़ के निष्पादक उत्तर के लिए कि कोड में अतिरेक दोष की संभावना को बढ़ाता है। वहाँ भी एक बहुत कम दक्षता मुद्दा है। उस पर विस्तार करने के लिए, प्रश्न में कोड के उदाहरण के बारे में, हम if-else-if की श्रृंखला लिख ​​सकते हैं यदि बिना किसी elses के बस अलग है, लेकिन हम आम तौर पर if-else के पाठक को विशेष विकल्पों की धारणा नहीं देते हैं। स्वतंत्र परिस्थितियों की श्रृंखला के बजाय (जो भी कम कुशल होगा, क्योंकि यह कहता है कि सभी स्थितियों का मूल्यांकन एक मैच के बाद भी किया जाना चाहिए)।
एरिक इद्दत

@ErikEidt> चूंकि यह कहता है कि सभी स्थितियों का मूल्यांकन एक मैच के बाद भी किया जाना चाहिए जब तक कि आप किसी फ़ंक्शन से वापस नहीं आ रहे हैं या लूप से "ब्रेकिंग" नहीं कर रहे हैं (जो उपरोक्त उदाहरण में ऐसा नहीं है)।
डेरेक नाद्जा

1
+1, अच्छा सवाल। एक तरफ यह आपकी रुचि हो सकती है कि NaN की उपस्थिति में उदाहरण संपूर्ण नहीं है।
मोनोकेल

जवाबों:


6

दोनों दृष्टिकोण मान्य हैं। लेकिन चलो पेशेवरों और विपक्ष पर करीब से नजर डालते हैं।

ifयहां जैसे तुच्छ परिस्थितियों के साथ -चैन के लिए , यह वास्तव में मायने नहीं रखता है:

  • एक फाइनल के साथ else, पाठक को यह पता लगाना स्पष्ट है कि किस स्थिति में दूसरे को ट्रिगर किया गया है;
  • एक फाइनल के साथ else if, यह पाठक के लिए स्पष्ट है कि elseआपको इसे कवर करने के बाद से कोई अतिरिक्त आवश्यकता नहीं है।

हालांकि, बहुत सारे if-चिन हैं जो अधिक जटिल परिस्थितियों पर निर्भर करते हैं, कई चर के राज्यों को मिलाकर, शायद एक जटिल तार्किक अभिव्यक्ति के साथ। इस मामले में यह कम स्पष्ट है। और यहाँ प्रत्येक शैली का परिणाम है:

  • अंतिम else: आपको यकीन है कि शाखा में से एक लिया गया है। यदि ऐसा होता है कि आप एक मामले को भूल गए हैं, तो यह उस अंतिम शाखा से होकर गुजरेगा, इसलिए डिबगिंग के दौरान, यदि अंतिम शाखा को चुना गया था और आपको कुछ और की उम्मीद थी, तो आप जल्दी से पता लगा लेंगे।
  • अंतिम else if: आपको कोड के लिए निरर्थक स्थिति प्राप्त करने की आवश्यकता है, और यह सभी मामलों को कवर नहीं करने की पुनरावृत्ति के साथ एक संभावित त्रुटि स्रोत बनाता है। इसके अलावा, यदि आपने कोई केस मिस कर दिया है, तो कुछ भी प्रदर्शन नहीं किया जाएगा और यह पता लगाना अधिक मुश्किल हो सकता है कि कुछ गायब था (जैसे कि कुछ वैरिएबल जिन्हें आप सेट करने की उम्मीद करते हैं, पिछले पुनरावृत्तियों से मान रखें)।

तो अंतिम निरर्थक स्थिति जोखिम का एक स्रोत है। यही कारण है कि मैं फाइनल में जाने का सुझाव दूंगा else

संपादित करें: उच्च विश्वसनीयता कोडिंग

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

यह रक्षात्मक कोडिंग है। यह कुछ सुरक्षा विनिर्देशों जैसे SEI CERT या MISRA द्वारा अनुशंसित है । कुछ स्थैतिक विश्लेषण उपकरण इसे एक नियम के रूप में भी लागू करते हैं जिसे व्यवस्थित रूप से जांचा जाता है (यह आपके संकलक की चेतावनी को समझा सकता है)।


7
क्या होगा अगर अंतिम निरर्थक शर्त के बाद मैं एक और जोड़ देता हूं जो हमेशा एक अपवाद फेंकता है जो कहता है "आप मुझ तक पहुंचने वाले नहीं थे!" - क्या यह मेरे दृष्टिकोण की कुछ समस्याओं को दूर करेगा?
गज़कम

3
@gaazkam हाँ, यह कोडिंग की एक बहुत ही रक्षात्मक शैली है। इसलिए आपको अभी भी अंतिम स्थिति की गणना करने की आवश्यकता है, लेकिन जटिल त्रुटि-प्रवण जंजीरों के लिए, आपको कम से कम जल्दी पता चल जाएगा। इस संस्करण के साथ मैं केवल एक ही मुद्दा देख रहा हूं कि यह स्पष्ट मामले के लिए थोड़ा ओवरकिल है।
क्रिस्टोफ

@gaazkam मैंने अपने उत्तर को आपके अतिरिक्त विचार का उल्लेख अपनी टिप्पणी में संपादित किया है
Christophe

1
@gaazkam एक अपवाद को फेंकना अच्छा है। यदि आप करते हैं, तो संदेश में अप्रत्याशित मूल्य को शामिल करना न भूलें। पुन: पेश करना कठिन हो सकता है और अप्रत्याशित मूल्य समस्या के स्रोत के बारे में एक सुराग प्रदान कर सकता है।
मार्टिन माट

1
एक अन्य विकल्प के लिए एक assertअंतिम में डाल दिया है else if। आपका स्टाइल गाइड इस बात पर भिन्न हो सकता है कि यह एक अच्छा विचार है या नहीं। ( assertजब तक प्रोग्रामर खराब न हो जाए, तब तक एक की स्थिति झूठी नहीं होनी चाहिए। इसलिए यह कम से कम अपने इच्छित उद्देश्य के लिए फीचर का उपयोग कर रहा है। लेकिन बहुत से लोग इसका दुरुपयोग करते हैं कि बहुत सारी दुकानों ने इसे एकमुश्त प्रतिबंधित कर दिया है।)
केविन

5

अब तक के उत्तरों में से कुछ गायब है, यह इस बात का विषय है कि किस प्रकार की विफलता कम हानिकारक है।

यदि आपका तर्क अच्छा है तो यह वास्तव में मायने नहीं रखता कि आप क्या करते हैं, महत्वपूर्ण मामला यह है कि यदि आपके पास बग है तो क्या होता है।

आप अंतिम शर्त को छोड़ देते हैं: अंतिम विकल्प निष्पादित होता है, भले ही वह सही काम न करे।

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

आप अंतिम सशर्त और एक अपवाद जोड़ते हैं: यह फेंकता है।

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

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


4

मैं जो सलाह देता हूं वह assertआपके दो और शैलियों में आपके अंतिम रूप में एक कथन का उपयोग कर रहा है :

setCircle(circle, i, { current }) {
    if (i == current) {
        circle.src = 'images/25CE.svg'
        circle.alt = 'Now picking'
    } else if (i < current) {
        circle.src = 'images/25C9.svg'
        circle.alt = 'Pick failed'
    } else {
        assert i > current
        circle.src = 'images/25CB.svg'
        circle.alt = 'Pick chance'
    }
}

या एक मृत कोड मुखर:

setCircle(circle, i, { current }) {
    if (i == current) {
        circle.src = 'images/25CE.svg'
        circle.alt = 'Now picking'
    } else if (i < current) {
        circle.src = 'images/25C9.svg'
        circle.alt = 'Pick failed'
    } else if (i > current) {
        circle.src = 'images/25CB.svg'
        circle.alt = 'Pick chance'
    } else {
        assert False, "Unreachable code"
    }
}

कोड कवरेज टूल को अक्सर कवरेज रिपोर्ट से "जोर झूठ" जैसे कोड को अनदेखा करने के लिए कॉन्फ़िगर किया जा सकता है।


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


1
मुझे आपका पहला विकल्प पसंद नहीं है, दूसरा बहुत स्पष्ट है कि यह एक असंभव मामला है।
लोरेन Pechtel

0

मैंने एक मैक्रो "मुखर" को परिभाषित किया जो एक स्थिति का मूल्यांकन करता है, और डीबग बिल्ड में डीबगर में गिरता है।

इसलिए अगर मुझे 100 प्रतिशत यकीन है कि तीन शर्तों में से एक सही होनी चाहिए, तो मैं लिखता हूं

If condition 1 ...
Else if condition 2 .,,
Else if asserted (condition3) ...

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


-2

मैं पूरी तरह से बचने की सलाह देता हूं । ifयह घोषित करने के लिए उपयोग करें कि कोड के ब्लॉक को संभालने के लिए क्या माना जाता है, और फ़ंक्शन से बाहर निकलकर ब्लॉक को समाप्त करें।

कोड में यह परिणाम बहुत स्पष्ट है:

setCircle(circle, i, { current })
{
    if (i == current)
    {
        circle.src = 'images/25CE.svg'
        circle.alt = 'Now picking'
        return
    }
    if (i < current)
    {
        circle.src = 'images/25C9.svg'
        circle.alt = 'Pick failed'
        return
    }
    if (i > current)
    {
        circle.src = 'images/25CB.svg'
        circle.alt = 'Pick chance'
        return
    }
    throw new Exception("Condition not handled.");
}

फाइनल ifआज बेमानी है ... आज। यह बहुत महत्वपूर्ण सोचा जा सकता है अगर / जब कुछ भविष्य के डेवलपर ब्लॉक की व्यवस्था करते हैं। इसलिए इसे वहां छोड़ने में मददगार है।


1
यह वास्तव में बहुत अस्पष्ट है क्योंकि अब मुझे इस पर विचार करने की आवश्यकता है कि क्या पहली शाखा को निष्पादित करने से दूसरे परीक्षण के परिणाम बदल सकते हैं। प्लस व्यर्थ कई रिटर्न। साथ ही संभावना है कि कोई भी शर्त सही नहीं है।
gnasher729

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

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

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