TWikiFns
Background
As of Dakar, it became possible for plugins to associate a tag with a function, via
TWiki::Func::registerTagFunction. At the same time, most TWikiVariables became associated with the function that implemented them in the same way, although the code for all of these was contained in the module
TWiki.pm. Every
TWikiVariable was associated with its function, and every function was compiled every time
TWiki.pm was compiled.
At some point not too long after Dakar shipped, the following changes were made in the =DEVELOP=branch:
- The code for most of the TWikiVariables was moved into individual perl modules, one per variable
- A function was added that would load and compile the code as needed
- Any module
FOO.pm in the Fns directory would work in the same manner. That is, if %FOO{arg1="blibble" arg2="glibble"}% were encountered, FOO.pm would be automatically loaded and the call replaced with the resulting text.
Anyone who has used the
DEVELOP branch has been using this changed code without even noticing it. At least one site has been using this code for production purposes.
For various reasons not worth going into, they've been renamed TWikiFns: Fn as in function.
Benefits
Usability
Pluggable functions are a major plus for plugins authors. They are much easier to create than a full-blown plugin; thus, with proper documentation of TWikiFn development, there may be a large influx of helpful tags which will make it easier for users to do things without learning esoteric recipes. It also allows using many small tags with no performance hit. This make it much easier for the users to do things that ought to be simple, but currently involve complex searches or other machinations. For example:
Performance
As noted above, code for TWikiVariables that aren't used in a topic isn't loaded or compiled. As most of these functions are not very large, this probably doesn't have any significant performance benefit; nor does it appear to have any performance cost. However every full-blown plugin has a performance impact -- a Plugin object is created for each plugin and the code for each plugin is checked for handlers -- although it's unclear at this point how much of an impact each has. Since by definition TWikiFns have less impact, sites can use them without concern about performance costs.
Flexibility
Individual
TWikiVariables can be extended without changing
TWiki.pm.
Refactoring
By splitting out Fns from TWiki.pm we shorten the module, as well as laying necessary groundwork for pluggable functions. The advantage of pluggable Fns is the ability to extend/modify the functionality of the preprogrammed tags, and create pluggable documentation. For example, Meredith has added the more useful
SEARCH arguments to
METASEARCH, making it much simpler for people to do searches. Since the code for the
METASEARCH tag isn't part of
TWiki.pm any more but is, instead, a pluggable Fn, she was easily able to extend the functionality.
Documentation
By providing a
data/TWiki/VarTAG.txt we import the documentation in a form consistent with the existing
TWikiVariables; the documentation gets extended cleanly and seamlessly. This is
much cleaner than the plugins approach, and consistent with the concept of
PluggableDocumentation.
Impact on 4.1
Other than one change that I would like to see made, the code is written and working already. All that remains to be done is to write unit tests. If there are unit tests for the current TWikIVariables, this should be trivial (at least for those who comprehend unit tests).
There are several Fns that have been written and are being used. For example,
CHILDTOPICS lists the topics that have a given topic as its parent. There are probably a number of complex idioms -- mostly searches -- that could be turned into Fns, allowing easier authoring.
Current state
The scratch branch
http://svn.twiki.org/svn/twiki/scratch/TWikiFns/
contains a copy of
TWikiRelease04x00 as of somewhere around 4.0.4 (after 4.0.4 was released!!) with Fn support added to TWiki.pm. Currently it passes the same unit tests as
TWikiRelease04x00.
Timing tests
This is on an unloaded Debian testing box, using svn and a basically virginal install.
As can be seen, there is no difference in performance, which is what I expected.
--
MeredithLesly - 20 Jul 2006
Policy suggestions
Fns should follow the same policies as
PluginsApiPolicies, unless written by a core developer. The current TWikiVariables probably have to use core code because they, by and large,
are core code. There are almost certainly new functions that would be much slower if they didn't use core code. OTOH, that suggests something >:-)
Personally, I use contribs for almost all of my core stuff. If I need core stuff for a plugin that isn't in the areas described in the policies, I put the code in a contrib.
This may be an area to discuss regarding Best Plugin Coding Practices
--
Contributors: MeredithLesly,
CrawfordCurrie
Discussion
I have considerable concerns about the overloading of existing functions; for example, someone could write SEARCH.pm and overwrite the system version. However this is an ongoing risk with
any extension module, so i guess it's manageable.
--
CrawfordCurrie - 18 Jul 2006
An interesting wrinkle that just occurred to me is the possibility of using this approach to remove configuration conditionals from the code. For example, consider USERINFO. It has a conditional in it that rejects an attempt to get USERINFO for anyone other than the logged in user, if a flag is set in configure. Instead, configure could select between two alternate implementations of USERINFO, eliminating the condition from the running code.
--
CrawfordCurrie - 19 Jul 2006
Parked. Original developer has left the project. Anyone can pick it up. It is an ACCEPTED proposal.
--
KennethLavrsen - 25 Apr 2007