Conditional Logic and Decision Making
The Guardian Pattern strategically places a guard condition before a risky operation in an 'and' expression to prevent runtime errors.
Why Order Matters
A logical expression can do more than produce a final true or false result. The order of its conditions can determine whether a later operation runs at all. The Guardian Pattern takes advantage of this behavior by placing a safe guard condition before an operation that could cause a runtime error.
What do you think happens?
Suppose an and expression checks a guard first, and that guard is false. What happens to the risky operation that comes after it?
Reveal answer
The risky operation is skipped
Short-circuit evaluation stops the expression as soon as a condition is false, so subsequent operations do not run.
Following a Guarded Expression
The Guardian Pattern has two parts. First comes the guard: a condition that checks whether it is safe to continue. After the guard comes the risky operation: an operation that should run only when the guard succeeds. In an and expression, a false guard stops evaluation before the risky operation is reached.
Checking a Denominator Before a Calculation
A calculation should use a denominator only when the denominator is non-zero. Which condition must come first in the guarded and expression?
- 1Identify the guard
The non-zero check is the guard because it determines whether the denominator is safe to use.
- 2Identify the risky operation
The calculation using the denominator is the risky operation because it should not run when the denominator is zero.
- 3Order the conditions
Place the non-zero guard before the calculation in the and expression.
- 4Apply short-circuit evaluation
When the guard is false, the expression stops and the calculation is not evaluated.
The non-zero denominator check protects the calculation only when it appears before the calculation.
Building the Safe Order
To construct a guarded and expression, first identify what could cause a runtime error. Then identify the condition that proves the operation is safe. Place that guard before the risky operation. The guard must be evaluated early enough to stop the expression before the risky operation is reached.
| Potentially risky use | Guard to place first |
|---|---|
| Using a denominator in a calculation | Check that the denominator is non-zero |
| Using an array index | Check that the index is valid |
| Using a data value | Check that the data value is valid |
Common guard-and-operation relationships
When Protection Fails
An incorrectly ordered expression evaluates the risky operation before it reaches the guard. If that operation encounters an unsafe value, the runtime error can occur before the guard has any chance to stop evaluation. The same guard may be present, but its position makes it ineffective.
Common mistake Putting the guard after the risky operation
What it looks likeThe expression attempts the calculation first and checks whether its input was safe afterward.
Why it failsShort-circuit evaluation can stop only operations that have not yet been reached. It cannot undo an operation that already ran.
Do this insteadMove the safety check before the calculation.
Common mistake Treating the presence of a guard as enough
What it looks likeAn expression contains both a valid-data check and an operation using that data, but the operation appears first.
Why it failsThe guard does not protect an earlier operation.
Do this insteadReview the evaluation order, not just the conditions that appear in the expression.
Common mistake Ignoring the specific unsafe input
What it looks likeA calculation uses a denominator without first checking whether it is non-zero.
Why it failsThe risky operation can run with an unsafe denominator before any protection is applied.
Do this insteadMatch the guard to the risk and place the non-zero check first.
Guard Construction Practice
For each situation, identify the guard and the risky operation. Then state which one must appear first in an and expression: a denominator that must not be zero, an array index that must be valid, and a data value that must be valid.
Hints
- The guard states the condition that makes the later operation safe.
- The risky operation is the use of the value, index, or denominator.
- The guard must come first so a false result can stop evaluation.
- 1Name the operation that could produce a runtime error.
- 2State the condition that makes that operation safe.
- 3Place the guard before the risky operation in the and expression.
- 4Check the false-guard path: the expression should stop before the risky operation runs.
- 5Check the true-guard path: the expression may continue to the risky operation.
Key Takeaways
- 1The Guardian Pattern places a guard condition before a risky operation in an and expression.
- 2Short-circuit evaluation stops the expression when a condition is false.
- 3A guard can prevent a later operation from running only when the guard comes first.
- 4Common guards check denominators, array indices, and data values before those values are used.
- 5Incorrect ordering can allow a runtime error before the guard is evaluated.
At a glance
- Use a guard condition to establish that a risky operation is safe.
- Place the guard before the risky operation in an and expression.
- Rely on short-circuit evaluation to stop when the guard is false.
- Remember that a guard placed after the risky operation cannot protect it.