Feature Proposal: Fine-granular control over supported features
Motivation
To have a flexible way to provide and check information about features
supported by the core or other components.
Description and Documentation
Usually software compatibility is checked by testing against versions. If we speak of extensions
it means that we usually know that an extension was designed for a core version X.Y and wont work
on lower versions because they lack of a required feature. It doesn't really matter what exactly
the term 'feature' means in this context: either it's an API, certain behaviour, or anything else
of the kind. All we need to know is if the feature is there to provide the extension with
required functionality or data.
But knowing the minimal required version is not sufficient too. Consider an abandoned extension
which would work as long as certain core functionality is in place. How do we know that the
extension's life cycle is over? Remember that we may speak of tens or even hundreds of them out there.
Closely following each one wouldn't be possible. Neither is possible to know what exact functionality
is required unless the author has documented it.
How it works.
Let's start with an example. The example assumes that feature set support was implemented for
Foswiki 2.x (hypothetically, of course).
package Foswiki;
...
use Foswiki::FeatureSet;
...
# Declare FEATURE => [ versionStarted, versionDeprecated, versionDropped, %options ] pairs.
features_provided
TWIKI_COMPATIBILITY => [ undef, 2.99, 3.0 ],
PARA_INDENT => [ undef, undef, undef,
-desc => "Paragraph indentation", ],
MOO => [ 2.99, undef, undef,
-desc => "OO with Moo",
-proposal => 'Development.ImproveOOModel',
-doc => 'Documentation.Foswiki3CodingStyle', ],
EXTENSIONS_1 => [ undef, undef, 2.99,
-desc => "Old-style plguins and contribs", ],
EXTENSIONS_1_3 => [ 2.99, 2.99, 4.0,
-desc => "Old-style plguins and contribs adapted for Foswiki 3.0", ],
EXTENSIONS_3 => [ 2.99, undef, undef,
-desc => "New and powerful OO extensions",
-doc => 'Foswiki::Extensions' ],
;
In this example we see that
TWIKI_COMPATIBILITY
feature (
TWikiCompatibilityPlugin) was there since
the beginning of time (true, isn't it?). But is deprecated since 2.99 and won't exist in 3.0.
For old-style extensions (
EXTENSIONS_1
) the situation is a bit more complicated because they won't work in their
old format (with
$Foswiki::Plugins::SESSION
variable and
$object->{attribute}
style of
accessing object's data). Thus this feature is just dropped in 2.99 but
EXTENSIONS_1_3
is introduced
instead which is deprecated since it's introduced in 2.99 and will be dropped in 4.0. (I hope nobody
would take this seriously as I'm alone do not define lifespan of a feature.)
For the feature set defined above an extension could use the following statement to define
what it needs:
our @requiredFeatures = qw(MOO EXTENSIONS_1_3);
The core would match these features against its version and in this way determine if the extension
could be used or shall be disabled. The compatibility table then would look like this:
Context
Features active for the current core version would be included into the
application context. To be distinguished from other contexts their names
will be completed with
SUPPORTS_
prefix. Note the
PARA_IDENT
feature
above – its context name would then become
SUPPORTS_PARA_INDENT
which
currently exists and is being used in Foswiki code.
NOTE At some point access to the contexts would be provided to the front
end
JavaScript. I expect it to open a couple of new possibilities for
future user experience.
Namespaces
Not only the core may need the feature sets. Other extensions or frameworks
could use it to improve their interoperability with other Foswiki components.
To make this kind of interaction easier and to avoid same feature names
from different components to clash with each other the concept of namespaces
is provided.
Consider the example:
features_provided -namespace => 'Foswiki::Extension::EmptyExtenion',
MY_FEATURE1 => [ undef, 0.8, 1.0 ],
MY_FEATURE2 => [ 0.3, undef, undef ],
;
In this code an extension declares features it provides in terms of the
extension's module version, not core's.
A namespaced feature does appear in the application context too but its
name has
<namespace>::
prefix. In the example above the context
name will be
Foswiki::Extension::EmptyExtenion::SUPPORTS_MY_FEATURE1
.
Yes, it does look terribly long. But namespaces are not limited to any
particular format and it may be agreed that:
-
Foswiki::
part could be avoided whatsoever as practically every component has it.
- Extensions can use only their plain name skipping the
Extension::
part too as long the name ends in 'Extension' suffix. Otherwise the full Extension::
form could be replaced with shorter Ext::
variant. For example: Ext::YAMLConfig
for Foswiki::Extension::YAMLConfig
.
NOTE The core features are in fact registered in the
CORE
namespace.
Naming conventions.
Though all feature names here are in all-caps format this is not mandatory.
Actually, a feature could be any sequence of symbols except for the following
rather clear rules:
- Throughout this proposal options are defined using -option notation. This is to distinguish them from feature names and to simplify some API calls allowing to mix up options with features. Of course this imposes a ban on dash-prefixed feature names. But I guess this won't be a big deal.
- Similar implication has use of double colon for namespaces in context names. Though this time it also implies that there will be no contexts containing a
m/[\w]::SUPPORTS_/
sequence. Despite very low possibility of such context would ever exists I would suggest prohibiting use of the double colons for context names whatsoever.
A component lifespan effect
Due to better granularity of defining compatibility comparing to simple version
match certain future components could survive major overhauls of core code simply
because they would depend on few rather stable features. Without it the risk of
declaring them non-compatible is rather high.
On the other hand, scanning for incompatible components will be as simple as
possible as long as features declared by core are kept tidy and actual.
Impact
Implementation
This functionality is currently in development in the
Item13897 branch. The
first commit is expected in 2-3 days from publishing this proposal.
Could be backported to 2.x branch.
--
Contributors: VadimBelman - 16 Nov 2016
Discussion
This is my last proposal
(Promise! I really do!) before dedicating myself to completing and polishing the future 3.0. Together with the new extensions this would be something we can provide for developers to do really fantastic things to Foswiki. Unfortunately, my other vision of redesigned
Foswiki::Meta
left outboard and won't be part of the (hopefully) forthcoming release. On the other hand a curious developer can take care of it by implementing a corresponding extension.
As it is clear from the text the main focus is kept on handling the new extensions. But the use could span beyond this particular case and everything depends on developers' fantasy. I currently would expect skins utilize features to turn on/off certain blocks depending on whether or not there is support for these block on core's or extensions' side. Think of it as of a possibility to have version independent skin which could provide extended functionality without the penalty of incompatibility with other Foswiki or extension versions.
I'm all eyes and ears now.
--
VadimBelman - 16 Nov 2016
Abandoned
--
MichaelDaum - 14 Oct 2024