Why isolation is important to sharing
An old adage in computing says “All you need to solve any problem is another layer of
abstraction.” The grain of truth behind this saying is that problems often become
much more tractable if the gory details are hidden away so that you can deal with a set
of simple base cases instead. This fact applies generally across software, and most
applications make use of frameworks or other services that deal in these abstractions.
INVASION OF PRIVACY
One of the most important things about levels of abstraction is that the underlying
details don't bleed through, breaking the abstraction. In Java code this is typically
accomplished through interfaces, factories, and changeable implementations. Unfor-
tunately for Java, there's little to prevent someone bypassing your API and starting to
work directly with the underlying implementation classes. Clearly this is a gross viola-
tion of the abstraction, but what if there's a method on the implementation object,
but not on the interface, that does exactly what you want, what you need ? Aren't you
tempted? Most people are; after all, expediency is what gets projects delivered on
The previous paragraph is clearly a bad idea, and yet so many of us are guilty of
doing it. When people start casting objects to specific implementation types, the API
becomes brittle. Any change to private content risks breaking clients, even though it's
not supposed to. Even without change, casting to implementation types is a risky busi-
ness. What if the internal documentation says you're supposed to synchronize on a
particular object in a lock hierarchy before calling it to avoid a potential deadlock?
KEEPING YOUR BUNDLES MODEST
Given that we'll never stop being tempted to make use of implementation specifics for
expediency, sacrificing long-term benefit for a quick win despite the cost, developers
won't stop doing it. The only way to stop this sort of hack from happening is to make
the hack less convenient than doing things properly. Fortunately, this is easy to accom-
plish in OSG i; if an implementation isn't part of your API , then don't export it. There's
no reason to expose the implementation type to other bundles. If other bundles can't
see your implementation type, it's impossible for them to cast to it, and it takes a dirty
hack for reflection to look like a good idea! When in doubt, cover up.
If your bundles do meet Victorian standards of decency, then how do they commu-
nicate? Bundle A may contain an implementation of an interface, but it's not much
use unless you can get it in to Bundle B somehow, and if you can't cast to a type you
certainly can't instantiate it...
The answer is to use the OSG i Service Registry.
EXPOSE SERVICES, NOT IMPLEMENTATIONS
As we've already mentioned, a great way of ensuring that bundles neither import nor
export too many packages is to never export implementation classes. This also pre-
vents people from violating any abstractions you've made, or doing things that are
plain wrong. Using services isn't just good for keeping manifest sizes down. It entirely
Search WWH ::