This is related to a chapter from beautiful code.
And in that chapter I read about the nested ifs.
The author was talking about deeply nested ifs as originator of bugs and less readable.
And he was talking about replacing nested ifs with case statements and decision tables.
Can anybody illustrate how to remove nested ifs with case (select case) and decision tables ?
Well, not directly an answer to your question since you specifically ask about switch/case statements, but here is a similar question.
Invert “if” statement to reduce nesting
This talks about replacing nested if's with guard-statements, that return early, instead of progressively checking more and more things before settling on a return value.
One example I always try to do is replace heavily nested if's like this (actually this one's not too bad but I've seen them up to 8 or 9 levels deep in the wild):
if (i == 1) {
// action 1
} else {
if (i == 2) {
// action 2
} else {
if (i == 3) {
// action 3
} else {
// action 4
}
}
}
with this:
switch (i) {
case 1:
// action 1
break;
case 2:
// action 2
break;
case 3:
// action 3
break;
default:
// action 4
break;
}
I also try to keep the actions as small as possible (function calls are best for this) to keep the switch statement compressed (so you don't have to go four pages ahead to see the end of it).
Decision tables, I believe, are simply setting flags indicating what actions have to be taken later on. The "later on" section is simple sequencing of actions based on those flags. I could be wrong (it won't be the first or last time :-).
An example would be (the flag-setting phase can be complicated if's since its actions are very simple):
switch (i) {
case 1:
outmsg = "no paper";
genmsg = true;
mailmsg = true;
phonemsg = false;
break;
case 2:
outmsg = "no ink";
genmsg = true;
mailmsg = true;
phonemsg = false;
break;
default:
outmsg = "unknown problem";
genmsg = true;
mailmsg = true;
phonemsg = true;
break;
}
if (genmsg)
// Send message to screen.
if (mailmsg)
// Send message to operators email address.
if (phonemsg)
// Hassle operators mobile phone.
How about chained ifs?
Replace
if (condition1)
{
do1
}
else
{
if (condition2)
{
do2
}
else (condition3)
{
do3;
}
}
with
if (condition1) {
do1;
} else if (condition2) {
do2;
} else if (condition3) {
do3;
}
This is much like switch statement for complex conditions.
Make the condition into booleans and then write boolean expression for each case.
If the code was:
if (condition1)
{
do1
}
else
{
if (condition2)
{
do2
}
else (condition3)
{
do3;
}
}
One can write it as:
bool cond1=condition1;
bool cond2=condition2;
bool cond3=condition3;
if (cond1) {do1;}
if (!cond1 and cond2) {do2;}
if (!cond1 and cond3) {do2;}
For decision tables, please see my answer to this question, or better still read chapter 18 in Code Complete 2.
You can just break once a part of the validation failed for example.
function validate(){
if(b=="" || b==null){
alert("Please enter your city");
return false;
}
if(a=="" || a==null){
alert("Please enter your address");
return false;
}
return true;
}
Decision tables are where you store the conditional logic in a data structure rather than within the code itself.
So instead of this (using #Pax's example):
if (i == 1) {
// action 1
} else {
if (i == 2) {
// action 2
} else {
if (i == 3) {
// action 3
} else {
// action 4
}
}
}
you do something like this:
void action1()
{
// action 1
}
void action2()
{
// action 2
}
void action3()
{
// action 3
}
void action4()
{
// action 4
}
#define NUM_ACTIONS 4
// Create array of function pointers for each allowed value of i
void (*actions[NUM_ACTIONS])() = { NULL, action1, action2, action3 }
// And now in the body of a function somewhere...
if ((i < NUM_ACTIONS) && actions[i])
actions[i]();
else
action4();
If the possibilities for i are not low-numbered integers then you could create a lookup table instead of directly accessing the ith element of the actions array.
This technique becomes much more useful than nested ifs or switch statements when you have a decision over dozens of possible values.
If and switch statements are not purely OO. They are conditional procedural logic, but do a very good job! If you want to remove these statements for a more OO approach, combine the 'State' and 'Descriptor' patterns.
You might also consider using the Visitor pattern.
Nested if are equivalent to the logical operator AND
if (condition1)
{
if (function(2))
{
if (condition3)
{
// do something
}
}
}
Equivalent code:
if (condition1 && function(2) && condition3)
{
// do something
}
In both cases, when an expression evaluates false, the subsequent expression will not be evaluated. For example, if condition1 is false, the function() will not be called, and condition3 won't be evaluated.
Another example some languages allow is this
switch true{
case i==0
//action
break
case j==2
//action
break
case i>j
//action
break
}
Related
I am actually trying to edit the etherhost2 function to send to several destinations and I reached a point where it is possible only for the first time.
In the original code the function is working properly by just moving the two functions sendBurstPackets() and scheduleNextPacket(simTime()) in if condition with destMACAddress = resolveDestMACAddress() those two functions are only called once.
Does that mean that destMacAddress is set once through the whole simulation?
Original Code
void EtherTrafGen::handleMessage(cMessage *msg)
{
if (!isNodeUp())
throw cRuntimeError("Application is not running");
if (msg->isSelfMessage()) {
if (msg->getKind() == START) {
destMACAddress = resolveDestMACAddress();
// if no dest address given, nothing to do
if (destMACAddress.isUnspecified())
return;
}
sendBurstPackets();
scheduleNextPacket(simTime());
}
else
receivePacket(check_and_cast<cPacket *>(msg));
}
My Changes
void EtherTrafGen::handleMessage(cMessage *msg)
{
if (!isNodeUp())
throw cRuntimeError("Application is not running");
if (msg->isSelfMessage()) {
if (msg->getKind() == START) {
if (!multipacket)
{
destMACAddress = resolveDestMACAddress();
sendBurstPackets();
scheduleNextPacket(simTime());
}
// if no dest address given, nothing to do
if (destMACAddress.isUnspecified())
return;
}
}
else
receivePacket(check_and_cast<cPacket *>(msg));
}
The first message is only true for that condition (msg->getKind() == START), which means the the mac is set once for each host through the whole simulation. Removing that condition made it work.
I am worried if there are other self messages that might be mistaken with that function. Would be better to have separate EtherHost app that only works for my simulation.
If there is an idea how to look at all self messages, I would appreciate if some one informed me.
I would like to consider one syntax improvement.
How I can write this better:
IF condition1
IF condition2
{ do something }
ELSE
{ message1 }
ELSE
{ message1 }
There are two IF statements that cannot be joined in one statement, but in both ELSE parts need to be same code (in this example message1).
How this can be written better? I wouldn't like to write same code (in ELSE parts) twice.
TnX in advance!
Nemanja
The obvious solution is to combine the two conditions:
IF condition1 AND condition2
{ do something }
ELSE
{ message1 }
However if the two conditions really can not be combined for some reason, and you are using a C-like language which has a break keyword or equivalent, then you can do something like this:
DO
IF condition1
IF condition2
{ do something }
BREAK
{ message1 }
WHILE FALSE
What about
IF condition1 AND condition2
{ do something }
ELSE
{ message1 }
If you can't join both statements, you can use some sort of GOTO (ps: this is bad practice)
IF condition1
IF condition2
{ do something }
ELSE
GOTO ELSE_CODE
ELSE
:ELSE_CODE
{ message1 }
in case you're talking about a language without short-circuit boolean evaluation, you could manually implement it like
flag = condition1
IF flag
flag = flag AND condition2
IF flag
{ do something }
ELSE
{ message1 }
I searched for this answer and I realized you just need to reorder the statements.
Instead of 2 IF statements with one else like this
{
if(FirstCheck === true){
//run function 1
}
if(SecondCheck === true){
//run function 2
}
}else{
//run this else only when the first 2 IFs are false
// run function 3
}
}
you want to do a IF for the reason why you want to run the function in the else, and then put an else for that IFs, that then runs your original IFs
if(orginalElse !== true){
//run function 3
//this is the orginal else you would want to run, just with a negative if statement
}else{
if(FirstCheck === true){
//run function 1
}
if(SecondCheck === true){
//run function 2
}
}
What would be the best way to write an algorith like:
if (a) {
doA();
done();
}
else if (b) {
doB();
done();
}
else if (c) {
doC();
done();
}
another approach I thought:
done = true;
if (a) {
doA();
}
else if (b) {
doB();
}
else if (c) {
doC();
}
else {
done = false;
}
if (done) {
done();
}
Which is better? Is there another best approach?
Without any context, the most natural looking way for me is:
bool do_it(int condition)
{
switch (condition)
{
case a: doA(); return true;
case b: doB(); return true;
case c: doC(); return true;
default: return false;
}
}
// ...
if (do_it) done();
since it abstracts the logic of "if this whole stuff succeeds, then do call done()".
But there are many other ways to do this. Especially, if the number of conditions will likely grow in the future, I wouldn't do that at all.
Depends on how many conditions/actions are there and kind of language you are using.
OOP and polymorphysm could work nicely.
Use a switch statement, setting an isDone flag along the way, and call done() based on the flag.
If a,b and c are different complex conditional expressions then your first solution is the best. Maybe you can avoid the "else if" elements if this code is inside a function, like that:
private void doit() {
if (a) {
doA();
done();
return;
}
if (b) {
doB();
done();
return;
}
if (c) {
doC();
done();
return;
}
}
So for me it is much more a code style question.
I would write it as
var failed = false;
if (a) doA();
else if (b) doB();
else if (c) doC();
else failed = true;
if (!failed) done();
I don't like setting a variable like done first to true and later undoing it, because the work is not done before the conditional starts, so it looks illogical.
I also don't like the switch case option because the conditions 'a', 'b', 'c' are not necessarily mutually exclusive; the if ... else if ... else cascade supports non-exclusive conditions but switch() might not depending on the language. E.g. you can't convert cascading if ... else's to switch in C++.
I think it's definitely important to remove multiple call points to done() because that's redundancy and later a maintenance issue if done() e.g. gets parameters.
First, have one condition variable, not three. Second, I'd use a map of function pointers, with the condition variable as the key. Here's an example:
#!/usr/bin/env python
def doA():
pass
def doB():
pass
def doC():
pass
def done():
pass
a = 3
b = 6
c = 8
doers = {}
doers[a] = doA
doers[b] = doB
doers[c] = doC
condition = a
# this is now the entire "algorithm":
if condition in doers:
doers[condition]()
done()
I have a series of QTextEdits and QLineEdits connected to a slot through a QSignalMapper(which emits a textChanged(QWidget*) signal). When the connected slot is called (pasted below), I need to be able to differentiate between the two so I know whether to call the text() or toPlainText() function. What's the easiest way to determine the subclass type of a QWidget?
void MainWindow::changed(QWidget *sender)
{
QTextEdit *temp = qobject_cast<QTextEdit *>(sender);
QString currentText = temp->toPlainText(); // or temp->text() if its
// a QLineEdit...
if(currentText.compare(""))
{
...
}
else
{
...
}
}
I was considering using try-catch but Qt doesn't seem to have very extensive support for Exceptions... Any ideas?
Actually, your solution is already almost there. In fact, qobject_cast will return NULL if it can't perform the cast. So try it on one of the classes, if it's NULL, try it on the other:
QString text;
QTextEdit *textEdit = qobject_cast<QTextEdit*>(sender);
QLineEdit *lineEdit = qobject_cast<QLineEdit*>(sender);
if (textEdit) {
text = textEdit->toPlainText();
} else if (lineEdit) {
text = lineEdit->text();
} else {
// Return an error
}
You can also use sender->metaObject()->className() so you won't make unnecesary casts. Specially if you have a lot of classes to test. The code will be like this:
QString text;
QString senderClass = sender->metaObject()->className();
if (senderClass == "QTextEdit") {
QTextEdit *textEdit = qobject_cast<QTextEdit*>(sender);
text = textEdit->toPlainText();
} else if (senderClass == "QLineEdit") {
QLineEdit *lineEdit = qobject_cast<QLineEdit*>(sender);
text = lineEdit->text();
} else {
// Return an error
}
I know is an old question but I leave this answer just in case it would be useful for somebody...
During a code review, a senior dev commented on some nesting I had going on in my code. He suggested I set a bool value so that I never have more than one level of nesting. I think my code is more readable but want to get other devs' opinion on this. Which is better style? Is his knee-jerk aversion to nesting founded?
Below are some simplified code examples.
Nested:
If(condition1)
{
If(condition2)
{
if(condition3)
{
return true;
}
else
{
log("condition3 failed");
}
else
{
log("condition2 failed")
}
}
else
{
log("condition1 failed")
}
return false;
or
Bool Driven:
bool bRC = false;
bRC = (condition1);
if(brc)
{
bRC = (condition2);
}
else
{
log("condition1 failed");
return false;
}
if(bRC)
{
bRC = (condition3);
}
else
{
log("condition2 failed");
return false;
}
if(bRC)
{
return true;
}
else
{
log("condition3 failed");
return false;
}
I like yours better, but I'd probably do something like:
if (condition1 && condition2 && condition3)
{
return true;
}
else if (!condition1)
{
log("condition1 failed");
}
else if (!condition2)
{
log("condition2 failed");
}
else
{
log("condition3 failed");
}
return false;
If the conditions are complex expressions then I might assign the expressions to appropriately named variables before evaluating the if statements to avoid having to recompute the values in each if.
This is assuming that the normal mode is that all conditions are true and thus you want to have that check first. If the normal mode is that one or more conditions are false, then I'd reorder it and check each negation in turn and simply return true if all the checks failed. That would also remove the need for temporary variables to take the place of complex expressions.
If you don't have any silly rules about multiple return points, I think this is quite nice (and so does someone else, but they deleted their answer for unknown reasons):
if(!condition1)
{
log("condition1 failed");
return false;
}
if(!condition2)
{
log("condition2 failed");
return false;
}
if(!condition3)
{
log("condition3 failed");
return false;
}
return true;
Maybe this is an equal knee-jerk aversion to super-nesting, but it's certainly cleaner than his crap storing the boolean conditions in certain values. However, it may be less readable in context: consider if one of the conditions was isreadable(). It's clearer to say if(isreadable()) because we want to know if something is readable. if(!isreadable()) suggests if we want to know whether it's not readable, which isn't our intention. It's certainly debatable that there may be situations where one is more readable/intuitive than the other, but I'm a fan of this way myself. If someone gets hung up on the returns, you could do this:
if(!condition1)
log("condition1 failed");
else if(!condition2)
log("condition2 failed");
else if(!condition3)
log("condition3 failed");
else
return true;
return false;
But that's rather underhanded, and less "clear" in my opinion.
I personally find the nested code significantly easier to read.
I generally prefer nested for my conditions; of course, if my nested conditions are getting indented too far to the right, I have to start wondering if there's a better way to go about whatever I'm trying to do (refactoring, redesigning, etc..)
Similar to the nested version, but much cleaner for me:
if not condition1:
log("condition 1 failed")
else if not condition2:
log("condition 2 failed")
else if not condition3:
log("condition 3 failed")
else
return true;
return false;
Beware that each condition is evaluated once.
The second style is absurdly verbose: did he really suggest exactly this? You don't need most of those if statements, because there is a return in the else part.
With the nested example you are relying on not forgetting to include any possible else clauses.
Neither of these seems satisfactory to me.
The bool driven way is confusing. Nesting is fine if required, but you could remove some of the nesting depth by combining the conditions into one statement, or calling a method where some of the further evaluation is done.
I think both ways are possible and have their Pros and Cons. I would use the bool-driven style in cases where i would have really deep nesting (8 or 10 or something like that). In your case with 3 levels, i would choose your style but for the exact sample from above, i would go like that:
void YourMethod(...)
{
if (condition1 && condition2 && consition3)
return true;
if (!condition 1)
log("condition 1 failed");
if (!condition 2)
log("condition 2 failed");
if (!condition 3)
log("condition 3 failed");
return result;
}
... or like that if you prefer a single exit point (like i do) ...
void YourMethod(...)
{
bool result = false;
if (condition1 && condition2 && consition3)
{
result = true;
}
else
{
if (!condition 1)
log("condition 1 failed");
if (!condition 2)
log("condition 2 failed");
if (!condition 3)
log("condition 3 failed");
}
return result;
}
That way, you will get all the failed condition logged in the first run. In your example, you will get only one failed condition logged even if there are more than one failing conditions.
I'd probably go with
if (!condition1) log("condition 1 failed");
else if (!condition2) log("condition 2 failed");
else if (!condition3) log("condition 3 failed");
// -------------------------------------------
return condition1 && condition2 && condition3;
which I believe is equivilent and much cleaner...
Also, once the client decides that all conditions should be evaluated and logged if they fail, not just the first one that fails, this is much easier to modify to do that:
if (!condition1) log("condition 1 failed");
if (!condition2) log("condition 2 failed");
if (!condition3) log("condition 3 failed");
// -------------------------------------------
return condition1 && condition2 && condition3;
This is how I would implement it, provided your implementations actually reflect the desired behavior.
if (!condition1) {
log("condition1 failed");
return false;
}
if (!condition2) {
log("condition2 failed");
return false;
}
if (!condition3) {
log("condition3 failed");
return false;
}
return true;
However, I think it's more likely that every failed condition should be logged.
result = true;
if (!condition1) {
log("condition1 failed");
result = false;
}
if (!condition2) {
log("condition2 failed");
result = false;
}
if (!condition3) {
log("condition3 failed");
result = false;
}
return result;
If the language supports exception handling, I'd go with the following:
try {
if (!condition1) {
throw "condition1 failed";
}
if (!condition2) {
throw "condition2 failed";
}
if (!condition3) {
throw "condition3 failed";
}
return true;
} catch (e) {
log(e);
return false;
}
EDIT From charles bretana: Please see Using Exceptions for control flow
I don't like either way. When you have so much nests something is wrong. In the case of a form validation or something that does indeed require something like this try to figure something out that's more modular or compact.
An example would be an array holding the conditions, through which you'll iterate with a while, and print/break as needed.
There are too many implementations depending on your needs so creating an example code would be pointless.
As a rule of thumb, when your code looks too complicated, it sucks :). Try rethinking it. Following coding practices most of the times makes the code turn out a lot more aesthetic and short; and obviously, also smarter.
Code shall restate the problem in a language given. Therefore I maintain that either snippets can be "better". It depends on the problem being modeled. Although my guess is that neither of the solutions will parallel the actual problem. If you put real terms instead of condition1,2,3 it might completely change the "best" code.
I suspect there is a better (3d) way to write that all together.
if( condition1 && condition2 && condition3 )
return true;
log(String.Format("{0} failed", !condition1 ? "condition1" : (!condition2 ? "condition2" : "condition3")));
return false;
That way, you don't have to see many lines of code just for logging. And if all your conditions are true, you don't waste time evaluating them in case you have to log.