शॉर्ट सर्किट मूल्यांकन, क्या यह बुरा अभ्यास है?


88

कुछ ऐसा जो मुझे थोड़ी देर के लिए जाना जाता है, लेकिन कभी नहीं माना जाता है कि अधिकांश भाषाओं में ऑपरेटरों को प्राथमिकता देना संभव है अगर उनके आदेश के आधार पर। मैं अक्सर इसे शून्य संदर्भ अपवादों को रोकने के लिए एक तरीके के रूप में उपयोग करता हूं, उदाहरण के लिए:

if (smartphone != null && smartphone.GetSignal() > 50)
{
   // Do stuff
}

इस मामले में कोड पहले जाँच करेगा कि ऑब्जेक्ट अशक्त नहीं है और फिर इस वस्तु का उपयोग करके यह जानना कि यह मौजूद है। भाषा चतुर है क्योंकि यह जानती है कि यदि पहला कथन यदि गलत है तो दूसरा कथन का मूल्यांकन करने का कोई मतलब नहीं है और इसलिए एक शून्य संदर्भ अपवाद कभी नहीं फेंका जाता है। यह ऑपरेटरों andऔर orऑपरेटरों के लिए समान काम करता है ।

यह अन्य स्थितियों में भी उपयोगी हो सकता है जैसे कि यह जाँचना कि एक सूचकांक किसी सरणी की सीमा में है और इस तरह की तकनीक को विभिन्न भाषाओं में, मेरी जानकारी के लिए: जावा, सी #, सी ++, पायथन और मैटलैब में किया जा सकता है।

मेरा प्रश्न है: क्या इस तरह का कोड बुरे व्यवहार का प्रतिनिधित्व करता है? क्या यह बुरी प्रथा कुछ छिपे हुए तकनीकी मुद्दे से उत्पन्न होती है (अर्थात यह अंततः एक त्रुटि हो सकती है) या क्या यह अन्य प्रोग्रामर के लिए पठनीयता की ओर ले जाती है? क्या यह भ्रामक हो सकता है?


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

3
अधिकांश भाषाओं ने आपको चुना है कि आपको क्या व्यवहार चाहिए। सी # में ऑपरेटर ||शॉर्ट-सर्किट, ऑपरेटर |(एकल पाइप) नहीं करता है ( &&और &समान व्यवहार करता है)। जैसा कि शॉर्ट-सर्किट ऑपरेटरों का अधिक बार उपयोग किया जाता है, मैं गैर-शॉर्ट-सर्किट वाले लोगों के usages को एक टिप्पणी के साथ चिह्नित करने की सलाह देता हूं ताकि आपको यह समझाया जा सके कि आपको उनके व्यवहार की आवश्यकता क्यों है (ज्यादातर तरीके इनवोकेशन जैसी चीजें जो सभी को होनी चाहिए)।
linac

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

14
@linac: C और C ++ में, &&शॉर्ट-सर्किट है और &नहीं है, लेकिन वे बहुत अलग ऑपरेटर हैं। &&एक तार्किक "और" है; &एक बिटवाइज़ है "और"। झूठे होते x && yहुए भी सच होना संभव x & yहै।
कीथ थॉम्पसन

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

जवाबों:


125

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

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

कैविएट के कुछ जोड़े:

जटिलता और पठनीयता के संबंध में सामान्य ज्ञान का उपयोग करें

निम्नलिखित एक अच्छा विचार नहीं है:

if ((text_string != null && replace(text_string,"$")) || (text_string = get_new_string()) != null)

अपने कोड में लाइनों को कम करने के कई "चतुर" तरीकों की तरह, इस तकनीक पर निर्भरता के परिणामस्वरूप हार्ड-टू-समझने, त्रुटि-प्रवण कोड हो सकता है।

यदि आपको त्रुटियों को संभालने की आवश्यकता है, तो अक्सर बेहतर तरीका होता है

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

एक ही स्थिति की बार-बार जांच से बचें

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

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


