यदि आप बड़ी स्थितियों को कैसे संभालेंगे?

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

क्या कोई अन्य विधियां हैं जो आपको मिली हैं जो मेरे और किसी और के लिए उपयोग की जा सकती हैं जो एक ही समस्या को प्रभावित करती है?

उदाहरण, सब एक पंक्ति पर:

if (var1 = true && var2 = true && var2 = true && var3 = true && var4 = true && var5 = true && var6 = true)
{

उदाहरण, बहु-पंक्ति:

if (var1 = true && var2 = true && var2 = true
 && var3 = true && var4 = true && var5 = true
 && var6 = true)
{

उदाहरण-नेस्टेड:

if (var1 = true && var2 = true && var2 = true && var3 = true)
{
     if (var4 = true && var5 = true && var6 = true)
     {
0
ro fr bn

21 उत्तर

मैं अलग बुलियन मूल्यों का सहारा लेता हूं:

Bool cond1 == (var1 && var2);
Bool cond2 == (var3 && var4);

if ( cond1 && cond2 ) {}
0
जोड़ा

मैकडोवेल,

You are correct that when using the single '&' operator that both sides of the expression evaluate. However, when using the '&&' operator (at least in C#) then the first expression to return false is the last expression evaluated. This makes putting the evaulation before the FOR statement just as good as any other way of doing it.

0
जोड़ा

जैसा कि अन्य ने उल्लेख किया है, मैं आपकी सशर्तताओं का विश्लेषण करने के लिए विश्लेषण करता हूं कि क्या कोई तरीका है कि आप इसे पठनीयता बढ़ाने के लिए अन्य तरीकों से आउटसोर्स कर सकते हैं।

0
जोड़ा

मैंने देखा है कि बहुत से लोग और संपादक या तो एक टैब के साथ अपने कथन में प्रत्येक शर्त को इंडेंट करते हैं, या खुले माता-पिता से मेल खाते हैं:

if (var1 == true
    && var2 == true
    && var3 == true
   ) {
    /* do something.. */
}

मैं आमतौर पर अंतिम स्थिति के रूप में एक ही पंक्ति पर करीबी माता पिता डाल दिया:

if (var1 == true
    && var2 == true
    && var3 == true) {
    /* do something.. */
}

लेकिन मुझे नहीं लगता कि यह काफी साफ है।

0
जोड़ा

केंट बेक द्वारा कार्यान्वयन पैटर्न देखें। एक विशेष पैटर्न है जिसके बारे में मैं सोच रहा हूं जो इस स्थिति में मदद कर सकता है ... इसे "गार्ड" कहा जाता है। कई स्थितियों के बजाय, आप उन्हें एक गार्ड में तोड़ सकते हैं, जो यह स्पष्ट करता है कि किसी विधि में प्रतिकूल परिस्थितियां कौन सी हैं।

तो उदाहरण के लिए, यदि आपके पास कोई तरीका है जो कुछ करता है, लेकिन कुछ ऐसी स्थितियां हैं जहां इसे कुछ नहीं करना चाहिए, इसके बजाए:

public void doSomething() {
    if (condition1 && condition2 && condition3 && condition4) {
        // do something
    }
}

आप इसे बदल सकते हैं:

public void doSomething() {
    if (!condition1) {
        return;
    }

    if (!condition2) {
        return;
    }

    if (!condition3) {
        return;
    }

    if (!condition4) {
        return;
    }

    // do something
}

यह थोड़ा और वर्बोज़ है, लेकिन बहुत अधिक पठनीय है, खासकर जब आप अजीब घोंसले शुरू करते हैं, तो गार्ड मदद कर सकता है (विधियों को निकालने के साथ संयुक्त)।

मैं उस पुस्तक को जिस तरह से अनुशंसा करता हूं।

0
जोड़ा
'फास्ट रिटर्न' मारता है 'तीर-सिर' विरोधी पैटर्न भी :)
जोड़ा लेखक Arnis Lapsa, स्रोत
मैं असहमत हूं कि ये गार्ड इसे पढ़ने में आसान बनाते हैं। "जटिल" स्थिति पर एक टिप्पणी बेहतर होगी।
जोड़ा लेखक Randy Stegbauer, स्रोत

@tweakt

It's no better, but what I've done in the past:

boolean ok = cond1; ok &= cond2; ok &= cond3; ok &= cond4; ok &= cond5; ok &= cond6;

Which is the same as:

ok = (cond1 && cond2 && cond3 && cond4 && cond5 && cond6);

असल में, ये दो चीजें ज्यादातर भाषाओं में समान नहीं हैं। दूसरी अभिव्यक्ति आमतौर पर मूल्यांकन की जा रही है जैसे ही शर्तों में से एक झूठी है, जो स्थिति का मूल्यांकन महंगा होने पर एक बड़ा प्रदर्शन सुधार हो सकता है।

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

do {
    if (!cond1)
       break;
    if (!cond2)
       break;
    if (!cond3)
       break;
    ...
    DoSomething();
} while (false);

जबकि (झूठी) चीज की तरह है। मेरी इच्छा है कि भाषाओं में "एक बार" या कुछ ऐसा कहा जा सके जिसे आप आसानी से तोड़ सकते हैं।

0
जोड़ा
यह मूल कोड से बेहतर नहीं है।
जोड़ा लेखक Randy Stegbauer, स्रोत

अगर तुम यह करते हो:

if (var1 == true) {
    if (var2 == true) {
        if (var3 == true) {
            ...
        }
    }
}

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

0
जोड़ा
क्षैतिज स्क्रॉल बार - सक्रिय करें !!! 11eleven
जोड़ा लेखक Arnis Lapsa, स्रोत
यह शायद इस सवाल का सबसे बुरा समाधान है।
जोड़ा लेखक Brad Gilbert, स्रोत

मैं अक्सर इन्हें घटक बुलियन वैरिएबल में विभाजित कर दूंगा:

bool orderValid = orderDate < DateTime.Now && orderStatus != Status.Canceled;
bool custValid = customerBalance == 0 && customerName != "Mike";
if (orderValid && custValid)
{
...
0
जोड़ा

कई बुलियन में स्थिति को अलग करें और फिर स्थिति के रूप में एक मास्टर बूलियन का उपयोग करें।

bool isOpaque = object.Alpha == 1.0f;
bool isDrawable = object.CanDraw && object.Layer == currentLayer;
bool isHidden = hideList.Find(object);

bool isVisible = isOpaque && isDrawable && ! isHidden;

if(isVisible)
{
    // ...
}

और भी बेहतर:

public bool IsVisible {
    get
    {
        bool isOpaque = object.Alpha == 1.0f;
        bool isDrawable = object.CanDraw && object.Layer == currentLayer;
        bool isHidden = hideList.Find(object);

        return isOpaque && isDrawable && ! isHidden;
    }
}

void Draw()
{
     if(IsVisible)
     {
         // ...
     }
}

सुनिश्चित करें कि आप अपने चर नाम दें जो वास्तव में कार्य के बजाय इरादे को इंगित करते हैं। यह डेवलपर को आपके कोड को बनाए रखने में बहुत मदद करेगा ... यह आप हो सकता है!

0
जोड़ा
सरल, आसान करने के लिए, और प्रभावी।
जोड़ा लेखक Graham Clark, स्रोत

मुझे आश्चर्य है कि अभी तक कोई भी यह नहीं मिला है। इस प्रकार की समस्या के लिए विशेष रूप से एक रिफैक्टरिंग है:

http://www.refactoring.com/catalog/decomposeConditional.html

0
जोड़ा
मुझे सशर्त विघटन करना पसंद नहीं है, क्योंकि यह एक-दूसरे के कार्यों के साथ कोड संरचना को प्रदूषित करता है जो पुन: प्रयोज्य नहीं होते हैं। मैं संबंधित चेक के प्रत्येक "समूह" के लिए टिप्पणियों के साथ एक बड़ा IF कथन होगा।
जोड़ा लेखक Milan Babuškov, स्रोत

सबसे पहले, मैं सभी == true भागों को हटा दूंगा, जो इसे 50% छोटा कर देगा;)

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

कभी-कभी मैं बूलियन अभिव्यक्तियों को थोड़ा सा सरल बनाने के लिए डी-मॉर्गन के नियम का उपयोग करता हूं।

0
जोड़ा

यदि आप पाइथन में प्रोग्रामिंग करते हैं, तो यह आपके चर के सूची में अंतर्निहित all() फ़ंक्शन के साथ एक सिंच है (मैं यहां केवल बूलियन अक्षरों का उपयोग करूंगा):

>>> L = [True, True, True, False, True]
>>> all(L) # True, only if all elements of L are True.
False
>>> any(L) # True, if any elements of L are True.
True

क्या आपकी भाषा में कोई संबंधित कार्य है (सी #? जावा?)। यदि ऐसा है, तो यह संभवतः सबसे साफ दृष्टिकोण है।

0
जोड़ा

खैर, पहले बंद, क्यों नहीं:

if (var1 && var2 && var2 && var3 && var4 && var5 && var6) {
...

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

यह कोई बेहतर नहीं है, लेकिन मैंने पहले क्या किया है: (निम्न विधि शॉर्ट-सर्किटिंग बूलियन परीक्षण को रोकती है, सभी परीक्षण तब भी चलते हैं जब पहला झूठा होता है। अनुशंसित पैटर्न नहीं जब तक आपको पता न हो कि आपको हमेशा वापस आने से पहले सभी कोड निष्पादित करने की आवश्यकता है - मेरी गलती को ढूंढने के लिए पीटीमैटो के लिए धन्यवाद!)

boolean ok = cond1;
ok &= cond2;
ok &= cond3;
ok &= cond4;
ok &= cond5;
ok &= cond6;

Which is the same as: (not the same, see above note!)

ok = (cond1 && cond2 && cond3 && cond4 && cond5 && cond6);

0
जोड़ा
वाह। मुझे यह पता होना चाहिए था। मेरे अपने उत्तर में से एक पर मेरा पहला चेहरा ;-)
जोड़ा लेखक Mark Renouf, स्रोत
यह वही नहीं है यदि && ऑपरेटर शॉर्ट सर्किटिंग है।
जोड़ा लेखक ptomato, स्रोत

यहां संबोधित करने के लिए दो मुद्दे हैं: पठनीयता और समझदारी

"पठनीयता" समाधान एक शैली मुद्दा है और जैसा कि व्याख्या के लिए खुला है। मेरी वरीयता यह है:

if (var1 == true && // Explanation of the check
    var2 == true && // Explanation of the check
    var3 == true && // Explanation of the check
    var4 == true && // Explanation of the check
    var5 == true && // Explanation of the check
    var6 == true)   // Explanation of the check
    { }

या यह:

if (var1 && // Explanation of the check
    var2 && // Explanation of the check
    var3 && // Explanation of the check
    var4 && // Explanation of the check
    var5 && // Explanation of the check
    var6)   // Explanation of the check
    { }

उस ने कहा, इस तरह की जटिल जांच कोड स्कैन करते समय मानसिक रूप से पार्स करना मुश्किल हो सकती है (विशेष रूप से यदि आप मूल लेखक नहीं हैं)। जटिलता को दूर करने के लिए एक सहायक विधि बनाने पर विचार करें:

/// 
/// Tests whether all the conditions are appropriately met ///
 
private bool AreAllConditionsMet (
    bool var1,
    bool var2,
    bool var3,
    bool var4,
    bool var5,
    bool var6)
{
    return (
        var1 && // Explanation of the check
        var2 && // Explanation of the check
        var3 && // Explanation of the check
        var4 && // Explanation of the check
        var5 && // Explanation of the check
        var6);  // Explanation of the check
}

private void SomeMethod()
{
    // Do some stuff (including declare the required variables)
    if (AreAllConditionsMet (var1, var2, var3, var4, var5, var6))
    {
        // Do something
    }
}

अब जब "SomeMethod" विधि को दृष्टि से स्कैन किया जाता है, तो परीक्षण तर्क की वास्तविक जटिलता छिपी हुई है लेकिन अर्थशास्त्र का अर्थ मनुष्यों के लिए उच्च स्तर पर समझने के लिए संरक्षित है। यदि डेवलपर को वास्तव में विवरणों को समझने की आवश्यकता है, तो AreAllConditionsMet विधि की जांच की जा सकती है।

यह औपचारिक रूप से मुझे लगता है कि "विघटनशील सशर्त" रिफैक्टरिंग पैटर्न के रूप में जाना जाता है। Resharper या रिफैक्टर प्रो जैसे उपकरण! इस प्रकार के रिफैक्टरिंग को आसान बना सकते हैं!

सभी मामलों में, पठनीय और समझने योग्य कोड रखने की कुंजी यथार्थवादी परिवर्तनीय नामों का उपयोग करना है। जबकि मैं समझता हूं कि यह एक संक्षिप्त उदाहरण है, "var1", "var2", आदि स्वीकार्य परिवर्तनीय नाम नहीं हैं। उनके पास एक ऐसा नाम होना चाहिए जो उनके द्वारा प्रस्तुत डेटा की अंतर्निहित प्रकृति को दर्शाता हो।

0
जोड़ा

PHP जैसी प्रतिबिंबित भाषाओं में, आप चर-चर का उपयोग कर सकते हैं:

$vars = array('var1', 'var2', ... etc.);
foreach ($vars as $v)
    if ($$v == true) {
        // do something
        break;
    }
0
जोड़ा

Steve Mcconell's advice, from Code Complete: Use a multi-dimensional table. Each variable serves as an index to the table, and the if statement turns into a table lookup. For example if (size == 3 && weight > 70) translates into the table entry decision[size][weight_group]

0
जोड़ा

अगर मैं इसे पर्ल में कर रहा था, तो मैं चेक चला सकता हूं।

{
  last unless $var1;
  last unless $var2;
  last unless $var3;
  last unless $var4;
  last unless $var5;
  last unless $var6;

  ... # Place Code Here
}

यदि आप इसे subroutine पर उपयोग करने की योजना बनाते हैं तो last के प्रत्येक उदाहरण को return के साथ प्रतिस्थापित करें;

0
जोड़ा

मैं प्रत्येक हालत को वर्णनात्मक चर में तोड़ना पसंद करता हूं।

bool isVar1Valid, isVar2Valid, isVar3Valid, isVar4Valid;
isVar1Valid = ( var1 == 1 )
isVar2Valid = ( var2.Count >= 2 )
isVar3Valid = ( var3 != null )
isVar4Valid = ( var4 != null && var4.IsEmpty() == false )
if ( isVar1Valid && isVar2Valid && isVar3Valid && isVar4Valid ) {
     //do code
}
0
जोड़ा
व्यक्तिगत बूल बनाने में क्या बात है। साथ ही, आप प्रत्येक varX से true की तुलना करें और इसे isVarXValid bool पर असाइन करें, जो अनिवार्य रूप से केवल longhand के लिए है isVar1Valid = var , जो अनावश्यक है। आपके पास पहले से शुरू करने के लिए बूल हैं, तो क्यों न केवल अगर (var1 && var2 && var3 && var4)
जोड़ा लेखक dreamlax, स्रोत
@dreamlax आप सही हैं। मैंने एक खराब उदाहरण इस्तेमाल किया।
जोड़ा लेखक wusher, स्रोत

Functors और prredicates को देखने का प्रयास करें। Apache Commons प्रोजेक्ट में ऑब्जेक्ट्स में सशर्त तर्क को समाहित करने की अनुमति देने के लिए ऑब्जेक्ट्स का एक बड़ा सेट है। उनके उपयोग का उदाहरण O'reilly यहां । कोड उदाहरण का अंश:

import org.apache.commons.collections.ClosureUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.functors.NOPClosure;

Map predicateMap = new HashMap();

predicateMap.put( isHonorRoll, addToHonorRoll );
predicateMap.put( isProblem, flagForAttention );
predicateMap.put( null, ClosureUtils.nopClosure() );

Closure processStudents = 
    ClosureUtils.switchClosure( predicateMap );

CollectionUtils.forAllDo( allStudents, processStudents );

अब उन सभी का विवरण हैनोररोल भविष्यवाणी करता है और उनका मूल्यांकन करने के लिए उपयोग किए जाने वाले बंद:

import org.apache.commons.collections.Closure;
import org.apache.commons.collections.Predicate;

// Anonymous Predicate that decides if a student 
// has made the honor roll.
Predicate isHonorRoll = new Predicate() {
  public boolean evaluate(Object object) {
    Student s = (Student) object;

    return( ( s.getGrade().equals( "A" ) ) ||
            ( s.getGrade().equals( "B" ) && 
              s.getAttendance() == PERFECT ) );
  }
};

// Anonymous Predicate that decides if a student
// has a problem.
Predicate isProblem = new Predicate() {
  public boolean evaluate(Object object) {
    Student s = (Student) object;

    return ( ( s.getGrade().equals( "D" ) || 
               s.getGrade().equals( "F" ) ) ||
             s.getStatus() == SUSPENDED );
  }
};

// Anonymous Closure that adds a student to the 
// honor roll
Closure addToHonorRoll = new Closure() {
  public void execute(Object object) {
    Student s = (Student) object;

    // Add an award to student record
    s.addAward( "honor roll", 2005 );
    Database.saveStudent( s );
  }
};

// Anonymous Closure flags a student for attention
Closure flagForAttention = new Closure() {
  public void execute(Object object) {
    Student s = (Student) object;

    // Flag student for special attention
    s.addNote( "talk to student", 2005 );
    s.addNote( "meeting with parents", 2005 );
    Database.saveStudent( s );
  }
};
0
जोड़ा
अच्छा! मेथिंक के साथ डाउनलोड और खेलने के लिए एक।
जोड़ा लेखक toolkit, स्रोत

मैं उन्हें स्तर से तोड़ना पसंद करता हूं, इसलिए मैं आपको इस तरह का उदाहरण प्रारूपित करूंगा:

if (var1 = true
 && var2 = true
 && var2 = true
 && var3 = true
 && var4 = true
 && var5 = true
 && var6 = true){

यह आसान है जब आपके पास अधिक घोंसले होते हैं, इस तरह (स्पष्ट रूप से वास्तविक परिस्थितियों में सब कुछ के लिए "= सत्य" से अधिक दिलचस्प होगा):

if ((var1 = true && var2 = true)
 && ((var2 = true && var3 = true)
  && (var4 = true && var5 = true))
 && (var6 = true)){
0
जोड़ा
    if (   (condition_A)
        && (condition_B)
        && (condition_C)
        && (condition_D)
        && (condition_E)
        && (condition_F)
       )
    {
       ...
    }

विरोध के रूप में

    if (condition_A) {
       if (condition_B) {
          if (condition_C) {
             if (condition_D) {
                if (condition_E) {
                   if (condition_F) {
                      ...
                   }
                }
             }
          }
       }
    }

तथा

    if (   (   (condition_A)
            && (condition_B)
           )
        || (   (condition_C)
            && (condition_D)
           )
        || (   (condition_E)
            && (condition_F)
           )
       )
    {
       do_this_same_thing();
    }

विरोध के रूप में

    if (condition_A && condition_B) {
       do_this_same_thing();
    }
    if (condition_C && (condition_D) {
       do_this_same_thing();
    }
    if (condition_E && condition_F) {
       do_this_same_thing();
    }

Most of the static analysis tools for examining code will complain if multiple conditional expressions do not use explicit parenthesis dictating expression analysis, instead of relying on operator precedence rules तथा fewer parenthesis.

Vertical alignment at the same indent level of open/close braces {}, open close parenthesis (), conditional expressions with parenthesis तथा operators on the left is an very useful practice, which greatly ENHANCES readability तथा clarity of the code विरोध के रूप में jamming everything that can possibly be jammed onto a single line, sans vertical alignment, spaces or parenthesis

Operator precedence rules are tricky, e.g. && has higher precedence than ||, but | has precedence than &&

इसलिए, ...

    if (expr_A & expr_B || expr_C | expr_D & expr_E || expr_E && expr_F & expr_G || expr_H {
    }

is a really easy multiple conditional expression for mere humans to read तथा evaluate improperly.

    if (   (  (expr_A)
            & (expr_B)
           )
        || (  (expr_C)
            | (  (expr_D)
               & (expr_E)
              )
           )
        || (   (expr_E)
            && (  (expr_F)
                & (expr_G)
               )
           )
        || (expr_H)
       )
    {
    }

There is nothing wrong with horizontal space (linefeeds), vertical alignment, or explicit parenthesis guiding expression evaluation, all of which ENHANCES readability तथा clarity

0
जोड़ा