Program defensively against conditions that can fail
As a best practice, Guidewire recommends that you program defensively. Always assume that conditions might fail. Follow these recommendations to avoid common but easily missed programming flaws, such as potential null pointer exceptions and out-of-bounds exceptions.
Use case-insensitive comparisons
Use the equalIgnoreCase method on the string literal to compare it with the value of a variable. Case mismatch can cause comparisons to fail unintentionally.
if("Excluded".equalsIgnorecase(str)) { // proper comparison method
print("They match.")
}
if(string.equals("Excluded")) { // improper comparison method
print("They do NOT match.")
}
Check for null values
If your code cannot handle a variable that
contains non-null values, check the variable for null before you access properties
on the variable.
function formatName (aUser : User) {
if (aUser != null) { // Check for null to avoid a null pointer exception later in the code.
print(aUser.DisplayName)
}
else {
print("No user")
}
}
Also, check variables for null before you call methods on
variables:
function addGroup (aUser : User, : aGroupUser : GroupUser) {
if (aUser != null) { // Check for null to avoid a null pointer if you call methods on the variable.
aUser.addToGroup(aGroupUser)
}
}
Consider the following issues
if you do not check variables for null:
- Accessing a property on a variable may use null-safe property access, which can cause null pointer exceptions in later code that handles only non-null values.
- Calling a method on a variable risks a null pointer exception.
Allow default null-safe property access
If your code
can handle a variable that contains null values, you can rely on null-safe
access of simple properties in most cases. With null-safe property access,
the entire expression evaluates to null
if the left-side of a period operator is null.
For example, the
following sample Gosu code returns null
if the user object passed
in by the caller is null.
Default null-safe property access prevents a null pointer exception in
the return statement.
function formatName (aUser : User) : String {
return aUser.DisplayName // Default null-safe access returns null if the passed-in user is null.
}
Usage of explicit null-safe operators
If your code does not need to perform additional actions for an object path expression that
evaluates to null, use the explicit Gosu null safe operators:
?.– Null-safe access to methods?[]– Null-safe access to arrays
Note that access to properties is always null-safe.
The following sample Gosu code uses the explicit null-safe operator ?. to check
for null to avoid a null pointer exception while calling a method. If
either aPerson or aPerson.PrimaryAddress is
null, Gosu does not call the method hashCode and
the entire object path expression aPerson.PrimaryAddress?.hashCode()
evaluates to 0, which is the int value for
null.
function formatName (aPerson : Person) : int {
// An explicit null-safe operator returns null if aPerson or PrimaryAddress is null.
return aPerson.PrimaryAddress?.hashCode()
}
The following sample Gosu code uses the explicit null-safe operator ?[] to check
for null to avoid a null pointer exception while accessing an array. If
strings[] is null, the entire expression
strings?[index] evaluates to null. However, the
null-safe operator does not avoid out-of-bounds exceptions if strings[]
is non-null and the value of index exceeds the array length. For
example, if the array is empty rather than null, an out-of-bounds
exception occurs.
function getOneString (strings : String[], index : int) : String {
return = strings?[index] // An explicit null-safe operator evaluates to null if an array is null.
}
See also
Check boundary conditions
In for
loops, check for boundary conditions ahead of the loop. Entering a loop
if the boundary condition is satisfied already can cause null pointer exceptions
and out-of-bounds exceptions.
Use structured exception handling
Use try/catch blocks wherever required
and possible. If you want to catch multiple exceptions, handle them in
a hierarchy from low-level, specific exceptions to high-level, generic
exceptions.
