EMF has a plug-in versioning problem,
and I'm looking for some input (especially from those who depend on us)
on how we should go about solving it.
We're striving to correctly follow the
plug-in versioning guidelines (http://wiki.eclipse.org/index.php/Version_Numbering),
which contains this statement:
"Plug-ins re-exporting other plug-ins
tie themselves to the re-exported plug-ins, since they are making the re-exported
plug-ins part of their API. Therefore, the version of such plug-ins must
indicate the most significant type of change between all the plug-ins they
re-export and the changes made locally."
EMF re-exports plug-ins extensively.
This was a decision made many years ago, when we really didn't understand
what its consequences would be. As a result, depending on just about
any plug-in in EMF automatically pulls in the APIs from just about every
other plug-in that it depends on. Today, it seems the accepted wisdom
is, "don't do that!", but unfortunately we've already done it.
The first change I made in our current
development stream was to add a method to an API in org.eclipse.emf.common.
Endeavoring to follow the rule, I mapped out the tree of EMF plug-ins
that reexport that plug-in. This is just like the tree you'd see
when you click "Show Callers" in the Plug-in Dependencies view,
except it only includes dependencies that re-export. Rather than
waste 234 lines to reproduce it in all its glory, I'll just say that it
includes almost every last plug-in in EMF. Trying to propagate version
changes through these huge trees of re-exporting dependencies in EMF would
be difficult to manage and prone to introducing error.
Moreover, I believe the results would
differ only marginally from treating all of EMF as a single monolithic
unit, and simply incrementing all of our plug-ins' versions in step each
cycle. And that was precisely the practice that these versioning
guidelines were intended to put an end to.
So just following the rules doesn't
seem to be a reasonable solution.
After giving it some thought, the EMF
team was able to come up with two other possibilities:
1. Remove our re-exports
We could improve the situation simply
by removing all the unnecessary re-exports in our plug-ins. We would
have to change our own plug-ins to explicitly require all of their dependencies,
which of course wouldn't be a problem. The problem is that this would be
a breaking change, probably for almost all of our clients. The fix
would be trivial: just use the excellent PDE tools to explicitly add missing
dependencies. But is that something that people would find overly
disruptive?
This should probably be considered a
change of API, so we would have to increment the major version numbers
of all affected plug-ins. But, we're planning such a version change
anyway, when we build our plug-ins to target Java 5. So, this would
seem an ideal opportunity to make this kind of change, leaving us in a
good position to do versioning correctly in the future. This is our
preference.
2. Ignore the rule and treat re-exported
plug-ins independently
We could pretend that we never started
re-exporting plug-ins in the first place, and just increment plug-in versions
based only on their own changes. This would save those who aren't
concerned interested in strict per-plug-in versioning from facing newly
broken dependencies, and would still communicate something useful, but
would not respect the expectations of those who are relying on strict plug-in
versioning.
One idea we came up with was a new feature
for Equinox: if a new directive could be recognized on Require-Bundle to
mean "ignore any of this dependency's re-exports", then we could
provide proper plug-in versioning (by not considering re-exported plug-ins)
for those who choose to "opt in" by using this directive when
they depend on our plug-ins. Alternatively, it could just be a development-time
feature in the Plug-in Manifest Editor. By enabling it, re-exported
plug-ins would be ignored, and people could use the tool to add all their
dependencies as explicitly required.
This seems like something that could
be generally applicable in situations like ours, where re-exports have
been used in the past, resulting in a non-modular set of plug-ins. However,
if this isn't a widely shared problem, or if this idea is viewed as just
adding more complexity, then that would seem to support option 1 as the
best way to go.
Any input would be greatly appreciated.
Cheers,
Dave
--
Dave Steinberg
Rational Software - IBM Toronto Lab
mailto:davidms@xxxxxxxxxx