12
यह ध्यान दिया जाना चाहिए कि यदि एक शॉर्ट-सर्किट मूल्यांकन में कोई नल अशक्त है तो जाँच करने वाले ब्लॉक शायद एक बार चेक करने के लिए फिर से लिखे जाएं।
नील

1
@ नील, अच्छी बात; मैंने जवाब अपडेट किया।

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

1
@ dan1111 मैं आपके द्वारा दिए गए उदाहरण को सामान्य करूंगा "एक शर्त में साइड इफेक्ट नहीं होना चाहिए (जैसे कि ऊपर वेरिएबल असाइनमेंट)। शॉर्ट-सर्किट मूल्यांकन में यह बदलाव नहीं होता है और इसे साइड के लिए शॉर्ट-हैंड के रूप में उपयोग नहीं किया जाना चाहिए- प्रभाव जो आसानी से अगर / फिर संबंध का बेहतर प्रतिनिधित्व करने के लिए के शरीर में आसानी से रखा जा सकता था। "
एरोनल्स

@AaronLS, मैं इस दावे से पूरी तरह असहमत हूं कि "एक शर्त में साइड-इफ़ेक्ट नहीं होना चाहिए"। एक स्थिति को अनावश्यक रूप से भ्रमित नहीं किया जाना चाहिए, लेकिन जब तक यह स्पष्ट कोड है, मैं एक स्थिति में साइड इफेक्ट (या एक से अधिक साइड इफेक्ट) के साथ ठीक हूं।

26

मान लीजिए कि आप बिना किसी &&प्रश्न के सी-स्टाइल भाषा का उपयोग कर रहे हैं और आपको अपने प्रश्न के समान समकक्ष कोड करने की आवश्यकता है।

आपका कोड होगा:

if(smartphone != null)
{
  if(smartphone.GetSignal() > 50)
  {
    // Do stuff
  }
}

यह पैटर्न बहुत कुछ बदल जाएगा।

अब हमारी काल्पनिक भाषा के संस्करण 2.0 की कल्पना करें &&। सोचिये कितना अच्छा लगता होगा आपको!

&&ऊपर मेरे उदाहरण क्या करता है की मान्यता प्राप्त, मुहावरेदार साधन है। इसका उपयोग करने के लिए यह बुरा अभ्यास नहीं है, वास्तव में यह खराब अभ्यास है जो उपरोक्त मामलों में इसका उपयोग नहीं करता है: ऐसी भाषा में एक अनुभवी कोडर सोच रहा होगा elseकि सामान्य फैशन में चीजें नहीं करने के लिए कहां या अन्य कारण था।

भाषा चतुर है क्योंकि यह जानती है कि यदि पहला कथन यदि गलत है तो दूसरा कथन का मूल्यांकन करने का कोई मतलब नहीं है और इसलिए एक शून्य संदर्भ अपवाद कभी नहीं फेंका जाता है।

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

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

विचार करें:

