if(x!=y) vs if(x==y) - java

I have run the PMD plugin in Eclipse against my code and I'm getting a high priority warning for code similar to the one shown below:
if(singleRequest !=null){
// do my work
}else{
// do my other work
}
PMD says `Avoid if (x != y) ..; else ..;
And the description of the error looks like this:
In an "if" expression with an "else" clause, avoid negation in
the test. For example, rephrase:
if (x != y) diff(); else same();
as:
if (x == y) same(); else diff();
Most "if (x != y)" cases without an "else" are often return
but I still can't understand the impact on my code. If someone could guide me with an example, I would appreciate it.

A number of PMD rules are more style opinions than correctness alerts. If you don't agree with this rule or the rule doesn't match your project's coding standards, you could consider suppressing warnings or even configuring PMD to enforce only the rules you like

PMD is a tool. PMD works based on heuristics. Someone decided upon this heuristic; that negative conditionals with else statements are not "good style".
However, in this case, as I have argued in my comments, the code posted is how I would write it. (In particular with x != null, but not exclusively to this construct.)
This is because I don't look at the conditional (excepting as it can be simplified; e.g. removing double-negatives as shown by Jim Kin) but rather I look at the logic of the branches or "flow".
That is, I place the positive branch first. In this case I contend that
if (x != null) {
doValid // positive branch
} else {
doFallback
}
is semantically equivalent to
if (isValid(x)) { // it looks like a "positive conditional" now
doValid // still positive branch
} else {
doFallback
}
and is thus positive branch first.
Of course, not all situations have such a "clear" positive flow, and some expressions might be expressed much easier in a negative manner. In these cases I will "invert" the branches - similar to what PMD is suggesting - usually with a comment stating the action at the top of the block if the positive branch/flow was reversed.
Another factor that may influence the conditional choice used is "immediate scope exiting" branches like:
if (x == null) {
// return, break, or
throw new Exception("oops!");
} else {
// But in this case, the else is silly
// and should be removed for clarity (IMOHO) which,
// if done, avoids the PMD warning entirely
}
This is how I consistently (a few occasional exceptions aside) write my code: if (x != null) { .. }. Use the tools available; and make them work for you. See Steven's answer for how PMD can be configured to a more suitable "taste" here.

It's a readability issue. Consider
if ( x != y )
{
}
else // "if x doesn't not equal y"
{
}
vs.
if ( x == y )
{
}
else // "if x doesn't equal y"
{
}
The latter example is more immediately identifiable. Mind you, I see nothing wrong with using negatives... it can make a lot more sense, consider
if ( x != null )...

The only reason I would avoid using the negative-case is if it resulted in double-negatives, which might be confusing.
e.g.
if (!checkbox.disabled) {
// checkbox is enabled
}
else {
// checkbox is disabled
}

Who reads your code? You do. The compiler does. Or maybe the assistant of the lecturer. A co-worker, who can't make difference between == and != ? Hope not.
I can only think negatives being bad in complex expressions. (Context being: at least for me. I know I've frustrated in debugging in my head while(!expr && !expr2 || expr3) { })
ch=getch(); if (ch!='a') is a pattern that is easily extended to
if (ch!='a' || ch!='b') which is always true, while sounding semantically correct.
From performance standpoint, it's best to sort the probabilities.
if (more_probable) {
....
unconditional_jump_to_end_of_block;
} else {
...
}
This choice should lead to better performance, as the there is no mis-prediction penalty in the more probable branch.
if (p && p->next) evaluated from performance standpoint gives poor results.

You have to avoid having "not equals" in the if condition. This is because when someone else looks at your code, there is a real possibility that the person might ignore the != and might jump to wrong conclusion about the logic of your program.
For your case, you may have to interchange the if logic with else logic and change != to ==

It's a balancing case of code readability vs. code organization. The warning is basically suggesting that it's confusing for people reading the code to navigate the negation of a negative.
My personal rule of thumb is, whatever you expect to be the "normal" case is what you should test for in the if. Consider:
if (x != y) {
// do work here...
} else {
throw new IllegalArgumentException();
}
In this situation I'd say that the important work is being done in the x != y case, so that's what you should test for. This is because I like to organize code so that the important work comes first, followed by handling for exceptional cases.

It's because "good style" says that if possible tests should be "positive", so:
if (singleRequest == null){
// do my other work
} else {
// do my work
}
Is easier to read because the test is "positive" (ie "equals" not "not equals"), and ultimately better readability leads to less bugs.
Edited
This is particularly the case with test like:
if (!str.equals("foo")) {
you can easily miss the ! at the front, but if you make the test positive, it's a lot cleaner.
The only time you should have a negative test is when there's no else block - then a negative test is unavoidable unless you have an empty true block, which itself is considered a style problem.

Not really an answer, but you can minimise the overall complexity and improve readability by returning or failing early and then continuing without indentation:
if (something == null) {
throw new IllegalArgumentException("something must not be null");
}
// continue here

Related

Nested ifs or ands?

I'm a beginner level programmer who's just starting to work on actual projects, and I'm starting to think about things such as efficiency and if my code looks professional. I was wondering if, when trying to check multiple booleans, is it better to use nested if statements, or multiple && and || operators.
Action action = event.getAction();
Material holding = event.getItem().getType();
if((action.equals(Action.RIGHT_CLICK_AIR)||(action.equals(Action.RIGHT_CLICK_BLOCK))))
{
if((event.hasItem())&&(holding.equals(Material.COMPASS)))
{
//if the player right clicked while holding a compass
}
}
Does this look right? I tried to group the like if-statements together. Also, if there's anything else I can do to improve my formatting, please tell me! Thanks.
Welcome to the Stack Overflow community!
There is no problem with the code shared in the question. In some cases, it is better to opt for legibility so that your co-workers will be able to understand the proposed code better. But in the end, this is very subjective.
IMHO, it is easier to understand if we write all the conditions at once. So,
Action action = event.getAction();
Material holding = event.getItem().getType();
Boolean isRequiredAction = action.equals(Action.RIGHT_CLICK_AIR) || action.equals(Action.RIGHT_CLICK_BLOCK)
if (
isRequiredAction
&& event.hasItem()
&& holding.equals(Material.COMPASS)
)
{
// logic...
}
However, if you really want advice and tips on how to refactor it and best practices in a particular language, try Code Review community.
imo for a personal taste, i would put those nested conditions in a boolean variable that can explain the behavior as much as the comment you let in the block, like:
boolean isActionRightClick = action.equals(Action.RIGHT_CLICK_AIR ||action.equals(Action.RIGHT_CLICK_BLOCK);
boolean isHoldingACompass = event.hasItem() && holding.equals(Material.COMPASS);
and then
if ( isActionRightClick && isHoldingACompass ) {...}
Yes your code looks very good to me. I used to work on big projects and uses nested if statements, or multiple && and || operators which saves time. In your code efficiency can be traced at :
if((action.equals(Action.RIGHT_CLICK_AIR)||(action.equals(Action.RIGHT_CLICK_BLOCK))))
As now check only one condition in the or statement will satisfy the if condition which will save time and also shorten the code length.
You can make this code more shorter by removing unwanted parenthesis from your code. Which you must take care in future.
For more details related to efficient coding you can visit this link:
https://docs.oracle.com/cd/E80738_01/pt854pbh2/eng/pt/tpcd/task_WritingMoreEfficientCode-0749ba.html#topofpage
This is good to think about the quality/readability of your code.
Nested "if" are a good question in most of the case i think this depends of people. Some people prefer to nest it, to evaluate condition one after another. Some other prefer to not nest for not lose the track in the block.
But in most of the case be careful to not do to much if statement and try to replace it with pattern design (Easier said than done.). You can find a lot of it in java-design-patterns
I think you could make it even more shorter by using ternary operator (?:) right.
if (expression1) {
result = 1;
} else if (expression2) {
result = 2;
} else if (expression3) {
result = 3;
} else {
result = 0;
}
result = (expression1) ? 1 : (expression2) ? 2 : (expression3) ? 3 : 0;

What is the best way to exit loop in Java? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
What is the best way to end a loop in Java?
This:
boolean exit = false;
while((a < 5) && (exit = false)){
if(a == 3)
exit = true;
else
a++;
}
Or this:
while((a < 5){
if(a == 3)
break;
else
a++;
}
Some people may find that break are harder to debug (personally, I prefer using flag) but it is principally a matter of opinion.
Imagine a loop body which contains over 500 lines of code, with some break statements located everywhere, it may be harder for you to visualise all the possibilities of exiting the loop.
Another reason of why I like using a flag is that you can give a signifiant name to the ending point instead of simply break.
Note that you can also use a flag in a for loop example :
boolean flag = false;
for(int i = 0; !flag && i < 10; i++) {
// some treatment
}
It may be interesting however, to know that when dealing with loop, there is the continue keyword which allow you to not exit the loop, but skip directly to the next iteration.
What is the best way to finish a loop in Java?
If there was really a best way between both, Java would probably not allow the other ;)
I guess the most important is to use the same convention as your co-worker so the code does not differ from class to class.
break exist for a reason, right!
while(a < 5){
if(a == 3)
break;
else
a++;
}
Very simple answer, go for the break, less flags, less to debug, easier to maintain. It is simple to change from a while to for loop without any modifications in the logic. Think of a scenario where you would need to add more conditions...
My opinion is if you don't understand the usage of break and continue then you might go for the flag all the time. But there is not only one answer. Your question is what option is better for exit the loop and from your two examples the option is simple. My opinion is the break one.
Now some will use the flag, and some the break, and they give code samples for which will fit better. But this is not your question!
I can give you lots of examples, where some I would go for the flag and other for the break and some a mix of both. It depends on what my loop is about to handle.
break is to mark that if we reach this condition, we will go out of the loop emiditely. Which is very important in some loop logic.
Even though when you/co-worker add more logic, before or after that condition, still the loop will exit where it reaches the break.
Sometimes you maybe want to flag that you reached a condition but want still to go thru all the instructions the loop covers, and here does a bool help you to stop the loop but after it went thru all the logic.
If you don't use flag/break in a right way your system can act very strange, specially when adding new logic.
Remember that you also can use break and continue with a label, which is not so common but good to know.
class ContinueWithLabelDemo {
public static void main(String[] args) {
String searchMe = "Look for a substring in me";
String substring = "sub";
boolean foundIt = false;
int max = searchMe.length() -
substring.length();
test:
for (int i = 0; i <= max; i++) {
int n = substring.length();
int j = i;
int k = 0;
while (n-- != 0) {
if (searchMe.charAt(j++) != substring.charAt(k++)) {
continue test;
}
}
foundIt = true;
break test;
}
System.out.println(foundIt ? "Found it" : "Didn't find it");
}
}
The first snippet is syntactically wrong - = is the assignment operator. You were looking for the equality operator, ==:
while ((a < 5) && (exit == false)) {
Or better yet, since exit is a boolean, just evaluate it directly:
while (a < 5 && !exit) {
Other than that, you should always strive to follow the convention of the project you're working on. If it's coding styles prefers breaks - just use them. If it prohibits them, don't.
Once you throw project guideline considerations out the window, it's completely a matter of preference. Personally, I tend to prefer the break statement, especially if I have several conditions to evaluate. E.g.:
while (a < 5) {
// do stuff
if (a == 3) {
break;
}
// do more stuff
if (b >= 19) {
break;
}
// etc...
}
But ultimately, you should evaluate it on a case-to-case basis. Preferring breaks, like I do, doesn't mean you should blindly always use them. Choose whatever makes the code look better and easier to maintain.
I depends on what you mean by "best" ? With the break, you exit the loop early, so that is more efficient.
I would prefer the first, cause goto is considered harmful. And an exit is like a goto. But more important: Please always use {} when writing a if clause.
Also, when using a condition, give it a name. It is almost simpler to understand ageBelow18 instead of today.getYear() < customer.getBirthday().getYear(); (the code is not correct, I know).
Both those options you have presented aren't as good as two alternatives.
Seeing as you directly exit the loop after a simple comparison then the best option is:
while (a < 5 && a != 3) {
a++;
}
This is because you need to check both conditions before executing the body, and you don't need to do anything special when exiting the loop.
However, if you need to do need a bit of special logic when a certain condition is hit then you should use a while true loop and breaks.
while (true) {
if (a >= 5) {
break; // nothing special, just exit
} else if (a == 3) {
a *= 2; // double a before exiting loop
break;
}
a++;
}
The while (true) shows that the only way to exit the loop is with a break, so the programmer should keep an eye out for them. The breaks should also be grouped together at the top of the loop body, so they act as guards preventing the loop body from being executed if their condition is hit.
I would choose the break statement since:
Code is more clean
No need for extra code declarations
Debug the code is easier
It's common to mess with a lot of flags declared on the condition. You will not want to get a lot of nested conditions on the same line.
There is also exist the continue keyword that will let you to skip parts of the code if necessary.

What are the cases in which it is better to use unconditional AND (& instead of &&)

I'd like to know some cases in Java (or more generally:
in programming) when it is preferred in boolean expressions to use the unconditional AND (&) instead of the conditional version (&&).
I know how they work, but I cannot think about a case when use the single & is worth it.
I have found cases in real life where both sides of the expression were really cheap, so it shaved off a nanosecond or two to avoid the branch and to use the unconditional & instead of &&. (These were extremely high-performance math utilities, though; I would almost never use this in other code, and I wouldn't have done it anyway without exhaustive benchmarking to prove it was better.)
(To give specific examples, x > 0 is going to be super cheap and side-effect-free. Why bother risking a branch misprediction to avoid a test that's going to be so cheap anyway? Sure, since it's a boolean the end result is going to be used in a branch anyway, but if (x >= 0 && x <= 10) involves two branches, and if (x >= 0 & x <= 10) involves only one.)
The only difference is that && and || stop the evaluation as soon as it is known. So for example:
if (a != null && a.get() != null)
works well with &&, but with & you could get a NullPointerException if a is null.
The only case I can think about where you want to use & is if the second operand has a side effect, for example (probably not the best example but you get the point):
public static void main(String[] args) {
int i = 1;
if (i == 0 & ++i != 2) {
}
System.out.println(i); //2
i = 1;
if (i == 0 && ++i != 2) {
}
System.out.println(i); //1
}
However, this looks like smelly code to me (in both cases).
The && allows the jvm to do short circuit evaluation. That is, if the first argument is false, then it doesn't need to bother checking the second argument.
A single & will run both sides regardless.
So, as a contrived example, you might have:
if (account.isAllowed() & logAccountAndCheckFlag(account))
// Do something
In that example, you might always want to log the fact that the owner of the account attempted to do something.
I don't think I have ever used a single & in commercial programming though.
Wikipedia has nicely described the Short Circuit Evaluation
Where do you prefer non short-circuit operators ?
From the same link:
Untested second condition leads to unperformed side effect
Code efficiency
Short-circuiting can lead to errors in branch prediction on modern
processors, and dramatically reduce performance (a notable example is
highly optimized ray with axis aligned box intersection code in ray
tracing)[clarification needed]. Some compilers can detect such cases
and emit faster code, but it is not always possible due to possible
violations of the C standard. Highly optimized code should use other
ways for doing this (like manual usage of assembly code)
If there are side effects that must happen, but that's a little ugly.
The bitwise AND (&) is mostly useful for just that - bitwise math.
Input validation is one possible case. You typically want to report all the errors in a form to the user in a single pass instead of stopping after the first one and forcing them to click submit repeatedly and only get a single error each time:
public boolean validateField(string userInput, string paramName) {
bool valid;
//do validation
if (valid) {
//updates UI to remove error indicator (if present)
reportValid(paramName);
} else {
//updates UI to indicate a problem (color change, error icon, etc)
reportInvalid(paramName);
}
}
public boolean validateAllInput(...) {
boolean valid = true;
valid = valid & validateField(userInput1, paramName1);
valid = valid & validateField(userInput2, paramName2);
valid = valid & validateField(userInput3, paramName3);
valid = valid & validateField(userInput4, paramName4);
valid = valid & validateField(userInput5, paramName5);
return valid;
}
public void onSubmit() {
if (validateAllInput(...)) {
//go to next page of wizard, update database, etc
processUserInput(userInput1, userInput2, ... );
}
}
public void onInput1Changed() {
validateField(input1.Text, paramName1);
}
public void onInput2Changed() {
validateField(input2.Text, paramName2);
}
...
Granted, you could trivially avoid the need for short circuit evaluation in validateAllInput() by refactoring the if (valid) { reportValid() ... logic outside of validateField(); but then you'd need to call the extracted code every time validateField() was called; at a minimum adding 10 extra lines for method calls. As always it's a case of which tradeoff's work best for you.
If the expression are trivial, you may get a micro-optimisation by using & or | in that you are preventing a branch. ie.
if(a && b) { }
if(!(a || b)) { }
is the same as
if (a) if (b) { }
if (!a) if (!b) { }
which has two places a branch can occur.
However using an unconditional & or |, there can be only one branch.
Whetehr this helps or not is highly dependant on what the code is doing.
If you use this, I sugegst commenting it to make it very clear why it has been done.
There isn't any specific use of single & but you can consider the following situation.
if (x > 0 & someMethod(...))
{
// code...
}
Consider that someMethod() is doing some operation which will modify instance variables or do something which will impact behavior later in processing.
So in this case if you use && operator and the first condition fails it will never go in someMethod(). In this case single & operator will suffice.
Because & is a bit-wise operator, you can do up to 32-checks in a single operation concurrently. This can become a significant speed gain for this very specific use cases. If you need to check a large number of conditions, and do it often and the cost of boxing/unboxing the conditions are amortized by the number of checks, or if you store your data on-disk and on-RAM in that format (it is more space efficient to store 32 conditions in a single bitmask), the & operator can give a huge speed benefit over a series of 32 individual &&. For example if you want to select all units that can move, is an infantry, has weapon upgrade, and is controlled by player 3, you can do:
int MASK = CAN_MOVE | INFANTRY | CAN_ATTACK | HAS_WEAPON_UPGRADE | PLAYER_3;
for (Unit u in allunits) {
if (u.mask & MASK == MASK) {
...;
}
}
See my other answers on a related question for more on the topic.
The only benefit I can think of is when you need to invoke a method or execute a code, no matter the first expression is evaluated to true or false:
public boolean update()
{
// do whatever you want here
return true;
}
// ...
if(x == y & update()){ /* ... */}
Although you can do this without &:
if(x == y){/* ... */}
update();
Short-circuiting can lead to errors in branch prediction on modern processors, and dramatically reduce performance (a notable example is highly optimized ray with axis aligned box intersection code in ray tracing)[clarification needed].

Is it bad to explicitly compare against boolean constants e.g. if (b == false) in Java?

Is it bad to write:
if (b == false) //...
while (b != true) //...
Is it always better to instead write:
if (!b) //...
while (!b) //...
Presumably there is no difference in performance (or is there?), but how do you weigh the explicitness, the conciseness, the clarity, the readability, etc between the two?
Update
To limit the subjectivity, I'd also appreciate any quotes from authoritative coding style guidelines over which is always preferable or which to use when.
Note: the variable name b is just used as an example, ala foo and bar.
It's not necessarily bad, it's just superfluous. Also, the actual variable name weights a lot. I would prefer for example if (userIsAllowedToLogin) over if (b) or even worse if (flag).
As to the performance concern, the compiler optimizes it away at any way.
As to the authoritative sources, I can't find something explicitly in the Java Code Conventions as originally written by Sun, but at least Checkstyle has a SimplifyBooleanExpression module which would warn about that.
You should not use the first style. I have seen people use:
if ( b == true )
if ( b == false )
I personally find it hard to read but it is passable. However, a big problem I have with that style is that it leads to the incredibly counter-intuitive examples you showed:
if ( b != true )
if ( b != false )
That takes more effort on the part of the reader to determine the authors intent. Personally, I find including an explicit comparison to true or false to be redundant and thus harder to read, but that's me.
This is strongly a matter of taste.
Personally I've found that if (!a) { is a lot less readable (EDIT: to me) than if (a == false) { and hence more error prone when maintaining the code later, and I've converted to use the latter form.
Basically I dislike the choice of symbols for logic operations instead of words (C versus Pascal), because to me a = 10 and not b = 20 reads easier than a == 10 && !(b==20), but that is the way it is in Java.
Anybody who puts the "== false" approach down in favour of "!" clearly never had stared at code for too long and missed that exclamation mark. Yes you can get code-blind.
The overriding reason why you shouldn't use the first style is because both of these are valid:
if (b = false) //...
while (b = true) //...
That is, if you accidentally leave out one character, you create an assignment instead of a comparison. An assignment expression evaluates to the value that was assigned, so the first statement above assigns the value false to b and evaluates to false. The second assigns true to b, so it always evaluates to true, no matter what you do with b inside the loop.
I've never seen the former except in code written by beginners; it's always the latter, and I don't think anyone is really confused by it. On the other hand, I think
int x;
...
if(x) //...
vs
if(x != 0) //...
is much more debatable, and in that case I do prefer the second
IMHO, I think if you just make the bool variable names prepended with "Is", it will be self evident and more meaningful and then, you can remove the explicit comparison with true or false
Example:
isEdited // use IsEdited in case of property names
isAuthorized // use IsAuthorized in case of property names
etc
I prefer the first, because it's clearer. The machine can read either equally well, but I try to write code for other people to read, not just the machine.
In my opinion it is simply annoying. Not something I would cause a ruckus over though.
The normal guideline is to never test against boolean. Some argue that the additional verbosity adds to clarity. The added code may help some people, but every reader will need to read more code.
This morning, I have lost 1/2 hour to find a bug. The code was
if ( !strcmp(runway_in_use,"CLOSED") == IPAS_FALSE)
printf(" ACTIVE FALSE \n"); else
printf(" ACTIVE TRUE \n");
If it was coded with normal convention, I would have seen a lot faster that it was wrong:
if (strcmp(runway_in_use, "CLOSED"))
printf(" ACTIVE FALSE \n"); else
printf(" ACTIVE TRUE \n");
I prefer the long approach, but I compare using == instead of != 99% of time.
I know this question is about Java, but I often switch between languages, and in C#, for instance, comparing with (for isntance) == false can help when dealing with nullable bool types. So I got this habbit of comparing with true or false but using the == operator.
I do these:
if(isSomething == false) or if(isSomething == true)
but I hate these:
if(isSomething != false) or if(isSomething != true)
for obvious readability reasons!
As long as you keep your code readable, it will not matter.
Personally, I would refactor the code so I am not using a negative test. for example.
if (b == false) {
// false
} else {
// true
}
or
boolean b = false;
while(b == false) {
if (condition)
b = true;
}
IMHO, In 90% of cases, code can be refactored so the negative test is not required.
This is my first answer on StackOverflow so be nice...
Recently while refactoring I noticed that 2 blocks of code had almost the exact same code but one used had
for (Alert alert : alerts) {
Long currentId = alert.getUserId();
if (vipList.contains(currentId)) {
customersToNotify.add(alert);
if (customersToNotify.size() == maxAlerts) {
break;
}
}
}
and the other had
for (Alert alert : alerts) {
Long currentId = alert.getUserId();
if (!vipList.contains(currentId)) {
customersToNotify.add(alert);
if (customersToNotify.size() == maxAlerts) {
break;
}
}
}
so in this case it made sense to create a method which worked for both conditions like this using boolean == condition to flip the meaning
private void appendCustomersToNotify(List<Alert> alerts
List<Alert> customersToNotify, List<Long> vipList, boolean vip){
for (Alert alert : alerts) {
Long currentId = alertItem.getUserId();
if (vip == vipList.contains(currentId)) {
customersToNotify.add(alertItem);
if (customersToNotify.size() == maxAlerts) {
break;
}
}
}
}
I would say it is bad.
while (!b) {
// do something
}
reads much better than
while (b != true) {
// do something
}
One of the reasons the first one (b==false) is frowned upon is that beginners often do not realize that the second alternative (!b) is possible at all. So using the first form may point at a misconception with boolean expressions and boolean variables. This way, using the second form has become some kind of a sjiboleth: when someone writes this, he/she probably understands what's going on.
I believe that this has caused the difference to be considered more important than it really is.
While both are valid, to me the first feels like a type error.
To me b == false looks as wrong as (i == 0) == false. It is like: huh?
Booleans are not an enum with 2 possible values. You don't compare them. Boolean are predicates and represent some truth. They have specific operators like &, |, ^, !.
To reverse the truth of an expression use the operator '!', pronounch it as "not".
With proper naming, it becomes natural: !isEmpty reads "not is empty", quite readable to me.
While isEmpty == false reads something like "it is false that it is empty", which I need more time to process.
I won't go into all of the details at length because many people have already answered correctly.
Functionality-wise, it gives the same result.
As far as styling goes, it's a matter of preference, but I do believe !condition to be more readable.
For the performance argument, I have seen many say that it makes no difference, but they have nothing to justify their claims. Let's go just a bit deeper into that one. So what happens when you compare them?
First, logically:
if(condition == false)
In this case, if is comparing its desired value to execute with the value between the parentheses, which has to be computed.
if(!condition)
In this case, if is directly compared to the opposite(NOT) of the condition. So instead of 2 comparisons, it is one comparison and 1 NOT operation, which is faster.
I wouldn't just say this without having tested it of course. Here is a quick screenshot of the test I did. !condition is nearly twice as fast over 10 million iterations.
https://imgur.com/a/jrPVKMw
EDIT: I tested this in C#, compiled with visual studio. Some compilers may be smarter and optimize it properly, which would make the performance the same.

Is it bad practice to change state inside of an if statement?

I wrote some code that looks similar to the following:
String SKIP_FIRST = "foo";
String SKIP_SECOND = "foo/bar";
int skipFooBarIndex(String[] list){
int index;
if (list.length >= (index = 1) && list[0].equals(SKIP_FIRST) ||
list.length >= (index = 2) &&
(list[0] + "/" + list[1]).equals(SKIP_SECOND)){
return index;
}
return 0;
}
String[] myArray = "foo/bar/apples/peaches/cherries".split("/");
print(skipFooBarIndex(myArray);
This changes state inside of the if statement by assigning index. However, my coworkers disliked this very much.
Is this a harmful practice? Is there any reason to do it?
Yes. This clearly reduces readability. What's wrong with the following code?
int skipFooBarIndex(String[] list){
if(list.length >= 1 && list[0].equals(SKIP_FIRST))
return 1;
if(list.length >= 2 && (list[0] + "/" + list[1]).equals(SKIP_SECOND))
return 2;
return 0;
}
It's much easier to understand. In general, having side effects in expressions is discouraged as you'll be relying on the order of evaluation of subexpressions.
Assuming you count it as "clever" code, it's good to always remember Brian Kernighan's quote:
Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.
...However, my coworkers disliked this very much...
Yes, it is. Not just because you can code it like that, you have to.
Remember that that piece of code will eventually have to be maintained by someone ( that someone may be your self in 8 months )
Changing the state inside the if, make is harder to read and understand ( mostly because it is non common )
Quoting Martin Fowler:
Any fool can write code that a computer can understand. Good programmers write code that humans can understand
There's an excellent reason not to do it: it's makes your code really hard to understand and reason about.
The problem is that the code would generate multiple-WTFs in a code review session. Anything that makes people go "wait, what?" has got to go.
It's sadly easy enough to create bugs even in easy-to-read code. No reason to make it even easier.
Yes, side effects are hard to follow when reviewing code.
Regarding reasons to do it: No, there is no real reason to do it. I haven't yet stumbled upon an if statement that can't be rewritten without side effects without having any loss.
The only thing wrong with it is that it's unfamiliar and confusing to people who didn't write it, at least for a minute while they figure it out. I would probably write it like this to make it more readable:
if (list.length >= 1 && list[0].equals(SKIP_FIRST)) {
return 1;
}
if (list.length >= 2 && (list[0] + "/" + list[1]).equals(SKIP_SECOND)) {
return 2;
}
Borrowed from cppreference.com:
One important aspect of C++ that is related to operator precedence is the order of evaluation and the order of side effects in expressions. In some circumstances, the order in which things happen is not defined. For example, consider the following code:
float x = 1;
x = x / ++x;
The value of x is not guaranteed to be consistent across different compilers, because it is not clear whether the computer should evaluate the left or the right side of the division first. Depending on which side is evaluated first, x could take a different value.
Furthermore, while ++x evaluates to x+1, the side effect of actually storing that new value in x could happen at different times, resulting in different values for x.
The bottom line is that expressions like the one above are horribly ambiguous and should be avoided at all costs. When in doubt, break a single ambiguous expression into multiple expressions to ensure that the order of evaluation is correct.
Is this a harmful practice?
Absolutely yes. The code is hard to understand. It takes two or three reads for anyone but the author. Any code that is hard to understand and that can be rewritten in a simpler way that is easier to understand SHOULD be rewritten that way.
Your colleagues are absolutely right.
Is there any reason to do it?
The only possible reason for doing something like that is that you have extensively profiled the application and found this part of code to be a significant bottleneck. Then you have implemented the abomination above, rerun the profiler, and found that it REALLY improves the performance.
Well, I spent some time reading the above without realising what was going on. So I would definitely suggest that it's not ideal. I wouldn't really ever expect the if() statement itself to change state.
I wouldn't recommend an if condition having side-effects without a very good reason. For me, this particular example took several looks to figure out what was going on. There may be a case where it isn't so bad, although I certainly can't think of one.
Ideally, each piece of code should do one thing. Making it do more than one thing is potentially confusing, and confusing is exactly what you don't want in your code.
The code in the condition of an if statement is supposed to generate a boolean value. Tasking it with assigning a value is making it do two things, which is generally bad.
Moreover, people expect conditions to be just conditions, and they often glance over them when they're getting an impression of what the code is doing. They don't carefully parse everything until they decide they need to.
Stick that in code I'm reviewing and I'll flag it as a defect.
You can also get ternary to avoid multiple returns:
int skipFooBarIndex(String[] list) {
return (list.length > 0 && list[0].equals(SKIP_FIRST)) ? 1 :
((list.length > 1 && (list[0] + "/" + list[1]).equals(SKIP_SECOND)) ? 2 : 0);
}
Though this example is less readable.
Speaking as someone who does a lot of maintenance programming: if I came across this I would curse you, weep and then change it.
Code like this is a nightmare - it screams one of two things
I'm new here and I need help doing the right thing.
I think I am very clever because I have saved lines of code or I have fooled the compiler and made it quicker. Its not clever, its not optimal and its not funny
;)
In C it's fairly common to change state inside if statements. Generally speaking, I find that there are a few unwritten rules on where this is acceptable, for example:
You are reading into a variable and checking the result:
int a;
...
if ((a = getchar()) == 'q') { ... }
Incrementing a value and checking the result:
int *a = (int *)0xdeadbeef;
...
if (5 == *(a++)) { ... }
And when it is not acceptable:
You are assigning a constant to a variable:
int a;
...
if (a = 5) { ... } // this is almost always unintentional
Mixing and matching pre- and post-increment, and short-circuiting:
int a = 0, b;
...
if (b || a++) { ... } // BAD!
For some reason the font for sections I'm trying to mark as code is not fixed-width on SO, but in a fixed width font there are situations where assignment inside if expressions is both sensible and clear.

Categories

Resources