The architecture of Eclipse and the structural concept of the underling OSGi framework are sometimes hard to combine with „effective Java“ programming as Joshua Bloch propagates it in his book „Effective Java„.
When you want to extend the functionality you must make certain compromises designing your API. This article describes how you can implement functionality with exposing a minimal API.
The extension mechanism of Eclipse works with reflection. Therefore the class of your implementation must be publicly accessible. Never the less it is probable, that your implementation contains methods that you don’t want to expose in a public API. Fortunately the Eclipse framework is richly „decorated“ with interfaces. For nearly any class you want to extend there is an interface and probably also some skeletal abstract implementation class. As an example for this
article let’s take the extension point ‚org.eclipse.ui.newWizards‘. Your implementation must implement org.eclipse.ui.INewWizard and extend org.eclipse.jface.wizard.Wizard.
The first step you take should be straight forward: Implement your wizard conforming to these conventions and test it. Then you generate a Façade class for your wizard, the implements the interface and extends the org.eclipse.jface.wizard.Wizard class. Make your wizard a component of this class as described in „Effective Java“ Item 16: Favour composition over inheritance. Then you delegate all the methods defined by the interface to your component. Also delegate all methods from org.eclipse.jface.wizard.Wizard that you have overridden to your wizard implementation. Change the the extension in your plugin.xml and you should be done.
If you have overridden protected methods of org.eclipse.jface.wizard.Wizard you cannot delegate their calls. Therefore you must create a private inner class that extends your wizard and makes this method accessible in your façade class. This is described in more detail in a seperate article.
What have we gained so far? We have another class that we must maintain. This was not the aim of our endeavour. But now that we have a public façade for the API we can hide the actual implementation. With Eclipse there are two possible ways:
- Make the class package private: this is the optimal solution. Should there be dependencies from outside the package, that cannot be satisfied through the façade class, you cannot take this step
- Move the class into another package. For this package you have two options. Don’t export the package – therefore the contents of the package is only accessible within the plugin. Or export the package with a restriction. For more detail on this option see this article.
So now lets have a final look. We have a public façade class in our API that defines the minimal set of access methods required. The contracts for these methods are defined and must be followed by your implementation. The implementation itself is hidden from the API but its capabilities are accessible within the plugin. Therefore we have reduced the defined API that you must maintain.