Velocity ${formal.notation} invites syntax errors: use it wisely

There are 2 ways to access references (i.e. variables) in Velocity.

① Simple/shorthand notation, prefixed with a $:

$variableName
$variable.property
$variable.method()
$variable.property.method()

② Formal/longhand notation, prefixed with $ and wrapped in {} (curly braces):

${variableName}
${variable.property}
${variable.method()}
${variable.property.method()}

Simple notation should be your default; formal notation should only be used when there's no alternative. As the Velocity docs say:

In almost all cases you will use the shorthand notation for references, but in some cases the formal notation is required for correct processing.

I'd go further: when used unnecessarily, formal notation can make your code confusing and fragile. Unfortunately, Marketo's script editor doesn't help you learn best practices, because when you drag a field from the field tree to the editor canvas, it's automatically wrapped in ${}:

ss

You should remove the curly braces right away, and only restore them if it proves necessary during development.

What can go wrong?

A recent Community post shows how confusing things can get when you use formal notation unnecessarily (note how the poster titled it “... tokens behave unexpectedly” when it's actually established behavior, if not well-circulated).

The catch: a reference enclosed in ${formal.notation} cannot be chained with a method/property outside the curly braces.

OK, that probably didn't make sense unless you're fluent in OO-speak! Let's look at some examples.

Here's something that does work with simple notation:

#if( $lead.FirstName.isEmpty() )

It doesn't work if you only enclose part of the expression in formal notation:

#if( ${lead.FirstName}.isEmpty() )

Sure, it would work if you happened to enclose the entire expression in curlies —

#if( ${lead.FirstName.isEmpty()} )

— but you should just use simple notation instead, because it's harder to mess up during refactoring.

Don't believe me? (You probably do, or I'd like to hear who's more authoritative about Velocity.) Consider what happens when you move from a not-best-practice, but syntax-error-free, comparison using double-equals ==:

#(if ${lead.numberOfProducts} == 0 )

to a more forward-looking equals():[1]

#if( ${lead.numberOfProducts}.equals(0) )

Suddenly, your Velocity token stops working because you can't have a . after a }. It may be clear, to you as a human, what you meant, but VTL doesn't allow it. If you'd used simple notation from the start you wouldn't have to make such adjustments.

When do you need to go formal?

Formal notation should only be considered inside strings or output, and only used when the separation between variables and static text would otherwise be unclear.

If you're in a line of code starting with #if or #set chances are very slim that you should be using formal notation.

Where is it necessary? When you have a variable butting right up against static text, and otherwise you couldn't tell where one ends and the other begins. Here, for example, you might be trying to use the variable $salary (stored in millions) followed immediately by the string "MM":

With your yearly income of of $salaryMM, you'll sure like this solid gold barbecue set.

That won't work unless you use formal notation, because Velocity thinks you mean the variable $salaryMM. So that's an occasion for formal notation:

With your yearly income of of ${salary}MM, you'll sure like this solid gold barbecue set.

However, this wouldn't need formal notation:

Good $time_of_day, $nickname!

Because the comma "," isn't allowed as part of a variable name, Velocity isn't confused and knows you mean $time_of_day followed by the comma.

Again, only use formal notation if you have a proven need based on ambiguous output.


Notes

[1] Comparing with == is acceptable in Velocity, but bad in Java. In the interest of writing Java-portable code, use equals(). I'm refactoring my old
VTL code accordingly.