Reputation: 7078
I have a list I need to process. The items are either enabled or disabled. The user can choose whether or not to show disabled items.
So you have cond2
that depends on the items, and cond1
that does not. Here's the dilemma I got into: Should I use cond1 && !cond2
or !(!cond1 || cond2)
? Or should I check for the cond2
(show disabled items) before the loop? I also thought (as you will see in the code I put) if I should put the cond2
before cond1
, because cond2
is a boolean variable, and with "short-circuits" (lazy evaluation?), it will be faster?
My main concern was speed. If I have many items in the loop, this might be an important change.
This is code that illustrates the options:
// First Option
for (String item : items) {
doSomethingFirst(item);
if (isDisabled(item) && !showDisabled) {
continue;
}
doSomethingElse(item);
}
// Second Option
for (String item : items) {
doSomethingFirst(item);
if (!(!isDisabled(item) || showDisabled)) {
continue;
}
doSomethingElse(item);
}
// Third Option
if (showDisabled) {
for (String item : items) {
doSomethingFirst(item);
doSomethingElse(item);
}
} else {
for (String item : items) {
doSomethingFirst(item);
if (isDisabled(item)) {
continue;
}
doSomethingElse(item);
}
}
So, does the order of isDisabled(item)
and showDisabled
matter? Should I be checking on things before the loop? Or does the compiler optimize that? (I doubt...)
PS I don't know how I would take measurements to see actual values, if it's relevant please do.
Thanks.
Upvotes: 0
Views: 3308
Reputation: 39403
Regarding readability, another good practice is to name functions and variables in their positive state. It's hard to read double negatives. Which one would you rather read?
enabled
Or
!disabled
There are some few cases though that naming things in their negative form makes sense. An example, if you will use them for terminating condition, e.g. end of file. while(!feof(fp))
But in most cases, the norm should be is to name things in their positive form, so reading code has lesser friction.
Let's see how your code looks like in positive form:
// First Option
for (String item : items) {
doSomethingFirst(item);
// if (isDisabled(item) && !showDisabled) {
if (!isEnabled(item) && showEnabled) {
continue;
}
doSomethingElse(item);
}
The readability on that code surely improved.
And even the following become readable too, the double negatives can be avoided, reading code is really merely reading it, not figuring it out too much. I once read an article that suggest that when writing code, it should be very pleasant to read too, he said reading code should not be like reading a detective novel. Reading double negatives code is like reading and deciphering a detective novel.
// Second Option
for (String item : items) {
doSomethingFirst(item);
// if (!(!isDisabled(item) || showDisabled)) {
// You can now avoid double negatives
if (!( isEnabled(item) || !showEnabled )) {
continue;
}
doSomethingElse(item);
}
In fact, the following is not merely double negative, it's a triple one:
if (!(!isDisabled(item)
It will take a two-pass read, or even a three-pass before you can decipher what's the intent of that code
Upvotes: 2
Reputation: 20065
In Java the expression is evaluated from left to right. With &&
if the first condition is false, the second one is not executed, with ||
if the first condition is true, the second one is not executed.
So try to put the condition that can be resolve faster in first place, in your case showDisabled
.
For the third example, it looks better because you check the boolean only once but I guess it don't really change performance, a bool comparison is not really costly. You will probably have better improvement to do in other part of your code. (and for the readable aspect it's not my favorite - quite long)
If you want to measure the performance in your case use a profiler for example.
Or add in your code :
long start=System.currentTimeMillis();
//code to analyse
long timeSpent = System.currentTimeMillis()-start
You'll have to put your code in a loop, to make it relevant. And you will probably notice that Java will increase the performance after some loops ;).
Upvotes: 3
Reputation: 22890
I will go for the option 1, and just reverse switch
isDisabled(item) && !showDisabled
with
!showDisabled && isDisabled(item)
If isDisabled(...)
is as slow as you say it is better to test the faster case first.
Now compared to the other option this is the most explicit and readable:
It will be difficult to do more explicit. And the 3rd option is plain ugly.
Upvotes: 1
Reputation: 11607
Should I use cond1 && !cond2 or !(!cond1 || cond2)? Or should I check for the cond2 (show disabled items) before the loop?
Whatever expresses your thoughts best, i.e. whatever is more readable.
My main concern was speed.
Writing speed? Refactoring speed? Compilation speed? Development speed? Reading and understanding speed? Debugging speed? Execution speed?
You can't have all at once. In no language.
Upvotes: 1
Reputation: 272317
As always with these types of questions, you should measure this to determine if this itself is your bottleneck. If it is, then I would measure the alternatives. I suspect for the above scenario that it will make next to no difference for your alternatives, especially since you'll likely be doing something much more heavyweight with the list entries (displaying them? writing them to a db or file?)
The simplest way to measure this is to generate a sizable list, record the time (say, via System.currentTimeMillis()) before you process, process, and then record the ms (or seconds) taken.
Upvotes: 1