Prevent leaking internals in API

I am looking for various ways to prevent internal components from entering the API. This is a huge problem because after these internal components leak into the API; you can run into either unexpected incompatibility issues or frozen internals.

One of the easiest ways to do this is to simply use the various Maven modules; one module with API and one module with implementation. Thus, it is not possible to implement the API implementation.

Unfortunately, not everyone agrees that this is the best approach; But are there any other alternatives? For example using checkstyle or other architecture checking tools?

PS: Java 9 is not used for us as we are going to migrate to Java 8 and this will be the lowest maintainable version for quite some time.

+3


source to share


4 answers


Following your checkstyle idea, it should be possible to set up rules that check the imports in the source files.

Checkstyle has built-in support for this, specifically IllegalImport and ImportControl .

This is of course best suited if public and internal classes can be easily separated by package names.



The idea IllegalImport

is that you are setting up the TreeWalker in a checkstyle that only looks at your API sources and excludes imports from internal packages.

With a rule ImportControl

, on the other hand, you can define very detailed access rules for an entire application / module in a separate XML file.

+1


source


It is standard in Java to define APIs using interfaces and implement them using classes. This way, you can change the "internals" but you want, and nothing will change for the users (users) of the API.



0


source


One option is to have one module (Jar file) for the API and implementation (but again, is this an API or just some library?). Within one, classes and interfaces are separated using packages, for example. com.acme.stuff.api

and com.acme.stuff.impl

. It is important to make the classes inside the last package protected

or just package-protected

. Not only does the package name tell the consuming developer "hey, this is the implementation", it is also impossible to use anything internally (let's just skip the reflections at this point for simplicity).

But again: this is contrary to the idea of ​​the API, because usually the implementation can be changed. With this approach, you cannot decouple the API from the implementation, since both are inside the same module.

If it is only about hiding the internal components of the library, then this is one (not one) valid approach.

And just in case you meant a library instead of an API that only exposes its "interface" (using interfaces or abstract classes, etc.), use different package names, for example. com.acme.stuff

and com.acme.stuff.internal

. Of course, the same rules of visibility.

Plus: this way you don't need Checkstyle and other burdens.

0


source


Here's a good start: http://wiki.netbeans.org/API_Design

Key Points: Don't expose more than you want . Obviously, the less the implementation is expressed in the API, the more flexibility is possible in the future. There are some tricks that can be used to hide the implementation while still delivering the desired functionality

I guess you don't need any control style or anything, good old solid design and architecture is enough. Polymorphism is all you need here.

One of the easiest ways to do this is to simply use different Maven modules; one module with API and one module with implementation. This path cannot be implemented from the API.

Yes, I totally agree, hide as much as possible, separate your interface in a standalone project.

0


source







All Articles