Using Optional Method Arguments
Using optional, named method arguments on your helper functions can make your code easier to read and more self-documenting. For example, consider a global helper function queryRows() that simplifies common querying use cases.
Sometimes your calling code only requires a select
list and a
from
clause:
def rates = adf.util.queryRows(select: 'FromCurrency,ToCurrency,ExchangeRate',
from: 'DailyRates_c')
where
clause to filter the data and an
orderBy
parameter to sort
it:def euroRates = adf.util.queryRows(select: 'FromCurrency,ToCurrency,ExchangeRate',
from: 'DailyRates_c',
where: "FromCurrency = 'EUR'",
orderBy: 'ExchangeRate desc')
By using
optional, named arguments, your calling code specifies only the information required and
clarifies the meaning of each argument. To adopt this approach, use a single parameter of
type Map
when defining your
function:// Global Function
List queryRows(Map options)
queryRows()
function is to explicitly pass
a Map
as its single argument like
this:// Passing a literal Map as the first argument of queryRows()
def args = [select: 'FromCurrency,ToCurrency,ExchangeRate',
from: 'DailyRates_c']
def rates = adf.util.queryRows(args)
You can also pass a literal Map
inline without assigning it to a local
variable like this:
// Passing a literal Map inline as the first argument of queryRows()
def rates = adf.util.queryRows([select: 'FromCurrency,ToCurrency,ExchangeRate',
from: 'DailyRates_c'])
Map
directly inside the function call
argument list you can omit the square brackets. This makes the code easier to
read:// Passing a literal Map inline as the first argument of queryRows()
// In this case, Groovy allows removing the square brackets
def rates = adf.util.queryRows(select: 'FromCurrency,ToCurrency,ExchangeRate',
from: 'DailyRates_c')
Map
argument representing your function's optional parameters must be
first. If your function defines additional parameters, then when calling the
function, pass the values of the other parameters first followed by any optional,
named parameters you want to include. For example, consider the signature of following
findMatchingOccurrences()
object function that returns the number of
strings in a list that match a search string. The function supports three optional
boolean
parameters caseSensitive
,
expandTokens
,
useRegExp
.Long findMatchingOccurrences(Map options, List stringsToSearch, String searchFor)
stringsToSearch
and searchFor
as shown
below:// Use an object function to count how many emails
// are from .org or .edu sites
def nonCommercial = findMatchingOccurrences(emails,'.*.org|.*.edu',
caseSensitive: true,
useRegExp: true)
Regardless of the approach the caller used to pass in the key/value pairs, your function
body works with optional, named arguments as entries in the leading Map
parameter. Be aware that if no optional argument is included, then the leading
Map
parameter evaluates to null
. So assume the
options
parameter might be null
and handle that case
appropriately.
queryRows()
global function. Notice it
uses the safe-navigation operator (?.
) when referencing the
select
property of the options
parameter just in case
it might be null
and signals an error using another global function named
error()
.// Global Function: List queryRows( Map options )
// ---------------
// The options Map might be null if caller passes no named parameters
// so check uses the safe-navigation operator to gracefully handle the
// options == null case, too. We're assuming another global helper function
// named 'error()' exists to help throw exception messages.
if (!options?.select) {
adf.util.error("Must specify list of field names in 'select' parameter")
}
if (!options?.from) {
adf.util.error("Must specify object name in 'from' parameter")
}
// From here, we know that some options were supplied, so we do not
// need to continue using the "?." operator when using options.someName
def vo = newView(options.from)
// etc.