What is a short-circuit statement? In this case, I’m not talking about the language feature related to boolean comparisons, but instead I’m talking about statements which cause a method to return as soon as some conclusion has definitely been reached. Here’s an example from a very simple compareTo
method in Java:
public int compareTo(Foobar that) { if (that == null) return -1; if (this._value < that._value) return -1; if (this._value > that._value) return +1; return 0; }
In this example, each line (except the last one) would qualify as a short circuit statement; that is, they all return as soon as a definite answer is determined, thus leaving some code in the method un-run. If we weren’t using short circuit statements, then the code may look like this:
public int compareTo(Foobar that) { int result = 0; if (that == null) { if (this._value == that._value) { if (this._value < that._value) { result = -1; } else { result = +1; } } } return result; }
For something this simple, there isn’t a huge difference in the complexity between the two functions, but it still demonstrates the point. Many people ardently recommend always having a single return
statement in any function, and would strongly advocate using the second example over the first. However, I would argue that the first is superior because it better respects the unit economy of the reader.
Short circuit statements allow a reader to take certain facts for granted for the remainder of a method. In the first example, after reading the first line of the method, the reader knows that they will never have to worry about the that
variable having a null
value for the rest of the method. In the second example, the reader will have to carry the context of whether he is still reading code within the first if
statement. Every short circuit statement removes one item from the set of things one must consider while reading the remainder of the method.
Naturally, this example is pretty simplistic, and it’s a stretch to claim that either method is more complicated than the other. However, consider if this weren’t a simple example. If this were a formula to compute an amortization table for a home mortgage, then the first few lines may look like this:
public AmortizationSchedule computeSchedule( int principle, float rate, int term) { if (principle <= 0) throw new IllegalArgumentException( "Principle must be greater than zero"); if (rate < 0.0) throw new IllegalArgumentException( "Rate cannot be less than zero"); if (term <= 0) throw new IllegalArgumentException( "Term must be greater than zero"); // Here is the 20 or so lines to compute the schedule... }
In this case, there may be a substantial amount of code following this brief preamble, and none of it has to consider what may happen if these invariants are broken. This greatly simplifies the act of writing the code, the logic of the code itself, and the process of maintaining the code later on.