Scripting: If Statements and Exit Script

I typically create scripts with the structure:

Enter Find Mode
Set Field
Set Field
Set Field
Perform Find
If Get Found Count > 0
Do Stuff
Else
Show Custom Dialog - No Results
End If
Exit Script

However, I’ve seen another structure:

Enter Find Mode
Set Field
Set Field
Set Field
Perform Find
If Get Found Count = 0
Show Custom Dialog - No Results
Exit Script
End If
Do Stuff
Exit Script

While I like the logic flow of the first method, the second may be easier to read. What is your preferred method?

The second structure you've described is sometimes called a guard clause. It's used to ensure that code is not run unnecessarily. They can improve readability in several ways. You've shown one way, which is that if the preconditions for the remaining code are not met then the script stops. It is also self-documenting ( not taking the place of documentation but it makes itself clear ) in that you can see immediately that the code will handle the "nothing found" case and how it handles it.

Another reason I like it is that it keeps the code simpler. When you nest code within multiple IF statements it is possible to lose track of which lF an ELSE refers to. Guard clauses flatten the code by reducing the amount of nesting.

4 Likes

Yes, I’m considering switching to this format to reduce the indenting a bit. Thanks for the info.

The first form has this disadvantage: if the code to be executed is quite long, then to find the else code forces the developer to scroll down to the bottom of the script.

With the the second form, the 'else' is right at the beginning, then the long code is after.

2 Likes

Thanks, I’ll experiment with a guard clause on my next script.

You're received great replies, but I'll just add a voice to preferring the second structure as well, for the reasons mentioned (mostly exiting ASAP). Cheers

2 Likes

I am not a fan of guard clauses, however I use a variation of the second. I substitute the exit clause with an else clause. My logic goes this way: write the if condition such that errors are processed at the start because they are usually short code blocks. I find this enhances readability.

2 Likes

I mostly use only one Exit in a script except if it is a script trigger before the event - even then it is possible to keep one exit using a calc for the result.

3 Likes

I'm a big fan of the single-pass Loop as a way to break out of a script early, while still having only one exit script line:

Loop
  # single-pass loop

  Enter Find Mode
  Set Field
  Perform Find
  # The calc below assumes a CFs called Error() and ErrorFound() exist
  Exit Loop If [ Let ( $error = Error ( Get(LastError) ; "Perform Find" ) ; ErrorFound($error) ) ]

  # Do Stuff

  # end single-pass loop
  Exit Loop If [ True ]
End Loop

If [ ErrorFound ( $error ) ]
  # Handle error here. Show dialog? Log error? Revert Transaction?
End If

Exit Script [ JSONSetElement ( "{}" ; [ "error" ; $error ; JSONObject ] ) ]

One huge benefit is that this is a generalized strategy for breaking early that works with any type of "error" or any condition you consider an error/exit-worthy. So you could also add error traps after Enter Find Mode, and Set Field to catch unexpected errors like a trigger canceling the layout mode change and privilege restrictions preventing the user from setting that search field.

It also lets you centralize the error handling and Exit Script, so if you have a long-ish procedure for handling errors, you only have to put it in one location.

EDIT: I really wish Claris would give us Try/Catch so that you could passively trap for Get(LastError) without having to explicitly poll for it after each script step. My scripts would be half as long

4 Likes