Error Handling Strategies
The Guardian Pattern strategically places a guard condition before a risky operation in an 'and' expression to prevent runtime errors.
Preventing the Failure
A runtime error can occur when a program performs an operation before confirming that the operation is safe. The Guardian Pattern addresses this by placing a guard condition before the risky operation in an and expression. If the guard is false, short-circuit evaluation stops the expression, so the later operation is not run.
Following the Short-Circuit Path
The Guardian Pattern depends on short-circuit evaluation. The expression checks the guard first. When that condition is false, evaluation stops immediately. Because evaluation stops, the subsequent risky operation is prevented from running. When the guard is true, evaluation can continue to the operation that follows it.
What do you think happens?
Suppose an and expression checks whether a denominator is non-zero before using that denominator in a calculation. What should happen when the denominator is zero?
Reveal answer
The guard becomes false and the later operation is skipped.
Short-circuit evaluation stops the expression as soon as a condition is false, so the later operation is not run.
A Guarded Calculation
Checking a Denominator Before Use
Construct an and expression that uses a denominator only after checking that it is non-zero.
- 1Name the risk
The risky part is the calculation that uses the denominator.
- 2Create the guard
Use a condition that checks whether the denominator is non-zero.
- 3Place the guard first
Put the non-zero check before the calculation in the and expression.
- 4Follow the false path
If the denominator is zero, the guard is false, short-circuit evaluation stops, and the calculation is not evaluated.
- 5Follow the true path
If the denominator is non-zero, the guard is true, so evaluation may continue to the calculation.
The guarded expression protects the calculation because the condition that establishes safety appears before the operation that depends on it.
The important feature of this example is not the particular calculation. It is the dependency order: first establish that the denominator is safe, then allow the calculation that uses it to be considered. The guard is useful because it controls whether the risky operation is reached.
Ordering the Conditions
In a guarded logical expression, the conditions are not interchangeable. The guard must appear before the operation it protects. This ordering allows a false guard to stop evaluation before the risky operation is reached. If the risky operation appears first, it may be evaluated before the program checks the condition intended to protect it.
| Condition order | What happens when the guard is false | Protection |
|---|---|---|
| Guard, then risky operation | Short-circuit evaluation can stop before the risky operation | The intended Guardian Pattern |
| Risky operation, then guard | The risky operation may already have been evaluated | The guard may fail to protect the operation |
The position of the guard determines whether short-circuit evaluation can prevent the risky operation.
When Protection Fails
Common mistake Putting the guard after the risky operation
What it looks likeThe expression attempts the operation first and checks the safety condition afterward.
Why it failsShort-circuit evaluation can stop only at the point where a false condition is encountered. A later guard cannot undo an operation that has already been evaluated.
Do this insteadMove the guard before the risky operation.
Common mistake Treating condition order as unimportant
What it looks likeThe same two conditions are rearranged without considering which one depends on the other.
Why it failsThe Guardian Pattern relies on the guard being evaluated first.
Do this insteadIdentify the operation that could cause a runtime error, then place its safety check before it.
Common mistake Using a guard that does not establish the needed safety
What it looks likeAn expression checks a value that is unrelated to whether the risky operation is safe.
Why it failsA condition protects an operation only when it checks the relevant safety requirement.
Do this insteadMatch the guard to the risk: check for a non-zero denominator before using it, a valid array index before accessing an array position, or valid data before using that data in a calculation.
Building the Expression
- 1Identify the operation that could produce a runtime error.
- 2Determine the condition that would make that operation safe.
- 3Place the safety condition first in the and expression.
- 4Place the risky operation after the guard.
- 5Trace the false-guard path and confirm that short-circuit evaluation stops before the risky operation.
- 6Trace the true-guard path and confirm that evaluation can continue to the operation.
The reusable structure is: relevant safety check, then and, then dependent operation. The safety check comes first because a false result must be able to stop evaluation before the dependent operation runs.
Practice the Guard
For each situation, identify the guard and the risky operation, then describe their correct order in an and expression: a calculation involving a denominator, an access using an array index, and a calculation using data whose validity has not yet been confirmed.
Hints
- The guard should state the safety condition relevant to the risk.
- Place the guard before the operation it protects.
- Ask what must be true before the operation can safely be considered.
A strong answer should name both parts of each pair. For the denominator case, the guard checks for a non-zero denominator. For the array case, the guard checks for a valid index. For the data case, the guard checks that the data is valid. In every case, the guard comes before the operation that uses the value.
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 and thereby prevent a runtime error.
- 4Condition order is essential: the guard must come before the operation it protects.
- 5Useful guards check non-zero denominators, valid array indices, and valid data values.
At a glance
- The Guardian Pattern uses a safety condition before a risky operation.
- Short-circuit evaluation prevents later operations from running when an earlier condition is false.
- A guard fails to protect code when the risky operation is placed before the guard.
- To construct a guarded expression, identify the risk, write its relevant safety check, and place that check first.