avoids compile-time dependencies on implementation bundles and keeps the cou-
pling between bundles much looser than it would be otherwise.
If you catch yourself exporting an implementation package from a bundle, stop
and think carefully. Why are you doing this, and is it the best way? Is your bundle gran-
ularity too fine? Could a service be used instead?
Structuring for flexibility
You already know that how you structure and scope your bundles has a big impact on
the modularity of your application. It's also important to realize that the structure of
your bundles affects how dynamic they can be as well. There are a few important
things to remember.
Separate interfaces from implementation
Not exporting implementation packages is important for modularity, but for dyna-
mism it's best if they aren't even in the same bundle as the interfaces. This is in fact
one of the most important things you can do to allow dynamism. But why?
Keeping API s separate from implementation matters more in an OSG i application
because OSG i makes it possible to add and remove things from a bundle's class space.
If your implementation is packaged in the same bundle as its API , then their lifecycles
are permanently tied together. If you had done this with your buggy persistence layer,
then, to replace the implementation, you'd also have to replace the API . After the old
API bundle has been replaced, any consumers of the API would need to be restarted
and refreshed to wire to the new copy of the API classes. Keeping API s separate gives
you much more flexibility to swap implementations in and out without affecting other
bundles in the runtime (see figure 5.6).
If you can't separate out your API
Sometimes, for perfectly good reasons, it's not possible to keep your API and implemen-
tation in separate bundles. Perhaps your architecture, or corporate policy, forces your
API to be colocated with your implementation classes. The best solution is to come up
with a more OSG i-friendly API , but often you have to play the cards you're dealt.
Figure 5.6 When the API for a service is separated from the client and implementations, then implemen-
tations can easily be switched. On the left you see the client using implementation 1. If you remove im-
plementation 1 from the system, then the client can switch to implementation 2 with no loss in function