if(smartphone != null && smartphone.GetSignal() > ((range = (range != null ? range : GetRange()) != null && range.Valid ? range.MinSignal : 50)

यह जाँचने के लिए आपके कोड का विस्तार करता है range। यदि rangeयह अशक्त है तो यह एक कॉल द्वारा इसे सेट करने का प्रयास करता है, GetRange()हालांकि यह विफल हो सकता है इसलिए rangeअभी भी अशक्त हो सकता है। यदि इसके बाद सीमा शून्य नहीं है, और यह Validतब है तो इसकी MinSignalसंपत्ति का उपयोग किया जाता है, अन्यथा डिफ़ॉल्ट का 50उपयोग किया जाता है।

यह &&भी निर्भर करता है, लेकिन इसे एक पंक्ति में रखना शायद बहुत चालाक है (मैं 100% निश्चित नहीं हूं कि मेरे पास यह सही है, और मैं डबल-चेक करने नहीं जा रहा हूं क्योंकि यह तथ्य मेरी बात को प्रदर्शित करता है)।

&&हालांकि, यह यहाँ समस्या नहीं है, लेकिन एक अभिव्यक्ति (एक अच्छी बात) में बहुत कुछ डालने के लिए इसका उपयोग करने की क्षमता अनावश्यक रूप से (एक बुरी चीज) को समझने के लिए कठिन अभिव्यक्ति लिखने की हमारी क्षमता को बढ़ाती है।

इसके अलावा:

if(smartphone != null && (smartphone.GetSignal() == 2 || smartphone.GetSignal() == 5 || smartphone.GetSignal() == 8 || smartPhone.GetSignal() == 34))
{
  // do something
}

यहाँ मैं &&कुछ मानों के लिए एक चेक के उपयोग का संयोजन कर रहा हूँ । यह फोन सिग्नल के मामले में यथार्थवादी नहीं है, लेकिन अन्य मामलों में सामने आता है। यहाँ, यह मेरे द्वारा पर्याप्त रूप से चतुर नहीं होने का एक उदाहरण है। यदि मैंने निम्नलिखित कार्य किया है:

if(smartphone != null)
{
  switch (smartphone.GetSignal())
  {
    case 2: case 5: case 8: case 34:
      // Do something
      break;
  }
}

मैंने दोनों पठनीयता में वृद्धि की है और प्रदर्शन में भी संभावना है (कई कॉल GetSignal()संभवत: दूर अनुकूलित नहीं होंगे)।

यहाँ समस्या फिर से इतनी नहीं है &&कि उस विशेष हथौड़े को लेना और बाकी सब कुछ एक नाखून के रूप में देखना; इसका उपयोग नहीं करने से मुझे इसका उपयोग करने की तुलना में कुछ बेहतर करने में मदद मिलती है।

सबसे अच्छा अभ्यास से दूर जाने वाला एक अंतिम मामला है:

if(a && b)
{
  //do something
}

की तुलना में:

if(a & b)
{
  //do something
}

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

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

पहला हालांकि इसकी एक और शाखा भी है। विचार करें कि क्या हम इसे अपनी काल्पनिक सी-शैली की भाषा में फिर से लिखते हैं &&:

if(a)
{
  if(b)
  {
    // Do something
  }
}

वह अतिरिक्त ifहमारे उपयोग में छिपा है &&, लेकिन यह अभी भी है। और जैसा कि यह एक ऐसा मामला है जहां शाखा भविष्यवाणी हो रही है और संभवतः इसलिए शाखा गलत भविष्यवाणी है।

उस कारण से if(a & b)कोड कुछ मामलों में अधिक कुशल हो सकता है।

यहाँ मैं कहूंगा कि if(a && b)अभी भी इसके साथ शुरू करने के लिए सबसे अच्छा अभ्यास दृष्टिकोण है: अधिक सामान्य, कुछ मामलों में केवल एक व्यवहार्य (जहां गलत bहोगा तो त्रुटि होगी a) और अधिक से अधिक बार नहीं। यह ध्यान देने योग्य है कि if(a & b)अक्सर कुछ मामलों में इस पर एक उपयोगी अनुकूलन होता है।


1
अगर किसी के पास सफलता के मामले में tryवापसी के तरीके हैं true, तो आप क्या सोचते हैं if (TryThis || TryThat) { success } else { failure }? यह एक कम कॉमन मुहावरा है, लेकिन मुझे पता नहीं है कि कोड डुप्लीकेशन या फ्लैग जोड़े बिना एक ही चीज़ को कैसे पूरा किया जाए। जबकि एक ध्वज के लिए आवश्यक मेमोरी एक गैर-मुद्दा होगी, विश्लेषण के दृष्टिकोण से, एक ध्वज को जोड़ने से प्रभावी रूप से कोड को दो समानांतर ब्रह्मांडों में विभाजित किया जाता है - एक जिसमें ऐसे बयान होते हैं जो ध्वज के पहुंचते समय पहुंच योग्य होते हैं trueऔर दूसरा एक बयान तब पहुंचता है जब यह होता है false। कभी-कभी DRY के नजरिए से अच्छा है, लेकिन icky।
सुपरकैट

5
मुझे कुछ भी गलत नहीं दिखता if(TryThis || TryThat)
जॉन हैना

3
लानत ठीक जवाब, सर।
बिशप

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

यदि (a && b) कथन; यथोचित रूप से प्रतिस्थापित करना आसान है। if (a && b && c && d) statement1; और कथन 2; एक वास्तविक दर्द है।
gnasher729

10

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

open($handle, "<", "filename.txt") or die "Couldn't open file!";

मुहावरेदार है। openसफलता के लिए कुछ नॉनज़रो लौटाता है (ताकि कभी न होने वाला dieहिस्सा or), लेकिन विफलता पर अपरिभाषित हो, और फिर कॉल करने के लिए dieहोता है (जो कि अपवाद को बढ़ाने के लिए पर्ल का तरीका है)।

यह उन भाषाओं में ठीक है जहां हर कोई इसे करता है।


17
पर्ल टू लैंग्वेज डिज़ाइन का सबसे बड़ा योगदान यह है कि इसे करने के कई उदाहरण दिए गए हैं।
जैक एदले

@JackAidley: मुझे पर्ल की याद आती है unless, और पोस्टफिक्स की स्थिति ( send_mail($address) if defined $address)।
रेमकोगर्लिच

6
@JackAidley क्या आपको संकेत दे सकता है कि 'या मरना' बुरा क्यों है? क्या यह अपवादों को संभालने का सिर्फ एक भोला तरीका है?
बिगस्टोन

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

1
@RemcoGerlich रूबी को कुछ इस तरह की शैली विरासत में मिली:send_mail(address) if address
bonh

6

जबकि मैं आमतौर पर dan1111 के उत्तर से सहमत हूं , एक विशेष रूप से महत्वपूर्ण मामला है जो इसे कवर नहीं करता है: वह मामला जहां smartphoneसमवर्ती रूप से उपयोग किया जाता है। उस परिदृश्य में, इस तरह का पैटर्न बग्स को खोजने के लिए कठिन का एक प्रसिद्ध स्रोत है।

समस्या यह है कि शॉर्ट सर्किट मूल्यांकन परमाणु नहीं है। आपका धागा जांच कर सकते हैं कि smartphoneहै null, एक और धागा में आ सकते हैं और यह रद्द, और फिर अपने धागा तुरंत करने की कोशिश करता GetSignal()है और ऊपर चल रही है।

लेकिन जाहिर है, यह केवल करता है कि जब सितारों संरेखित और अपने धागे 'समय है सिर्फ सही।

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


3

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

तो तार्किक अभिव्यक्तियों की गारंटी शॉर्ट सर्किट मूल्यांकन के लिए एक बड़ी आवश्यकता थी। यह पास्कल (जिसमें गैर-गारंटीकृत शॉर्ट सर्किट मूल्यांकन था) में मौजूद नहीं था जो एक प्रमुख दर्द था; मैंने इसे पहली बार एडा और सी में देखा है।

यदि आपको वास्तव में लगता है कि यह "बुरा अभ्यास" है, तो कृपया किसी भी जटिल जटिल बिट कोड को लें, इसे फिर से लिखें ताकि यह शॉर्ट सर्किट मूल्यांकन के बिना ठीक काम करेगा, और वापस आकर हमें बताएगा कि आपको यह कैसे पसंद आया। यह बताया जा रहा है कि सांस लेने से कार्बन डाइऑक्साइड पैदा होती है और यह पूछा जाता है कि क्या सांस लेना एक बुरा अभ्यास है। इसके बिना कुछ मिनट के लिए प्रयास करें।


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

2

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

if (currentUser && currentUser.isAdministrator()) 
  doSomething();

बस होने के लिए सरलीकृत किया जा सकता है:

if (currentUser.isAdministrator())
  doSomething ();

यदि currentUserउपयोगकर्ता लॉग इन नहीं है, तो कुछ 'अनाम उपयोगकर्ता' या 'अशक्त उपयोगकर्ता' को एक डिफ़ॉल्ट कार्यान्वयन के साथ डिफ़ॉल्ट किया जाता है।

नहीं हमेशा एक कोड गंध है, लेकिन कुछ विचार करने के लिए।


-4

मैं अलोकप्रिय होने जा रहा हूं और कहता हूं हां, यह बुरा है। यदि आपके कोड की कार्यक्षमता सशर्त तर्क को लागू करने के लिए उस पर निर्भर है।

अर्थात

 if(quickLogicA && slowLogicB) {doSomething();}

अच्छा है, लेकिन

if(logicA && doSomething()) {andAlsoDoSomethingElse();}

बुरा है, और निश्चित रूप से कोई भी इससे सहमत नहीं होगा ?!

if(doSomething() || somethingElseIfItFailed() && anotherThingIfEitherWorked() & andAlwaysThisThing())
{/* do nothing */}

तर्क:

यदि दोनों पक्षों का मूल्यांकन केवल तर्क नहीं करने के बजाय आपका कोड त्रुटियां हैं। यह तर्क दिया गया है कि यह कोई समस्या नहीं है, 'और' ऑपरेटर को c # में परिभाषित किया गया है, इसलिए अर्थ स्पष्ट है। हालांकि, मैं तर्क देता हूं कि यह सच नहीं है।

कारण 1. ऐतिहासिक

अनिवार्य रूप से आप अपने कोड में कार्यक्षमता प्रदान करने के लिए एक कंपाइलर ऑप्टिमाइज़ेशन (जो मूल रूप से इरादा था) पर भरोसा कर रहे हैं।

हालांकि c # में भाषा विनिर्देश बूलियन की गारंटी देता है 'और' ऑपरेटर लघु परिचलन करता है। यह सभी भाषाओं और संकलक के लिए सही नहीं है।

wikipeda विभिन्न भाषाओं और उनकी छोटी-मोटी परिक्रमा को http://en.wikipedia.org/wiki/Short-circuit_evaluation पर सूचीबद्ध करता है क्योंकि आपके पास कई दृष्टिकोण हैं। और अतिरिक्त समस्याओं की एक जोड़ी मैं यहाँ नहीं जाना है।

विशेष रूप से, फोरट्रान, पास्कल और डेल्फी में संकलक झंडे हैं जो इस व्यवहार को टॉगल करते हैं।

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

कारण 2. भाषा भेद

जैसा कि आप विकिपीडिया से देख सकते हैं, सभी भाषाएं शॉर्ट सर्किटिंग के लिए समान दृष्टिकोण नहीं लेती हैं, तब भी जब वे निर्दिष्ट करते हैं कि बूलियन ऑपरेटरों को इसे कैसे संभालना चाहिए।

विशेष रूप से VB.Net के 'और' ऑपरेटर में शॉर्ट सर्किट नहीं होता है और TSQL में कुछ ख़ासियतें होती हैं।

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

कारण 3. किसी भाषा के भीतर का अंतर

उदाहरण के लिए VB की इनलाइन यदि इसके से भिन्न व्यवहार करती है। आधुनिक अनुप्रयोगों में फिर से आपका कोड बीच में आ सकता है, उदाहरण के लिए पीछे कोड और इनलाइन वेबफॉर्म, आपको अर्थ में अंतर के बारे में पता होना चाहिए।

कारण 4. किसी फ़ंक्शन के पैरामीटर की जांच करने वाला नल का आपका विशिष्ट उदाहरण

यह बहुत अच्छा उदाहरण है। इसमें वह कुछ है जो हर कोई करता है, लेकिन वास्तव में बुरा व्यवहार है जब आप इसके बारे में सोचते हैं।

इस तरह के चेक को देखना बहुत ही सामान्य है क्योंकि यह आपके कोड की लाइनों को काफी कम कर देता है। मुझे संदेह है कि कोई भी इसे एक कोड समीक्षा में लाएगा। (और स्पष्ट रूप से टिप्पणियों और रेटिंग से आप देख सकते हैं कि यह लोकप्रिय है!)

हालांकि, यह एक से अधिक कारणों से सर्वोत्तम अभ्यास में विफल रहता है!

  1. कई स्रोतों से यह बहुत स्पष्ट है, सबसे अच्छा अभ्यास यह है कि वैधता के लिए अपने मापदंडों की जांच करने से पहले आप उनका उपयोग करें और यदि वे अमान्य हैं तो अपवाद फेंक दें। आपका कोड स्निपेट आसपास के कोड को प्रदर्शित नहीं करता है, लेकिन आपको शायद कुछ ऐसा करना चाहिए:

    if (smartphone == null)
    {
        //throw an exception
    }
    // perform functionality
  2. आप सशर्त विवरण के भीतर से एक समारोह बुला रहे हैं । यद्यपि आपके फ़ंक्शन का नाम यह बताता है कि यह केवल एक मूल्य की गणना करता है, यह साइड इफेक्ट्स को छिपा सकता है। जैसे

    Smartphone.GetSignal() { this.signal++; return this.signal; }
    
    else if (smartphone.GetSignal() < 1)
    {
        // Do stuff 
    }
    else if (smartphone.GetSignal() < 2)
    {
        // Do stuff 
    }

    सर्वोत्तम अभ्यास सुझाएगा:

    var s = smartphone.GetSignal();
    if(s < 50)
    {
        //do something
    }

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

मुझे लगता है कि आप पाएंगे कि अन्य सामान्य उपयोगों के लिए भी यही स्थिति है। आपको याद रखना होगा कि हमारे पास भी है:

इनलाइन सशर्तियां

var s = smartphone!=null ? smartphone.GetSignal() : 0;

और अशक्त सहानुभूति

var s = smartphoneConnectionStatus ?? "No Connection";

जो अधिक स्पष्टता के साथ समान शॉर्ट कोड लंबाई कार्यक्षमता प्रदान करते हैं

मेरे सभी बिंदुओं का समर्थन करने के लिए कई लिंक:

https://stackoverflow.com/questions/1158614/what-is-the-best-practice-in-case-one-argument-is-null

कंस्ट्रक्टर पैरामीटर सत्यापन सी # में - सर्वोत्तम प्रथाओं

क्या किसी को अशक्त होने की जांच करनी चाहिए, यदि वह अशक्त होने की उम्मीद नहीं करता है?

https://msdn.microsoft.com/en-us/library/seyhszts%28v=vs.110%29.aspx

https://stackoverflow.com/questions/1445867/why-would-a-language-not-use-short-circuit-evaluation

http://orcharddojo.net/orchard-resources/Library/DevelopmentGuidelines/BestPractices/CSharp

संकलक झंडे के उदाहरण जो लघु परिचलन को प्रभावित करते हैं:

फोरट्रान: "sce | nosce डिफ़ॉल्ट रूप से, कंपाइलर XL Fortran नियमों का उपयोग करते हुए चयनित तार्किक अभिव्यक्तियों में शॉर्ट सर्किट मूल्यांकन करता है। sce को निर्दिष्ट करने से कंपाइलर गैर-XL Fortran नियमों का उपयोग करने की अनुमति देता है। कंपाइलर शॉर्ट सर्किट मूल्यांकन करेगा यदि वर्तमान नियम इसकी अनुमति देते हैं। । डिफ़ॉल्ट डिफ़ॉल्ट है। "

पास्कल: "बी - एक ध्वज निर्देशन जो शॉर्ट-सर्किट मूल्यांकन को नियंत्रित करता है। शॉर्ट-सर्किट मूल्यांकन के बारे में अधिक जानकारी के लिए डियाडिक ऑपरेटरों के संचालन के मूल्यांकन के आदेश। अधिक जानकारी के लिए कमांड-लाइन कंपाइलर के लिए -sc कंपाइलर विकल्प भी देखें। उपयोगकर्ता के मैनुअल में दस्तावेजित)। "

डेल्फी: "डेल्फी डिफ़ॉल्ट रूप से शॉर्ट सर्किट मूल्यांकन का समर्थन करता है। इसे {$ BOOLEVAL OFF} संकलक निर्देश का उपयोग करके बंद किया जा सकता है।"


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