Selective API Javadocs - java

I have what must surely be a fairly common documentation need...
I'm implementing a rather sizable Java library code base that has, among other things, various classes intended to be exposed to a caller/implementor at the appropriate level of abstraction. At the same time, the code base contains, of course, various internal classes, interfaces, and other abstractions that the user of the library doesn't need to know about in order to use the API.
Lots of other API libraries out there make the mistake of simply throwing everything into the Javadocs, and leaving it up to the user to figure out which objects and entities they actually need to deal with as a caller through some combination of guesswork, inference, and, if you're lucky, example code.
I don't want to be in that same position. I would like to have an "internal" set of Javadocs that expose the entire extent of the codebase, and an "external" set of Javadocs intended to clearly communicate to the developers the characteristics of the classes that they actually need to use to get their work done. I don't need or want to muddy the waters with various internal abstractions that they don't need to see or know about - there's no need for them to know how it all works under the hood, and it would just confuse and misdirect them, making for a very inefficient API learning process.
How can I accomplish this? Is there a well-known combination of arguments to 'javadoc' and perhaps some annotations that can make this happen?
Thanks very much for your consideration!

Assuming that you have followed best-practice and put your internal classes in different packages to your public APIs, you can run javadoc with the public API package names as command line arguments.
Refer to the javadoc command line synopsis for more details.
(If you haven't organized your packages to keep internal classes out of API packages, you may be in for a bit of pain ...)

In addition to Stephen C's answer and using the javadoc tool, you can specify exactly which packages appear in the javadoc (hence Stephen C's comment about 'pain' if they aren't organised logically) using something like this:
Say you have 5 classes and you want only the classes in the org.notprivate package to appear in the Javadoc:
org.notprivate.Foo
org.notprivate.Bar
org.notprivate.Stuff
org.notpublic.Things
org.notpublic.More
You can use something like:
javadoc -d target/api -source 1.6 -sourcepath src/main/java org.notprivate
That's just a quick example, if you need to specify each class you'll need to look at the link Stephen C provided in more detail
Posted here for clarity:
Javadoc Documentation

I would like to have ... an "external" set of Javadocs intended to clearly communicate to the developers the characteristics of the classes that they actually need to use to get their work done. I don't need or want to muddy the waters with various internal abstractions that they don't need to see or know about - there's no need for them to know how it all works under the hood, and it would just confuse and misdirect them, making for a very inefficient API learning process.
Given this desire, perhaps Javadoc isn't the best method of documenting the overall system view or for giving a "here's what you need to know"-type info to new developers?
I would recommend supplementing your Javadoc files with a separate guide/document/wiki/something to give the meta-view.

You can use some extra arguments when invoking the javadoc tool :
-public : Shows only public classes and members.
-protected : Shows only protected and public classes and members. This is the default.
-package : Shows only package, protected, and public classes and members.
-private : Shows all classes and members.
So, with these options you can generate a full documentation for internal usage, and give a 'light' documentation with only the public interface to your customers.
If you're using Eclipse, the Javadoc wizard shows radio buttons to help you choose the documentation level - which is "public fields only" by default.

Related

Find out used classes and methods from Java source code

For Java source files, I would like to find out:
Which classes use which other classes (fully qualified names)?
Which methods call which other methods (fully qualified names)?
What would be a reasonable way to achieve that?
EDIT:
To clarify: I want a list of source code files as input. The output should be (as specified above) which class uses which other class and which method calls which other method. I do not want to inspect other loaded classes at runtime, like when using reflection.
You need to use static analysis tool as STAN standalone mode:
The standalone application is targeted to architects and project managers who are typically not using the IDE.
Or JArchitect (available also using command line)
JArchitect is a powerful tool for static code analysis. It can provide a lot of insight into complex code bases. Using custom code queries you are able to build your own rule sets in a very comfortable way.
In the Class Browser right-click menu, JArchitect proposes to explore the graph of dependencies between members (methods + fields) of a type.
Another option is SourceTrail
The graph visualization provides a quick overview of any class, method, field, etc., of interest and all its relations. The graph is fully interactive. Use it to move through the codebase by focusing on related nodes and edges.
(source: sourcetrail.com)
Unfortunately, reflection doesn't give you all the information you need to do this.
I've done it with ASM (https://asm.ow2.io/).
It provides the ability to walk the byte code of all of your classes using the visitor pattern, including the actual method implementations, from which you can extract the references to other classes.
I'm sorry that I cannot provide the implementation, because it's proprietary.
Note that this works from your .jar files, not your sources. If you really need to work from sources, then have a look at https://github.com/javaparser . Really, though, it's better to use the byte code, since the java language changes frequently, while the byte code specification does not.
I am not sure how to get a listing, but for identifying refactoring opportunities, you might try IntelliJ IDEA. It will dull out the signature line of any methods that are not accessed in the project. It will also detect code segments that are repeated elsewhere in the project, so you can extract common code.

Prevent Internals leaking into API

I'm looking for different ways to prevent internals leaking into an API. This is a huge problem because once these internals leak into the API; you can run either into unexpected incompatibility issues or into frozen internals.
One of the simplest ways to do so is just make use of different Maven modules; one module with API and one module with implementation. This way it is impossible to expose the implementation from the API.
Unfortunately not everyone agrees this is the best approach; But are there other alternatives? E.g using checkstyle or other 'architecture checking' tools?
PS: Java 9 for us is not usable, since we are about to upgrade to Java 8 and this will be the lowest supporting version for quite some time to come.
Following your checkstyle idea, it should be possible to set up rules which examine import statements in source files.
Checkstyle has built-in support for that, specifically the IllegalImport and ImportControl rules.
This of course works best if public and internal classes can be easily separated by package names.
The idea for IllegalImport would be that you configure a TreeWalker in checkstyle which only looks at your API-sources, and which excludes imports from internal packages.
With the ImportControl rule on the other hand you can define very detailed access rules for the whole application/module in a separate XML file.
It is standard in Java to define an API using interfaces and implement them using classes. That way you can change the "internals" however you want and nothing changes for the user(s) of the API.
One alternative is to have one module (Jar file) for API and implementation (but then again, is it an API or just any kind of library?). Inside one separates classes and interfaces by using packages, e.g. com.acme.stuff.api and com.acme.stuff.impl. It is important to make classes inside the latter package protected or just package-protected.
Not only does the package name show the consuming developer "hey, this is the implementation", it is also not possible to use anything inside (let's omit reflections at this point for the sake of simplicity).
But again: This is against the idea of an API, because usually the implementation can be changed. With this approach one cannot separate API from implementation, because both are inside the same module.
If it is only about hiding internals of a library, then this is one (not the one) feasible approach.
And just in case you meant a library instead of an API, which only exposes its "frontend" (by using interfaces or abstract classes and such), use different package names, e.g. com.acme.stuff and com.acme.stuff.internal. The same visibility rules apply of course.
Also: This way one does not need Checkstyle and other burdens.
Here is a good start : http://wiki.netbeans.org/API_Design
Key point : Do not expose more than you want Obviously the less of the implementation is expressed in the API, the more flexibility one can have in future. There are some tricks that one can use to hide the implementation, but still deliver the desired functionality
I think you don't need any checkstyle or anything like that, just a good old solid design and architecture should be enough. Polymorphism is all you need here.
One of the simplest ways to do so is just make use of different Maven
modules; one module with API and one module with implementation. This
way it is impossible to expose the implementation from the API.
Yes, I totally agree, hide as much as possible, separate your interface in a standalone project.

How do I stop javadoc from generating documentation for super classes?

Context: NetBeans 8.0.2, Java 8.0.0
I have written a couple of classes to encapsulate dialogs to assist my students in writing simple, visual applications without a sophisticated knowledge of GUI programming - Tic-Tac-Toe, for example. Unfortunately I made some of the classes extend JFrame, and now my javadoc is littered with long lists of features inherited from the class hierarchy, making it look kind of intimidating.
I know I can reformulate my implementation strategy to "use" a JFrame rather than to "be" a JFrame, but is there some simpler way to tell javadoc just not to generate documentation based on the class hierarchy?
Thanks.
Edit :
I am using the NetBeans generator out-of-the-box, with these additional options:
-stylesheetfile C:\Users\jack\Documents\NetBeansProjects\CartesianPlane/src/customStylesheet.css -overview "C:\Users\jack\Documents\NetBeansProjects\CartesianPlane/src/Overview.html" -subpackages edu.pcwe.uw.javaintro.cartesian_plane -exclude edu.pcwe.uw.javaintro.cartesian_plane.test
This question is already listed in the Javadoc FAQ
A16. How can I exclude or skip certain public members or classes
from being documented?
[...] There is currently no Javadoc option to hide, exclude or
suppress public members from the javadoc-generated documentation.
Since it is automatically generated, and you have no option to exclude, you have to deal with it.
There is an issue scheduled for version 9 where an exclude tag is requested.
You might want to read the entire request as it offer workaround for some exclusion, but I'm not sure it would work for your case.
Edit :
The yDoc (now renamed yWorks as per your comment) doclet mentionned in the request I linked offer the possibility to do some exclusion using y.exclude.
Note that you will have to specify y.exclude on your super class. Since JFrame is part of the standard JDK, you won't be able to specify it. Unless you want to recompile it, for sure but it is good to know that you have a workaround to do it for your own classes.

Can I set up custom warnings in NetBeans

So, I may sound crazy when I say that I want more warnings in my Java code, but hear me out. I'm transitioning to better coding practices, and want the IDE to help. In my older days, I made a library in packages like bht.tools, but now am moving to org.bh.tools. To do this, I'm moving the classes slowly and one-by-one, so that I can also go over their code to make sure best practices are being used there too. This has the added benefit of knowing that any class I import from the new packages has recently been reviewed to be more robust and efficient.
In short, I want NetBeans to show a warning wherever I'm using bht., whether it be in imports, fully-qualified names, etc.. Is this possible?
Yes, you can use the Netbeans Java Hint Module. There is a nice tutorial here.
You probably need do define a TriggerPattern:
Find parts of the source code that satisfy the given pattern, and invoke the method that is annotated with this annotation. The method must be public static, the return type must either be assignable to ErrorDescription or to Iterable. Its sole parameter must be HintContext.
and also a JavaFix
A base class for fixes that modify Java source code. Using this class as a base class makes creating the fix somewhat simpler, but also supports running the hint in the Inspect&Transform dialog. The fix can be converted to Fix by means of the toEditorFix() method.
Read the official tutorial and the org.netbeans.spi.java.hints documentation for full details.

Java package politics

I always doubt when creating packages, I want to take advantage of the package limited access but at the same time I want to have similar classes divided into packages.
The problem comes when you understand that packages are not hierarchical in Java:
At first, packages appear to be
hierarchical, but they are not.
source
Imagine I have an API defined with its classes at foo.bar, only the classes the API client needs are set public. Then I have another package with some internal objects I need in the API defined at foo.bar.pojos, this classes need to be public so they can be accessed by foo.bar but this means the API client could also access them if the package foo.bar.pojos is imported.
What is the common package politic that should be followed?
I've seen two ways of doing.
The first one consists in separating the public API and internal classes into two different artefacts (jars). The documentation is separated as well, and it's thus easy for the end user to make the distinction between what is internal and what is not. But it sometimes make things more complex to have two jars, two source trees, etc.
The second one consists in delivering a single jar, but have a good documentation allowing to know what's internal and what's not. The textual documentation can explain how to use the API (and thus avoids talking about the internals). And the javadoc can specify that a class is for internal use and is thus subject to changes.
Yes, Java packages don't give you enough control over your dependencies. The classic way to deal with this is to put external APIs in one package and internal implementation classes in another, and rely on people's good sense to avoid creating dependencies on the latter.
With Maven and OSGI, you have an additional mechanism for managing dependencies between modules / bundles of packages. In the case of OSGI, you can explicitly declare some packages as not exported, and an OSGI aware development environment will prevent people creating harmful dependencies. Maven's module support is weaker, but at least it controls dependency cycles.
Finally, you could use custom PMD rules to enforce your project's modularization conventions ... in the same way that there are rules to discourage dependencies on Java's "com.sun.*" package tree.
It is a mess.
Using only what Java itself offers, you have to put everything in the same package. You end up with a single (or a few) packages with lots of classes, and no good way to group them for yourself (but at least that problem does not leak outside). Most people don't do that, though, and as a result, your (as a developer on top of these libraries) public classpath is littered with stuff you should never need to see.
You might like OSGi, which has (and enforces) the concept of bundle-private packages. Those are not exported to the outside world.

Categories

Resources