Your 100% right it's the OSGi environment that enforces the exported
packages and hiding the rest. So I concur with your 3 points at the end.
Sent from my iPhone
On Jan 6, 2011, at 5:21 PM, Stefan Seelmann <[email protected]>
wrote:
On Thu, Jan 6, 2011 at 2:58 PM, Alex Karasulu <[email protected]>
wrote:
In the end, dependency upon further transitive dependencies are
making us
expose almost all implementation classes in shared, and most can
easily be
decoupled and hidden. It's effectively making everything in
shared come
together in one big heap exposing way more than we want to.
It's quite impossible in Java to 'hide' all the classes that a
user should
not manipulate. Unless you use package protected classes, and it
quickly has
a limit, I would rather think in term of 'exposed' (ie documented)
API.
OSGi bundles really helps in this respect. It fills in where Java
left off.
OSGi makes it so the (bundle) packaging coincides with module
boundaries. In
Java this is loose and there's leakage all over, as you say, it's
very hard
to hide all implementation classes.
That this documented API is gathered in one separate module for
convenience
is another aspect, but the user will still have to depend on all
the other
modules.
Certainly, you're right, dependencies will still exist. A codec
will be
depended upon for it's functionality even if we do hide the
implementation
details under the hood.
The value add here is not from avoiding a dependency. It's from not
exposing
more than we have to and being able to hide the implementation.
This way we
can change the implementation at will across point releases without
having
to bump up to a major revision.
So all in all, should we define a module (a maven module)
containing the
public API and the associated implementation ? Probably (But this
is not an
absolute necessity). I guess this is what you have in mind, so
let's see
what's the proposal is...
We have multiple options for chopping this up. With bundles we have
a nice
tool to carve out physical not just logical boundaries to our API's
and only
expose those packages we need to show API users.
LDAP Client API
------------------------
Everyone agrees that this API is very important to get right with
a 1.0.
Right now this API pulls in several public interfaces directly from
shared.
Those interfaces also pull in some implementation classes. The
logical API
extends into shared this way. Effectively the majority of shared is
exposed
by the client API. The client API does not end at it's jar
boundary.
All this exposure increases the chances of API change when all
implementation details are wide open and part of the client API.
And this
is what I'm trying to limit. There are ways we can decouple these
dependencies very nicely with a mixed bag of refactoring
techniques while
breaking up shared-ldap into lesser more coherent modules. The
idea is to
expose the bare minimum of only what we need to expose. Yes the
shared
code
has become very stable over time but the most stability is in the
interfaces
and if we only expose these instead of implementation classes
then we'll
have an awesome API that may remain 1.X for a while and not require
deprecations as new functionality is introduced.
How will you limit the visibility of the modules you don't want
the user to
be exposed to ?
A combination of refactoring techniques will be used to be able to
better
use standard Java protection mechanisms to hide implementation
details
combined with using OSGi bundles instead of Jars to only export those
packages that we do want users to see.
Alex, I agree with you that separating interfaces and implemenation
details is a good thing. Also creating OSGi bundles with a minimal set
exported packages is a good thing. But it only helps if the bundles
are used in an OSGI environment.
I think we'll continue to deploy those OSGi bundles (which are just
Jars with a good META-INF/MANIFEST.MF) to maven central. And each user
using those Jars will see and can use all classes, when not using an
OSGI environment.
So I think we need additional techniques for non-OSGi users to let
them know which packages to use, for example:
- Use a naming convention for internal packages, the name "internal"
is used in Eclipse and Apache Felix, not sure if is specified in OSGi.
- Create separate Jars for API and implementation (e.g. xyz-api.jar
and xyz-impl.jar)
Kind Regards,
Stefan