What kind of problems have you encountered when building plugin interfaces for your application? And how did you resolve them?
I want to refactor an application so that various features can be moved into plugins, allowing them to be easily added and removed in future.
I hope this will be a neater system than scattering
if (FeatureX_is_enabled) branches throughout the code. (I may be wrong!) I believe I will need to define interfaces for each part of the system into which a features may plug in.
I would like to benefit from your experience if you have already undertaken this kind of project. Perhaps you have endured mistaken designs, and can advise what not to do. Perhaps you can recommend patterns or architectures that can make such a system more manageable.
A few issues already spring to mind:
- I will need to provide some power to plugins so that they can get their job done. If I pass too little control, new plugins may be too restricted to do what they need (e.g. some Google Chrome extension authors complain about the inability to modify the core interface). However if I pass too much control, irresponsible plugins will have the power to break the whole application (e.g. Mozilla Firefox extensions).
- Some plugins may need to run in a different order on different events. I could register event handlers with a priority, e.g. 1-100, so that plugins can hook themselves into the appropriate order. Or I could just create
pre_events and hope nothing more finely grained is needed.
- If two plugins depend on another plugin to be available first then the plugin architecture will need some kind of dependency (and naming) system.
- Related, some plugins will need to know when other plugins are present, and perhaps even make calls into each other to handle edge cases.
- There may be difficulties maintaining the state of the application if plugins are enabled and disabled at runtime. (Chrome seems to handle this well, but many applications require a restart.)
- This kind of architecture will obfusticate the flow of execution (in exchange for keeping additional behaviour out of the core code). I will need to write neat interfaces so that unexpected behaviour is minimised.
- Sometimes the monolothic
if (FeatureX_is_enabled)approach might be a better way to handle the situation than breaking out to a plugin, but I don't know how to recognise such situations.
It is likely there are other concerns I have not considered, so I would love to hear what you have had to deal with!
Related question: How to turn on/off code modules?