This is the first in a two part series of articles regarding FileMaker’s custom function feature. I’ve seen a number of opinions that deride the excessive use of custom functions for various reasons. In this first part I’ll outline what I do (and don’t) like about FileMaker’s implementation. Next time I’ll offer some tips on how, at least to some extent, you can overcome what limitations do exist.
The arguments against widespread use of custom functions assumes first that almost everything that can be done with custom functions can also be done with scripting (true), and therefore:
While the first assertion is true, I find it a weak argument. Custom functions offer too much convenience to allow their requirement of FileMaker Pro Advanced to hinder their use.
As far as the second argument is concerned, it’s going to be a tradeoff, I suppose. Importing scripted versions of algorithms instead of custom function versions is also going to have dependencies, but so do scripts. And the process of importing a library of cutstom functions is a two-minute operation, easily recouped in saved development time later.
FileMaker hasn’t yet perfected the custom function feature. My wish list for custom functions includes:
Char was for me). The same tecnique I use for organization addresses this problem. Look for it in this article’s sequel.
One of the defenders of scripts in preference to custom functions mentions that he places portability in high priority. I’ll admit that while portability is nice, I place maintainability higher, and assuming the use of FileMaker Pro Advanced in one’s toolkit, custom functions are as, if not more, portable as scripts.
I don’t think anyone’s actually claimed that the choice of using custom functions is also a choice between portability and maintainability. What has been claimed is that custom functions aren’t as portable as scripts because importing scripts doesn’t require FileMaker Pro Advanced. While technically true, having a license to FileMaker Pro Advanced seems like a fairly low barrier of entry. It’s included with every site license and for individuals is only $180/year (or, as FileMaker somewhat ingenuously puts it, $15/month). And once you have FileMaker Pro Advanced, importing custom functions is a very quick, as easy as importing scripts.
The point of portability seems to be that the quality of the software’s evolution will increase over time if it can be easily used by many people, and it can only be easily used by many people if it’s portable. I’m a firm believer in the power of open source software, which is why my own custom function library, as well as other FileMaker-related resources, are available on Github. But as easy as it is to get started building useful software with FileMaker, the people who are most likely to contribute to such an open source approach are also the ones who will be working with FileMaker Pro Advanced.
There are very few instances where a feature would be impossible without a custom function. The only instance I could conceive would be where recursion were needed within a calculation that couldn’t be scripted, such as a calculation field or a “hide when” calculation, and if you wanted to avoid custom functions completely, even these limitations could be worked around.
But custom functions provide more maintainable software in a number of ways.
A fairly simple example is the need to find out how many repetitions a field has available. The raw calculation for doing so is:
GetAsNumber ( RightWords ( FieldType ( Get ( FileName ) ; GetFieldName ( _repeating_field ) ) ; 1 ) )
Without a custom function that encapsulates that logic, when I need to know how many repetitions a field has, I have three choices: figure it out anew each time; find where I did it before so I can copy and paste it; use a script to store that logic, call the script and use
Get ( ScriptResult ) to get the final value. The first two seem to me to be eliminated immediately, and the last one gives us the difference between
Set Variable [ $_repetitions ; rept.FieldReps ( _repeating_field ) ]
Perform Script [ FieldsReps ; Parameter: GetFieldName ( _repeating_field ) ] Set Variable [ Get ( ScriptResult ) ]
with the latter one not only involving an additional script in the stack during debugging but, in this case, the breaking up of the logic between the called script and the script parameter (since the called script wouldn’t have access to the original field, only the contents of that field passed by parameter).
By storing layout object names in a custom function, such as
appl.PanelEdit, should the name ever change, it need do so only on the layout object and within the custom function, rather than in every calculations that references the name.
By storing string constants in a custom function, FileMaker’s calculation engine will provide a degree of syntax checking. FileMaker won’t catch it if I mistype
"paneledit", but if I mistype a custom function name incorrectly, for example, typing
appl.PanlEdit instead of
appl.PanelEdit, FileMaker will alert me.
This also works nicely for global fields, such as
$$_TRIGGERS_DISABLE, as well. FileMaker won’t balk at my typing
$_TRIGGERS_DISABLE, but will if I type
trig.Disabeld instead of
Don’t look it up: what does
Get ( WindowMode ) return when find mode is active? What error code is generated when attempting to access a missing field? How about what values
Get ( ActiveModifierKeys ) can return when the shift key is pressed? Or which string to pass to
GetLayoutObjectAttribute to find out if a tab panel is in front?
Personally, I don’t know and I don’t need to ever look it up. I have custom functions for these, and can write calculations such as
Get ( WindowMode ) = mode.Find,
Get ( LastError ) = errn.FieldIsMissing,
mkey.ModifierKeyIsActive ( mkey.Shift ) and
devp.TabPanelIsFront ( appl.MyTabPanel ).
Answering the first three questions above in order, find mode is indicated with
1, a missing field with error
102, and possible values with shift held down are any odd number between 1 and 31. If I avoid custom functions for any of these, I’m going to either have to remember what they mean when I later read them, or add a comment, something like
Get ( WindowMode ) = 1 // Find mode or
Get ( LastError ) = 102 // Field is missing. But with the calculations that do use the custom functions, the code is self-documenting. There’s no need for an extra comment.
If you’re one of those who tends to avoid custom functions, I’d encourage you to try using them as I’ve described above. FileMaker 14’s auto-fill feature in calculation dialog boxes will find all of the custom functions you have in your solution, making it easier than ever to integrate them.
Come back soon for some tips on how to ease the use of custom functions with some simple techniques.