I keep getting questions on the reasons for deprecation of certain functions in the plugins API, from people who weren't involved in TWiki development at the time. There isn't a natural place in the release doc for describing this, so I thought I would write a supplemental doc that explained the reasoning.
Remember, "deprecated" means that a function will be supported for some considerable time to come. It is therefore important to deprecate functions
as early as possible, because they will constrain improvements in the core for a long time. If they are not deprecated developers are also likely to utilise them, making eventual deprecation that much more difficult.
Note that most of these deprecations were only necessary because the API functions were, I think, introduced as a "quick fix" to the API. This illustrates how dangerous it is to allow a single plugin to dictate how the API evolves. The new approach is to allow new functionality to develop within Contribs (such as the
FuncUsersContrib), which allows time for new functionality to mature before it gets cast in stone. Hopefully this will avoid the need for wholesale deprecation in the future.
TWiki::Func functions
formatGmTime
Special case of
formatTime. Replaced by the more generic function.
getScriptUrlPath
Returned a relative path to a TWiki script. No apparent reason for using it. Did not support URL parameters. Was not matched by equivalent pub URL method. Very uncommon in plugins.
getPublicWebList
A special case of
getListOfWebs. Replaced by the more generic function.
getDataDir,
getPubDir
Assumes a directory structure for the database. As such, it encourages plugin developers to think of topics as files on disc. Fundamentally violates store encapsulation.
No direct equivalent; replaced by enhanced functions for handling topics and attachments within the DB.
checkDependencies
BuildContrib supports definition of DEPENDENCIES that can be statically evaluated at install time instead, which is significantly more efficient.
Handlers
startRenderingHandler,
endRenderingHandler
The
startRenderingHandler would deliver the topic text with <verbatim> blocks removed to the plugin. If a plugin needed access to other topic content, such as the contents of verbatim blocks, or meta-data, it had no choice but to re-read and re-parse the topic. This was the case in several plugins. Impossible to fix without changing the semantics of this handler, so
preRenderingHandler and
postRenderingHandler were introduced. These correctly handle verbatim and other TWiki ML block types, and give the handler access to the whole topic content.
outsidePreHandler,
insidePreHandler
These handlers were called on a line-by-line basis during
TML rendering. As such they:
- Assumed and required detailed knowledge of the internals of the rendering loop,
- Are a fundamental block to optimisation of the rendering,
- Lost all context information between each call, requiring delicate maintenance of context through global variables.
They were therefore deprecated in favour of
preRenderingHandler and
postRenderingHandler.
writeHeaderHandler
Deprecated in favour of
modifyHeaderHandler, which is a lot more flexible, as it allows you to modify existing headers as well as add new ones. The new handler also works correctly when multiple plugins want to modify headers.
What I should have deprecated (with reasons), but didn't
earlyInitPlugin,
initializeUserHandler
A fundamentally flawed quick hack put in for
SessionPlugin, now redundant and IMHO utterly confusing. User management should
not be done via plugins; there is a steadily improving architecture for it in TWiki::Users.
readFile,
saveFile
These functions encourage the view of the TWiki database as a file system. While this is the case in fact, it is
not an architectural assumption - TWiki can equally use a relational databse or other store implementation.
getTopicEditLock,
setTopicEditLock
Send completely the wrong message to the plugin author about how locks are handled.
readTopicText,
saveTopicText
Assume that %META is embedded in the topic text, which exports the implementation details of the Store. Lock down the format of embedded META or, if it changes, require a massive effort to map new to old just for these functions.
redirectCgiQuery
Produces a 302 directly. Fine if you are the only plugin in the world, otherwise dodgy as hell, because there is no guarantee that your redirect won't be overridden by another plugin. Should be handled through exceptions.
internalLink
Again exposing the internals of the renderer to the plugin author in a horrible way.
In general, link format handling needs much more careful thought, and probably should be done via listeners (or handlers as they are known in TWiki)
--
CrawfordCurrie - 13 Jun 2006