tags:

views:

68

answers:

2

I'm hard at work packaging up an API for public consumption. As such I'm trying to limit the methods that are exposed to only those that I wish to be public and supportable. Underneath this of course there are a multitude of limited access methods.

The trouble is that I have a lot of internal code that needs to access these restricted methods without making those methods public. This creates two issues:

  • I can't create interfaces to communicate between classes as this would make these my internal methods public.
  • I can't access protected or default methods unless I put the majority of my internal classes in the same package.

So, I have around 70 or 80 internal classes in cleanly segregated packages BUT with overly permissive access modifiers. Would you say that a single package is the lesser of two evils or is there a better way to be able to mask my internal methods whilst keeping more granular packages?

I'd be interested to find out the best practice here.

I'm already aware of This

+1  A: 

One example could be the Servlet API as you see they have separated common servlet API and http into two packages.

If you separate your code in an api.jar and implementation.jar you could use interfaces for your implementation which are not visible to the users of api.jar. If objects of classes regardless of their package, have to collaborate in any way, the methods of course must be visible (at least in the implementation).

stacker
+1  A: 

yeah, you just cannot protect internal implementation stuff from access. There are some technologies (like OSGi), which offer solution to that during runtime/application startup. This is a java language-design modularization flaw (but also very difficult to add afterwards due to down-compatibility).

I like the convention to add publicly visible artifacts to /api package and internals to /internal. In the end you end up with.


# this package is allowed to be accessed by api-users
com.foo.users.api
# this is completely internal logic (api implementation)
# should only be touched by the api-module itself.
com.foo.users.internal

This way you have clean separation and can also run static code analysis code-rules.

Like with servlet-api mentioned above you can even further split api vs. impl to different jars. But this involves more effort to build-lifecycle and maintaining modules, so I would only do it where a complete runtime artifact split make sense (like in jsr-spec vs. impl).

manuel aldana