Glorious Custom Functions

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:

  • Custom functions are less portable than scripts because scripts do not require FileMaker Pro Advanced, whereas custom functions do.
  • Custom functions introduce unecessary dependencies, breaking functionality of modular solutions if they aren’t present.

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.

Where Custom Functions Fall Short

FileMaker hasn’t yet perfected the custom function feature. My wish list for custom functions includes:

  • Ability to use FileMaker 14’s new calculation interface, which includes the use of a mono-spaced font and auto-fill suggestions for fields and functions. But the custom function calculation window doesn’t use this yet. Hopefully we won’t have to wait until FileMaker 15 to see this addition. Once we have that, much of the reason for my development of filemaker.vim (syntax highlightlighting would also be nice) will have evaporated.
  • Ability to step through a custom function. My study of Lisp has influenced this. Lisp is a fascinating language that actually has many similarities with FileMaker’s calculation engine, especially within custom functions. One of the features that many Lisp implementations offer is a step-level debugger that will simplify a Lisp form one step at a time, allowing insight into what may be going wrong. Such a feature for FileMaker calculations in general, and custom functions in particular, would be a welcome addition. My next article will point out some techniques for getting around this limitation.
  • Organizational features similar to what we have with layouts and scripts, including folders and dividers. In my next article I’ll show how I emulate this to some extent.
  • Namespacing features to ensure that custom functions can’t have duplicating calling names nor be overridden by future built-in FileMaker functions (like Char was for me). The same tecnique I use for organization addresses this problem. Look for it in this article’s sequel.

not (Portability xor Maintainability)

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.

To Calc or Not To Calc

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.

  • Custom functions allow the abstraction of complicated logic into a very compact call.

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).

  • Custom functions reduce duplicated strings.

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.

  • Custom functions allow syntax checking of string constants and global variables.

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 "panel.edit" as "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 $$_TRIGERS_DISABLE or $_TRIGGERS_DISABLE, but will if I type trig.Disabeld instead of trig.Disabled.

  • Custom functions prevent me from having to search FileMaker’s documentation.

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 ).

  • Custom functions allow for self-documenting code.

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.

// End

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.


0 # Matt Petrowsky 2015-05-20 21:10
Nice writeup Chuck! I'm a big fan of custom functions.
Reply | Reply with quote | Quote

Add comment

Security code