This is the second post in a series on writing cleaner code in your WCMS Velocity formats.
In my previous post, I talked about how we can apply the PSR-1 Coding Standard’s recommendation on side effects to our Velocity code in an effort to make our Velocity formats easier to reason about.
In this post, I’m going to continue this train of thought, bringing in some lessons from pure functions.
Pure functions applied to Velocity
Last April, I wrote about pure functions and how they’re an essential part of functional programming:
Pure functions don’t affect any part of your program outside of themselves — they can only work with data you pass to the function. They can’t change that data, but can and usually do spit out remixed copies. Pure functions can’t change program state.
Velocity macros aren’t functions in the strictest sense of the term, especially because they don’t “return” values — they always create output. Still, we can benefit from borrowing some of the principles of pure functions.
Only transform data passed to the macro
In functional programming, pure functions can only operate on the data they’re given. They also can’t mutate that data — they can only create new data from the originals.
Like functions, Velocity macros can be defined to take one or more parameters. However, a Velocity macro inherits access to all variables defined in the calling format.
For example, if you define a variable in
$primaryColor and then call
#showProfileImage() macro can access
$primaryColor, even if you don’t explicitly pass it.
As I bet you can imagine, referencing variables not explicitly passed to a macro introduces problems similar to global variables in languages like PHP — it jams us up with action at a distance. Stick to a simple principle: if you need some data in a macro, pass it as a parameter.
Likewise, try to avoid re-assigning the value of variables passed to Velocity macros, especially since it’ll affect Velocity formats downstream that rely on that variable. Make things easier on yourself: sidestep state and treat the data passed to macros as immutable.
In a perfect world, your Velocity macros should only use the data passed to them as a means to create a new representation of that data as HTML, JSON, or whatever output you’re building.
Don’t make me read the whole framework
As programmers, we spend most of our time reading code, not writing it. One of the most important parts of writing readable code is structuring it so that you can reason about the individual pieces in isolation.
When I load up someone else’s code (or code I wrote in the past), I should be able to jump directly to the piece I’m worried about and start hacking at it without needing to (re-)read the entire codebase.
By applying the principle of pure functions to Velocity macros, we can better isolate the individual parts of our codebase, which helps make our WCMS frameworks a lot easier to maintain.