बूलियन तर्क की स्थिरता - यदि कथन की आवश्यकता है तो घोंसला बनाना है?


11

इनमें से कौन सी बेहतर है स्थिरता के लिए?

if (byteArrayVariable != null)
    if (byteArrayVariable .Length != 0)
         //Do something with byteArrayVariable 

या

if ((byteArrayVariable != null) && (byteArrayVariable.Length != 0))
  //Do something with byteArrayVariable 

मैं दूसरा पढ़ना और लिखना पसंद करता हूं, लेकिन मुझे कोड पूरा पढ़ने में याद आता है कि इस तरह की चीजें करना स्थिरता बनाए रखने के लिए बुरा है।

ऐसा इसलिए है क्योंकि आप भाषा पर भरोसा कर रहे हैं कि ifयदि पहला भाग गलत है तो दूसरे भाग का मूल्यांकन न करें और सभी भाषाएँ ऐसा नहीं करतीं। (दूसरा भाग एक अपवाद का मूल्यांकन करेगा यदि अशक्त के साथ मूल्यांकन किया गया है byteArrayVariable।)

मुझे नहीं पता कि वास्तव में इस बारे में चिंता करने के लिए कुछ है या नहीं, और मैं इस सवाल पर सामान्य प्रतिक्रिया चाहूंगा।

धन्यवाद।


1
पहले रूप में झूलने का जोखिम है-अन्य
JBRWilkinson

बस जिज्ञासु, आप किस भाषा के साथ काम कर रहे हैं?
एसटीडब्ल्यू

@STW - हम C # का उपयोग करते हैं और डेल्फी में कुछ विरासत कोड हैं।
वेकैनो

2
जानकार अच्छा लगा। मैं डेल्फी से परिचित नहीं हूं, लेकिन सी # में आप शॉर्ट-सर्किट मूल्यांकन कर रहे ऑपरेटरों &&और ||ऑपरेटरों पर विश्वास कर सकते हैं । एक भाषा से दूसरी भाषा में जाने पर आमतौर पर कुछ गोचर्स होते हैं, और उन छोटे मुद्दों को पकड़ने में मदद करने के लिए कोड समीक्षा करने के बारे में दृढ़ रहना अच्छा है।
STW

यहाँ कई उत्तरों के साथ-साथ मुझे दूसरा और पठनीय लगता है, पहला डीबग करना कहीं अधिक आसान है। इस मामले में, मैं अभी भी दूसरे का उपयोग करूंगा क्योंकि आप चीजों को डीबग करना आसान बना रहे हैं। लेकिन सामान्य रूप से सावधान रहें।
मगस

जवाबों:


30

मुझे लगता है कि दूसरा रूप ठीक है, और यह भी स्पष्ट रूप से दर्शाता है कि आप क्या करने की कोशिश कर रहे हैं। आप कहते हैं कि...

मुझे याद है कि कोड को पूरा पढ़ना उस तरह की चीजों को बनाए रखने के लिए बुरा है। इसका कारण यह है कि आप भाषा पर भरोसा कर रहे हैं यदि दूसरे भाग का मूल्यांकन नहीं किया जाता है यदि पहला भाग गलत है और सभी भाषाएं ऐसा नहीं करती हैं।

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


12
माना। धरती पर मुझे इसकी परवाह क्यों होगी अगर दूसरी भाषा में कॉपी करने पर मेरा कोड वही चलेगा?
टिम गुडमैन

16

मुझे आश्चर्य है कि किसी ने भी इसका उल्लेख नहीं किया है (इसलिए उम्मीद है कि मैं इस सवाल का गलत इस्तेमाल नहीं कर रहा हूं) - लेकिन दोनों तरह के चूसना!

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

उस समय आप कुछ ऐसा करेंगे:

if ((byteArrayVariable == null) || (byteArrayVariable.Length != 0)) {
  return; // nothing to be done, leaving
}

// Conditions met, do something

यह सत्यापन की तरह लग सकता है - और यह ठीक यही है। यह पुष्टि करता है कि यह विधि करने के लिए शर्तों को संतुष्ट किया गया है - दोनों विकल्प जो आपने पूर्व तर्क चेक के भीतर वास्तविक तर्क को छिपाए थे।

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


जैसा कि जिम का उल्लेख है, बहस के लिए अभी भी जगह है कि कैसे जल्दी से बाहर निकलने की संरचना की जाए। ऊपर जो होगा उसका विकल्प होगा:

if (byteArrayVariable == null) 
  return; // nothing to be done, leaving

if (byteArrayVariable.Length != 0)
  return;

// Conditions met, do something

1
मैं अच्छे तर्क के लपेटने के बजाय वापसी से सहमत हूं, लेकिन वही लोग उपयोग करने के बारे में उसी तर्क का उपयोग करेंगे || से संबंधित &&।
मिया

14

हर गैर इस स्थिति के लिए फंसाने के लिए समय बर्बाद मत करो । यदि आप डेटा या स्थिति को अयोग्य घोषित कर सकते हैं तो जल्द से जल्द ऐसा करें।

if (byteArrayVariable == null) Exit;
if (byteArrayVariable.Length == 0) Exit;
// do something

