Functions and Subroutines

Functions and subroutines help define logic in one place, and allow you to use that logic in many other places throughout your rules.By placing your logic into a function or subroutine, you can keep your code "DRY" by following the best practice of "Don't Repeat Yourself".  As in other programming languages, Snap functions and subroutines can both accept input parameters, and functions can return an output value.


Function Example 1

The function is defined in the definition statement in the Start block. From there it can be used in the code below it.

Function Example 2

Certain functions -- such as those who make database queries, web service calls, or refer to safe functions – cannot be called using the same "call function" block as in Example 1. Instead, they must be called using this similar-looking "call function... returns" block. If you do not see your function in the drop-down list provided by the call function block shown in Example 1, try finding it in this block instead shown in Example 2.

Subroutine Example 3

Subroutines are the same as functions, except they do not return a value. Instead, they perform actions. In this example, it processes a car object such that the car's price attribute is rounded to a whole number.

Communication Between Your Code and a Subroutine / Function

The Snap language supports both primitive types (expressed like strings or numbers) and complex types, usually expressed as objects.

  • Primitive types are passed by value.
    In example 1, the function gets a separate, independent copy of the basic data values of 1 and 2.  These values, along with any other variables declared in the function, disappear at the end of the function's life.

  • Objects are passed by reference.
    In example 3, however, "car" passed into the subroutine is an object, since it was created from a database query.  We see the car object has a price property, and may have many other properties as well.  Objects are not passed by value, like primitive strings or numbers.  Objects are passed by reference, meaning the entire original object is passed into the function or subroutine, not an independent copy of it.  Because of this, changes made to that object by the function/subroutine remain, even after the function ends.

When writing a function or subroutine in Snap, consider which location for your library would be best.

Benefit Safe
Function
Global
Rule
Global
Function
Logic available to entire environment

   
Logic available through the REST API

   
Logic hidden

   
Logic available to only this configurator/scene  

Calculates faster, without network lag  

Can write directly to UI elements  

Can read directly from UI elements    

Storing your Subroutine / Function

Epicor CPQ has different places where you can store reusable logic.  Which one is best? While every application is different, consider these guidelines:

What does the function do? From where is it called? The best location for this function
Snap code that can run locally From only one place,
in only one configurator.

Define your function in that same rule type, so it's easy to maintain.

For example, a function to help a value rule work can be defined at the top of that value rule, or in any preceding value rule.

Snap code that can run locally From many places
in only one configurator.
Define your function in a "global" rule type, so it's visible throughout the configurator.
Snap code that can run locally From many configurators.

For faster user experience:
If performance needs to be fast, then define it as a global rule in a configurator, then copy/paste into other configurators.  For example, name the global rule "Useful Function Library v1.0".  In exchange for speed, you assume some responsibility as an administrator to ensure any updates to the function library in one configurator are distributed across the configurators.  Editing the name of the rule (to "v1.1", for example) can help highlight differences.

For easier administrator experience:
If the risk of your code forking between two or more configurators is too great, then define your logic as a safe function.  You'll know every configurator is using this same function, and your code exists only once.  In exchange for this administrator convenience, your users will now have slightly slower performance as the safe function (stored on the server) is queried and internet latency will be part of their experience.

Snap code that can only be performed on a server, such as 

  • querying a database
  • sending emails
  • calling a web service
Anywhere
Define it as a safe function.

Remember, safe functions can be called from anywhere.  So if your configurator needs information from a database, simply query the database from a safe function, and then call that safe function from your configurator.  Here's a walkthrough example.

Keep your application secure.

Remember the Snap rules you write for your configurator or scene are executed in one of two places: either server-side within the cloud, or client-side within the user's browser.  Consider the best location to balance needs for security and speed.

  • Server Side
    Server-side code is executed on the server, and the results sent to the client. The Snap code itself is never sent to the user's device for execution. Server-side code is best for any proprietary calculations or patented, sensitive lookups. However, network latency does make this code slower.
    Examples: pricing rules, workflow rules, safe functions, global functions.
  • Client Side
    Most other code is processed within the web browser on the user's device.  Local to the user with no network latency, client-side code is fast and responsive.  However, it is not as secure: some users could expose the logic or comments within the rule, as they can with any client-side javascript.  Local rules are the best place for code which runs often, needs to be fast, and does not contain sensitive calculations or comments.
    Examples: configurator rules, scene rules, global rules, etc.

You can easily mix and match your code, placing sensitive functions on the server and other code locally. Learn more about where Snap rules are executed.

Was this article helpful?