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.
source to share
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.
source to share
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.
source to share
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.
source to share