The discussion has been summarized on a Wiki page:
Two separate approaches, dubbed 'Open bar' and 'Guided', are outlined
in the document.
At this point, the 'Guided' approach seems like a sensible choice. But
before moving forward, we'd like to have your input on this.
Could you guys please take a moment and let us know what you think?
Also, feel free to add to the wiki page if you have additional ideas.
I have two suggestions:
- Plugin install directory
I would prefer a "system wide" place for the plugins (in the application folder), since i often copy the whole
app dir to another box, most of the time without my profile in ~/.mucommander/. Maybe the two places can be
combined - first scan the applications plugins dir, then the users profile plugin dir.
Whats about a GUI for the configuration of plugins? A new tab in the preferences dialog would be the easiest
way, since all configuration related method (save/load) are located in the base class.
But i would like to sperarate the plugin configuration from the app configuration.
Mybe a new entry in the main menu bar (e.g. "Plugins") could contain the configuration dialogs. Plugins should
provide a configuration dialog extending the configuration base dialog.
Since not all plugins need to be configured, this class name should be optional in the MANIFEST.MF.
Currently there are 1000+ java files in /source.Plugin API would be something like 5-10, max 20 interfaces. I don't
think that such additional layer of tiny interfaces is really
complexity, and that this is hard to maintain...
BTW, you say that there is coming global refactoring (
com.mucommander.file -> com.mucommander.protocol )
We can make file-only PluginApi after that.
I have followed the discussion and given this more thought, and I have
to say Nicolas raised some very valid concerns about the 'Guided
The two following requirements render backwards compatibility
impossible to guarantee in practice, no matter what approach we choose:
A) the Plugin API has manipulate some of the core classes
(ProtocolProvider, AbstractFile, MuAction, ...) to harness the
existing APIs (file API, action API, ...).
B) we can't afford to freeze core API as they are not fully mature ;
we want to keep improving them over time, and muCommander to benefit
from those improvements.
=> that means whenever core APIs change (class renamed, package moved,
method deleted), plugins will fail to load.
I think there is no way around it, unless we have proxy classes and
methods for every single core class that we want to expose in the
Plugin API ... which would be a nightmare to develop and maintain, and
wouldn't completely shield us from changes in the underlying core APIs.
If backwards compatibility can't be guaranteed, then the main argument
in favor of the 'Guided approach' is gone. In that case, the 'simpler
is better' principle applies and we should go for the 'Open bar'
approach as it is easier for us to roll out.
With that being said, we should do our best to offer backwards
compatibility ('best effort' mode) :
- limit changes in the core APIs as much as possible
- favor class and method deprecation rather than plain removal
- consider sticking to the same core API versions between major
revisions. For instance, muCommander 0.9.1, 0.9.2, ... 0.9.x would all
use the same file / action / ... API versions. Note that we will have
to complete the extraction of core APIs first, see http://trac.mucommander.com/wiki/ApiSplitting
- Give proper guidelines to plugin developers, and list the APIs
that are safe to use (core APIs)
I think we're making good progress here. Feel free if you have more to
add, the discussion is still open.
As the work on 0.9.1 release is coming to an end, and we plan to defined the next release as a "community release" with plugin APIs as its major feature I would like to continue the discussion about plugin APIs. It's been a long time since this discussion took place and I hope the guys that participated in the discussion are still interesting in this feature. I've read the discussion on the mailing list and the wiki page that was created, and I think that it was a good discussion that can be a basis for further discussion.
I think that first we should define what is the goal of using plugin APIs, what do we expect to achieve by using plugin APIs. it seems to me that the discussion around this feature was mainly focused on backward compatibility, how to ensure that previously developed plugins will still work as we continue to develop muCommander. IMO, backward compatibility is something that we should think about, as we don't want to update the plugins on every release of course, but IMO there are more important things that plugins should provide to muCommander:
1. plugins should make it technically easier to extend the application
1.1 when someone wants to develop an extension he won't have to be exposed to all muCommander's code. he would need to know only the parts in the code that are required for implementing the extension.
1.2 it should be easier to set the development environment for plugins development as not all the settings and external dependencies are required
2. plugins should increase the level of participartion in the project - one of the major advantages of muCommander IMO is that it is written in Java which is a very popular language today, and there are many libraries which are developed in Java, so the potential for extensions by the comumnity is high (and the next release should address this in different areas as well - by using github/gerrit, having tutorial videos on youtube channel/on our website, etc)
2.1 plugins will provide a way to implement extensions without maintainers of muCommander being involved in the process, as the code doesn't need to be reviewed by maintainer since it is not going to be merged to muCommader's source control
2.2 as opposed to code that is integrated within mucommander's source control, plugins don't have to be open sourced
3. plugins will provide a way to add/replace implementations without recompile
3.1 new extensions can be downloaded and loaded into the application without recompile
3.2 built-in components can be replaced with other components
3.2.1 can be used to replace component with different implementation, for example users will be able to replace the rar files extension with other implementation that use different library than junrar
3.2.2 can be used to update libraries. today users need to wait for us to upgrade the external libraries we use, with plugins users will be able to replace plugin with an updated version as long as it is compatible with mucommander's extension protocol. users can sometimes even just update the jar of the external library if it is backward compatible.
4. the API splitting was a great design change in terms of modulatiry and reusability (I've encountered a project that use our commons-file package, I can't remember its name..). enhance the current design with plugins architecture will make our code more modular and if the extensions protocols will be independent enough, the plugins could serve other projects as well.
5. the size of mucommader's jar file increase as we add more external libraries and dependencies to the project. by using a plugins architecture, we can extract some components from mucommander's core and provide them as an optional (as opposed to integrated) plugins. for example, in 0.9.1 we are adding support for vSphere protocol which will probably not be used by the majority of our users, so we can implement it as a plugin that is not integrated in our release of muCommander, but could be downloaded separately.
Few more word regarding the backward compatibility issue: I think that Nicolas had a point with his arguments, and Maxence summerized it well - there won't be ideal solution that will ensure backward compatibility always. but I don't think that it's one of the important goals of plugin design though. it's important to have versions so that when we break the protocol/API between the core part and the plugins, plugins that don't conform the API won't be loaded. if we break such protocol/API, it's ok to expect plugin developers will update the plugins in order to conform the new API. plugin APIs should be relatively stable of course, and we should try to minimized the number of changes in them. if we add functionality to the API, we'll need to decide whether to support plugins that are not updated with default implementation for the added functionality, or reject plugins that do not provide the new funcionality.
Not everything should be developed as a plugin though. I think we should define things which are extensible and can be defined with a clear API for extensions, for example:
1. file systems - like ftp, smb, etc. we already got few contribution in that area, one of them is the vSphere support that was lately integrated - the plugins should provide a panel (for the server dialog) and support for the file operations (ls, copy, remove, etc)
2. compression protocols - like zip, rar, 7zip, etc. such plugins should provide support for packing, unpacking (in the future we can add passwords and so on)
3. desktop types
4. file viewers/editors - like text, image, pdf, etc (viewer/editor).
5. more general plugins that get the paths of the selected files and can operate on them, such plugins should be able to open a new dialog, add menu-item etc
6. TBD ..
This post is already long so I'll cut it here, and I'll wait for your feedback about what has been written so far.
You are more than welcome to share you thoughts and insights.
Next I'll describe what I had on mind regarding the design of the plugin APIs and about OSGI which I checked not very long ago to serve as a basis for our plugin architecture.