Instead of using nested if-else
-
Hi i have requirement like doing 10 steps to complete task After completion of one only i can enter into another I used nested if- else to do that like if (true) { if (true) { if (true) { return true; } else { } } else { } } else { } is there any better way to handle these type of situation Thanks in Advance
---------------------------- KRISHNA KUMAR T M
-
Hi i have requirement like doing 10 steps to complete task After completion of one only i can enter into another I used nested if- else to do that like if (true) { if (true) { if (true) { return true; } else { } } else { } } else { } is there any better way to handle these type of situation Thanks in Advance
---------------------------- KRISHNA KUMAR T M
Yes switch(i) { case 0: break; case 1: break; default: break; }
-
Yes switch(i) { case 0: break; case 1: break; default: break; }
How about:
if (expression1 &&
expression2 &&
expression3 &&
expression4 &&
...) ... //success
else //failure...or an uglier aproach:
try {
if (!expression1) throw 1;
if (!expression2) throw 2;
if (!expression3) throw 3;
...
} catch (int where)
{
//Do whatever here, "where" will even show you where the whole thing failed
}> The problem with computers is that they do what you tell them to do and not what you want them to do. <
-
Hi i have requirement like doing 10 steps to complete task After completion of one only i can enter into another I used nested if- else to do that like if (true) { if (true) { if (true) { return true; } else { } } else { } } else { } is there any better way to handle these type of situation Thanks in Advance
---------------------------- KRISHNA KUMAR T M
Usually this can be handled (as already suggested) with
try-catch
blocks or (using plainC
) with the (in)famousgoto
. You may also schedule a set of operation to be invoked inside a loop (for instance with an array of function pointers) and usebreak
to interrupt the iteration whenever needed (i.e. on any operation failure). :)If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler. -- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong. -- Iain Clarke
[My articles] -
How about:
if (expression1 &&
expression2 &&
expression3 &&
expression4 &&
...) ... //success
else //failure...or an uglier aproach:
try {
if (!expression1) throw 1;
if (!expression2) throw 2;
if (!expression3) throw 3;
...
} catch (int where)
{
//Do whatever here, "where" will even show you where the whole thing failed
}> The problem with computers is that they do what you tell them to do and not what you want them to do. <
The argument is "are guard clauses in methods okay?" And how do you handle resource cleanup if one of the guard clauses fail? I haven't seen a convincing consensus either way. A specific example: Let's say you have 10 resources to allocate (like opening files, networks, etc) -- for brevity here, let's just use four resources. All resources have to be allocated for the method to continue. So what we are trying to avoid is something like this (yuck):
isMethodSuccessful = false; // assume this isn't going to work
resource1 = OpenMyFile(myFile);
if (resource1 == SUCCESS)
{
resource2 = OpenSomeNetworkConnection(networkID)
if (resource2 == OKAY)
{
resource3 = CreateNewFile(outputFile);
if (resource3 == SUCCESS)
{
resource4 = ConnectToSomething(mySomething);
if (resource4)
{
//
// Do all my logic here
//
isMethodSuccessful = true; // return success
}
else
{
DeleteFile(resource3); // do cleanup
CloseNetwork(resource2);
CloseFile(resource1);
}
}
else
{
CloseNetwork(resource2); // do cleanup
CloseFile(resource1);
}
}
else
{
CloseFile(resource1); // do cleanup
}return (isMethodSuccessful);
}
Guard clauses will convert that mess into something like this:
resource1 = OpenMyFile(myFile);
if (resource1 != SUCCESS)
{
return failure;
}resource2 = OpenSomeNetworkConnection(networkID)
if (resource2 != OKAY)
{
CloseFile(resource1); // do cleanup
return failure;
}resource3 = CreateNewFile(outputFile);
if (resource3 != SUCCESS)
{
CloseNetwork(resource2); // do cleanup
CloseFile(resource1);
return failure;
}resource4 = ConnectToSomething(mySomething);
if (!resource4)
{
DeleteFile(resource3); // do cleanup
CloseNetwork(resource2);
CloseFile(resource1);
return failure;
}//
// Put all your logic here
//return (success);
...which is far from ideal (i.e. more yuck). So what's the best code logic in this situation?
-
The argument is "are guard clauses in methods okay?" And how do you handle resource cleanup if one of the guard clauses fail? I haven't seen a convincing consensus either way. A specific example: Let's say you have 10 resources to allocate (like opening files, networks, etc) -- for brevity here, let's just use four resources. All resources have to be allocated for the method to continue. So what we are trying to avoid is something like this (yuck):
isMethodSuccessful = false; // assume this isn't going to work
resource1 = OpenMyFile(myFile);
if (resource1 == SUCCESS)
{
resource2 = OpenSomeNetworkConnection(networkID)
if (resource2 == OKAY)
{
resource3 = CreateNewFile(outputFile);
if (resource3 == SUCCESS)
{
resource4 = ConnectToSomething(mySomething);
if (resource4)
{
//
// Do all my logic here
//
isMethodSuccessful = true; // return success
}
else
{
DeleteFile(resource3); // do cleanup
CloseNetwork(resource2);
CloseFile(resource1);
}
}
else
{
CloseNetwork(resource2); // do cleanup
CloseFile(resource1);
}
}
else
{
CloseFile(resource1); // do cleanup
}return (isMethodSuccessful);
}
Guard clauses will convert that mess into something like this:
resource1 = OpenMyFile(myFile);
if (resource1 != SUCCESS)
{
return failure;
}resource2 = OpenSomeNetworkConnection(networkID)
if (resource2 != OKAY)
{
CloseFile(resource1); // do cleanup
return failure;
}resource3 = CreateNewFile(outputFile);
if (resource3 != SUCCESS)
{
CloseNetwork(resource2); // do cleanup
CloseFile(resource1);
return failure;
}resource4 = ConnectToSomething(mySomething);
if (!resource4)
{
DeleteFile(resource3); // do cleanup
CloseNetwork(resource2);
CloseFile(resource1);
return failure;
}//
// Put all your logic here
//return (success);
...which is far from ideal (i.e. more yuck). So what's the best code logic in this situation?
For instance, the
C
languagegoto
statement allows to handle well the above scenario. :)If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler. -- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong. -- Iain Clarke
[My articles] -
The argument is "are guard clauses in methods okay?" And how do you handle resource cleanup if one of the guard clauses fail? I haven't seen a convincing consensus either way. A specific example: Let's say you have 10 resources to allocate (like opening files, networks, etc) -- for brevity here, let's just use four resources. All resources have to be allocated for the method to continue. So what we are trying to avoid is something like this (yuck):
isMethodSuccessful = false; // assume this isn't going to work
resource1 = OpenMyFile(myFile);
if (resource1 == SUCCESS)
{
resource2 = OpenSomeNetworkConnection(networkID)
if (resource2 == OKAY)
{
resource3 = CreateNewFile(outputFile);
if (resource3 == SUCCESS)
{
resource4 = ConnectToSomething(mySomething);
if (resource4)
{
//
// Do all my logic here
//
isMethodSuccessful = true; // return success
}
else
{
DeleteFile(resource3); // do cleanup
CloseNetwork(resource2);
CloseFile(resource1);
}
}
else
{
CloseNetwork(resource2); // do cleanup
CloseFile(resource1);
}
}
else
{
CloseFile(resource1); // do cleanup
}return (isMethodSuccessful);
}
Guard clauses will convert that mess into something like this:
resource1 = OpenMyFile(myFile);
if (resource1 != SUCCESS)
{
return failure;
}resource2 = OpenSomeNetworkConnection(networkID)
if (resource2 != OKAY)
{
CloseFile(resource1); // do cleanup
return failure;
}resource3 = CreateNewFile(outputFile);
if (resource3 != SUCCESS)
{
CloseNetwork(resource2); // do cleanup
CloseFile(resource1);
return failure;
}resource4 = ConnectToSomething(mySomething);
if (!resource4)
{
DeleteFile(resource3); // do cleanup
CloseNetwork(resource2);
CloseFile(resource1);
return failure;
}//
// Put all your logic here
//return (success);
...which is far from ideal (i.e. more yuck). So what's the best code logic in this situation?
Actually, your "yuck" example is much better than the "more yack" one. The former is just yacky, and the later is dangerous (think introducing changes to the function and remembering to copy/paste all the resource cleanup). The only robust and non-yacky way to handle this situation is use of The RAII programming idiom[^] In this case, the destructors will make sure that all your resources are freed at the end of the scope - even if you throw an exception.
-
Hi i have requirement like doing 10 steps to complete task After completion of one only i can enter into another I used nested if- else to do that like if (true) { if (true) { if (true) { return true; } else { } } else { } } else { } is there any better way to handle these type of situation Thanks in Advance
---------------------------- KRISHNA KUMAR T M
krishnakumartm wrote:
is there any better way to handle these type of situation
Yes, like:
if (ret)
ret = foo1();if (ret)
ret = foo2();if (ret)
ret = foo3();if (ret)
ret = foo4();If any of the function calls fail, none of the remaining ones will execute.
"Love people and use things, not love things and use people." - Unknown
"The brick walls are there for a reason...to stop the people who don't want it badly enough." - Randy Pausch
-
Hi i have requirement like doing 10 steps to complete task After completion of one only i can enter into another I used nested if- else to do that like if (true) { if (true) { if (true) { return true; } else { } } else { } } else { } is there any better way to handle these type of situation Thanks in Advance
---------------------------- KRISHNA KUMAR T M
Tons of COM examples and winsock examples use this approach in methods which would normally result in deep nested branch statements... void CSomeClass::SomeMethod(void) { if (FALSE) { return; } // got here 1 if (FALSE) { return; } // got here 2 if (FALSE) { return; } // got here 3 // ... }
-
Hi i have requirement like doing 10 steps to complete task After completion of one only i can enter into another I used nested if- else to do that like if (true) { if (true) { if (true) { return true; } else { } } else { } } else { } is there any better way to handle these type of situation Thanks in Advance
---------------------------- KRISHNA KUMAR T M
if (true)
{
if (true)
{
if (true)
{
return true;
}
else
{
}
}
else
{
}
}
else
{
}Do you need to do something in each else block? if yes than follow the same, else you can use
if((condition1)&&(condition2)&&(condition3))
return true;
else
return false; -
The argument is "are guard clauses in methods okay?" And how do you handle resource cleanup if one of the guard clauses fail? I haven't seen a convincing consensus either way. A specific example: Let's say you have 10 resources to allocate (like opening files, networks, etc) -- for brevity here, let's just use four resources. All resources have to be allocated for the method to continue. So what we are trying to avoid is something like this (yuck):
isMethodSuccessful = false; // assume this isn't going to work
resource1 = OpenMyFile(myFile);
if (resource1 == SUCCESS)
{
resource2 = OpenSomeNetworkConnection(networkID)
if (resource2 == OKAY)
{
resource3 = CreateNewFile(outputFile);
if (resource3 == SUCCESS)
{
resource4 = ConnectToSomething(mySomething);
if (resource4)
{
//
// Do all my logic here
//
isMethodSuccessful = true; // return success
}
else
{
DeleteFile(resource3); // do cleanup
CloseNetwork(resource2);
CloseFile(resource1);
}
}
else
{
CloseNetwork(resource2); // do cleanup
CloseFile(resource1);
}
}
else
{
CloseFile(resource1); // do cleanup
}return (isMethodSuccessful);
}
Guard clauses will convert that mess into something like this:
resource1 = OpenMyFile(myFile);
if (resource1 != SUCCESS)
{
return failure;
}resource2 = OpenSomeNetworkConnection(networkID)
if (resource2 != OKAY)
{
CloseFile(resource1); // do cleanup
return failure;
}resource3 = CreateNewFile(outputFile);
if (resource3 != SUCCESS)
{
CloseNetwork(resource2); // do cleanup
CloseFile(resource1);
return failure;
}resource4 = ConnectToSomething(mySomething);
if (!resource4)
{
DeleteFile(resource3); // do cleanup
CloseNetwork(resource2);
CloseFile(resource1);
return failure;
}//
// Put all your logic here
//return (success);
...which is far from ideal (i.e. more yuck). So what's the best code logic in this situation?
ssclaire wrote:
And how do you handle resource cleanup if one of the guard clauses fail?
Use RAII, see http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization[^].