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.