इससे आप नई स्थितियों के लिए अपने कोड को बहुत आसान बना सकते हैं

if (byteArrayVariable == null) Exit;
if (byteArrayVariable.Length == 0) Exit;
if (NewCondition == false) Exit;
if (NewerCondition == true) Exit;
// do something

2
+1 युप, यूप, यूप। जितना सरल यह मुश्किल कोड में परिणाम नहीं होना चाहिए तर्क। आपके (पूछने वाले की) आंत आपको यह बता रही होगी।
जॉब

11

आपका उदाहरण इसका सटीक उदाहरण है कि क्यों नेस्टेड ifsअधिकांश भाषाओं के लिए एक बुरा दृष्टिकोण है जो बूलियन तुलना का ठीक से समर्थन करते हैं। घोंसला बनाना ifsएक ऐसी स्थिति है जहाँ आपका इरादा बिल्कुल भी स्पष्ट नहीं है। क्या यह आवश्यक है कि दूसरा ifतुरंत पहले वाले का अनुसरण करे? या यह सिर्फ इसलिए है क्योंकि आपने अभी तक एक और ऑपरेशन नहीं किया है?

if ((byteArrayVariable != null) && (byteArrayVariable.Length != 0))
  //Do something with byteArrayVariable 

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

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

उस सभी ने कहा, यह बहुत अधिक पठनीय है, इसे उल्टा करना और बस विधि से बाहर लौटना अगर या तो संतुष्ट नहीं है जैसा कि एसटीडब्ल्यू अपने जवाब में कहता है।


दो से अधिक स्थितियां अपने स्वयं के फ़ंक्शन को वारंट कर सकती हैं जो एक अशक्त लौटाती हैं।
जॉब

3

इस उदाहरण में आपके दो खंड सीधे संबंधित हैं, इसलिए दूसरा रूप बेहतर है।

यदि वे संबंधित नहीं थे (उदाहरण के लिए विभिन्न स्थितियों पर गार्ड क्लॉज की एक श्रृंखला) तो मैं 1 फॉर्म को प्राथमिकता दूंगा (या मैं नाम के साथ एक विधि को फिर से तैयार करूंगा जो यह दर्शाता है कि यौगिक स्थिति वास्तव में क्या दर्शाती है)।


1

यदि आप डेल्फी में काम करते हैं, तो पहला तरीका सामान्य रूप से सुरक्षित है। (दिए गए उदाहरण के लिए, नेस्टेड ifs का उपयोग करने से बहुत कुछ हासिल नहीं होता है।)

डेल्फी आपको संकलक स्विच के माध्यम से यह निर्दिष्ट करने की अनुमति देता है कि बूलियन अभिव्यक्ति का मूल्यांकन या "शॉर्ट सर्किट" है या नहीं। # 1 करने का तरीका (नेस्टेड इफ्स) आपको यह सुनिश्चित करने की अनुमति देता है कि दूसरा क्लॉज यदि और केवल (और सख्ती से ) के बाद निष्पादित होता है, तो पहला क्लॉज सही मूल्यांकन करता है।


1
डेल्फी विकास के 23 वर्षों में मैंने कभी भी "पूर्ण बूलियन eval" विकल्प नहीं बदला है। अगर मैं कहीं और शिपिंग कोड होता तो मैं यूनिट में {$ BOOLEVAL OFF} या {$ B-} डालता।
गेरी

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

@ चेरी: सहमत। एकमात्र कारण जो आप संभवतः पूर्ण मूल्यांकन चाहते हैं, वह है दुष्प्रभाव - और एक सशर्त में दुष्प्रभाव एक बुरा विचार है!
लोरेन Pechtel

बस मेरी टिप्पणी को फिर से पढ़ें 23 साल 13 होना चाहिए! मैं एक Tardis की जरूरत नहीं है
गेरी

1

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


2
ऐसा इसलिए है क्योंकि VBA एक भयानक भाषा है
फल्मरी

@Falmarri, इसके बारे में कुछ भयानक चीजें हैं (और कुछ अच्छी चीजें)। अगर मेरे पास मेरे शराबी होते तो मैं बहुत सारी चीजें ठीक करता।

2
शॉर्ट-सर्किट बूलियन मूल्यांकन की कमी किसी भी चीज़ से अधिक विरासत की चीज है। पता नहीं क्यों उन्होंने इसके साथ शुरुआत नहीं की। OrElse और AndAlso का VB.NET "फिक्स" थोड़े परेशान करने वाला है, लेकिन शायद पिछड़े अनुकूलता को तोड़े बिना इससे निपटने का एकमात्र विकल्प है।
जॉन एफएक्स

1

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


0

मुझे लगता है कि वे दोनों पठनीय हैं, और मैं इस तर्क को स्वीकार नहीं करता हूं कि यदि आप भाषाओं को स्विच करने के लिए थे, तो आपको कोड रखरखाव की चिंता करनी चाहिए।

कुछ भाषाओं में दूसरा विकल्प बेहतर प्रदर्शन करता है इसलिए यह स्पष्ट विकल्प होगा।


0

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

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


0

मैं दूसरा विकल्प पसंद करता हूं, क्योंकि यह अधिक पठनीय है।

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


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