How to deal with dependencies between plugins?
Martin Klapetek
martin.klapetek at gmail.com
Mon Jun 25 12:12:21 UTC 2012
On Sun, Jun 24, 2012 at 5:12 PM, Lasath Fernando <kde at lasath.org> wrote:
> Hey
>
> Okay, this email may *feel* like a wall of text, but if you bear with
> me for a moment, you'll see that it's actually filled with legitimate
> questions.
>
> I started discussing this problem with a friend of mine (CC'ed)
> because he was bored at the time, and these are the issues we came up
> with. I want to start implementing a solution next Wednesday, so I
> would appreciate it if you guys can give your suggestions/solutions
> sooner rather than later.
>
> I outlined a part of the problem of dependencies between plugins in a
> comment on reviewboard.
> But to those who didn't read it, but would like to contribute wisdom
> anyway, the brief rundown is :
> We need to account for a few things. We need a way of identifying the
> dependancies of a plugin, and we need a way of handling the situation
> where they aren't found. We also need to account for the user
> enabling/disabling them. We also need to be able to control the order
> in which they are run.
>
> First of all, filters parse messages, and modify/add parts to the
> message. But they also store metatdata for other plugins to use in the
> form of properties. For example, the UrlFilter adds <a> tags to make
> links clickable, but it also dumps all the urls found as a property so
> that all other plugins don't have to parse it. ImageFilter (which
> embeds links to images directly in the chat) uses that.
>
> So, when I say B depends on A, I mean a situation like that.
>
>
> First scenario. Plugin B requires plugin A, but A is not present.
> (I.e. KPluginLoader failed to load it).
> Should it silently fail, or give a message to the user informing that
> B has failed becuase A is missing?
>
Failing silently (in the frontend) is almost never good, because the user
expects something and nothing happens, so that's bad.
> Should it then disable it forever, or keep trying in case A comes back
> in future messages?
>
I'd say inform once and keep trying, but don't put it in user's face
everytime it fails (until it works again). This might be too complex to
implement/handle, so disabling forever might be probably better.
> Second case: B requires A but A is disabled.
> Should this be dealt with at runtime, or while the user is
> enabling/disabling plugins?
>
Config time, definitely.
>
> Doing it at configure time will mean that all relationships between
> plugins will need to be explicitly stated in their service files. This
> will of course mean more work to verify everything in the KCM, and an
> extra chance of human error. (Screwing something up in a service
> file).
>
I think the same system exists and is used by KWin plugins system, ie. if
there's a dependency, it offers you to enable the other plugin.
> So, if the KCM does work this out, how should it behave. Should it:
> * not let B be enabled (i.e box greyed out until A is enabled)?
> * give a dialog box asking to enable A when the user ticks the box for B?
>
^ This. State that the plugin needs another plugin and offer a button to
enable it right away. Think of multiple dependencies as well - if one
plugin requires two plugins, it should show only one dialog imho. However
for this you'd need some graph theory or whatever is used for the
dependency solving, because you need to resolve /all/ the dependencies at
once (eg. A depends on B, which depends on C and D and D depends on E).
> * silently enable A when B is enabled?
> * automatically enable A when B is enabled but inform the user (with a
> KMessageWidget or something) with a button to undo?
> And vice versa if the user tries to disable A while B is enabled.
>
> However, doing it at runtime might be considered a fail on our part by
> users.
> This will essentially give us the same issues as the first scenario,
> so there's no point in stating them twice.
>
>
> The order that things should run was much more complicated to think
> about. While with a dependancy, it's clear that A has to run before B.
> Other things, are not so explicit. For example, EscapeFilter should
> always run first and we need a way of declaring that.
> Other things are even more fuzzy, like for example, should the
> 'Replace Words' filter run before or after the 'Translate' filter?
>
For this I guess you simply have to decide it yourself and see how it
works. Some priorities system, perhaps. Plugins are then ordered by the
priority.
>
> We're pretty much at a dead loss for this part.
>
> We also discussed, for actually solving this thing, whether
> dependancies should be declared implicitly or explicitly.
> Explicitly:
> In the service file, we write that B requries A. This would mean
> the MessageProcessor/KCM would know to enable and load A before B.
> That would mean though, that plugins depend on each other by name. It
> would also mean an extra chance to screw things up - i.e misspelling a
> dependent plugin name and stopping it from loading.
> Implicitly:
> Because the only way for plugins to interact with each other is
> through properties (which means only one getter and setter), a
> selected list of plugins can be run and rearranged dynamically to the
> required order. This would provide the advantage that if two plugins
> provide the same metadata and the user has either enabled, it'll work.
> It will also mean there's no chance for us to screw things up by
> making mistakes in the service files, as everything would be
> determined automatically.
>
You do the mistake just once and it's easy to fix. Also if you're careful
enough, you should be just fine. Check out the stuff Dave posted before me.
--
Martin Klapetek | KDE Developer
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.kde.org/pipermail/kde-telepathy/attachments/20120625/155f9d41/attachment.html>
More information about the KDE-Telepathy
mailing list