Note: All example code is in Java.
true" or "false"| Example of Problem | Simplification |
|---|---|
b == false |
!b |
General Rule: the boolean literals, i.e. the keywords "true" and "false",
should only be assigned, passed or returned.
Don't operate on them with "==", "!=", "&&", "||" or "!": every such case can be simplified.
Discussion: this is a reason to use good variable names for booleans, e.g. "if (!checked) ..." and "if (isRaining()) ..." read better than "if (x) ...", and make it less tempting to add "== true".
| Example of Problem | Simplification |
|---|---|
if (x < 2) {
return true;
} else {
return false;
}
|
return x < 2; |
if (it.next().isRed()) {
m(true);
return false;
} else {
m(false);
return true;
}
|
boolean nextIsRed = it.next().isRed(); m(nextIsRed); return !nextIsRed; |
General Rule: an if-else with branches differing only in the use of "true" versus "false" should be rewritten without if-else. Use one of the branches, replacing its differing uses of "true" or "false" with the condition or negated condition. If there is more than one use of a boolean literal and the condition is complex or has side-effects, store the condition's value in a temporary variable and use that.
| Example of Problem | Simplification |
|---|---|
(a && b) || (c && a) |
a && (b || c) |
(a || b) && (a || c) |
a || (b && c) |
General Rule: undistribute the two Distributive Laws of Propositional Logic, as shown in the examples, "factoring out" the repeated condition.
Exception: the simplification usually isn't equivalent if the repeated expression has side-effects.
Discussion: think about the similarity to the next issue below.
if-else| Example of Problem | Simplification |
|---|---|
if (x()) {
a();
b();
c();
} else {
a();
d();
c();
}
|
// Assumes a() and x() don't have side-effects affecting each other
a();
if (x()) {
b();
} else {
d();
}
c();
|
General Rule: move statements appearing at the start or end of both branches of an if-else outside of the if-else.
Exception: the simplification isn't equivalent if the condition and a statement moved from the start of the branches have side-effects affecting each other. In this case consider storing the condition's value in a temporary variable first:
| Form: same statement at start of both branches | Equivalent form, even if side-effects |
|---|---|
if (<condition>) {
<repeated-statement>
<rest-of-first-branch>
} else {
<rest-of-second-branch>
<statements>
}
|
boolean c = <condition>;
<repeated-statement>
if (c) {
<rest-of-first-branch>
} else {
<rest-of-second-branch>
}
|
Discussion: think about the similarity to the previous issue above.
if inside an else| Example of problem | Syntactic convention: partially unindented and unbraced |
|---|---|
if (x < 0) {
s1();
} else {
if (x == 0) {
s2();
}
}
|
if (x < 0) {
s1();
} else if (x == 0) {
s2();
}
|
General Rule: use the unnested form of if-else-if for mutually exclusive or related conditions. In Java this means using the unbraced form for the else clause, and unindenting one level. In languages with a dedicated special syntax for this case, use that: discussion of convention versus special syntax.
Exception: you have considered both forms, and there levels of condition checking you want to emphasize. For example:
if (x < 0) {
if (y == 1) {
s1();
} else if (y == 3) {
s3();
}
} else {
// condition on y relying on implicit x >= 0
if (y == 2) {
s2();
}
}
| Example of problem | Simplification |
|---|---|
int x; x = 0; |
int x = 0; |
General Rule: don't declare and initialize a variable in two consecutive statements, instead use the single statement form.
Exception: two or more related variables are declared together but only some are initialized. For example:
int x, y; y = 0;