Question

I am writing my first "API jar" that will be open source library and used by (possibly) other developers. I've read Joshua Block's thesis on effective API design, and one of the things he talks about - that I never would have thought of otherwise - is his concepts of minimizing access and maximizing information hiding. Basically, you only want your API developers to have access to the Java objects they will be using, and you don't want your API developers to have access to any of the "guts" of your library.

In my several years as a Java developer, I've never had the need to make a class anything other than public. Furthermore, I've never used nested classes either. So I'm sitting here wondering how do I implement this "information hiding" best practice in my Java API? And I think private, and possibly nested, classes is the answer. But where to begin?

  • Every .java source file requires at least 1 public class in it to compile. So for me to make a class private (and non-nested), I need to "bundle it with a public class. To me this makes sense only if the public/private classes are heavily related. But what if I have a section of my API that just consists of private classes (for accessibility-minimizing-purposes) that don't relate to any other public analogs?
  • When do you make a private class nested, and when do you make it non-nested? Or is it just a matter of preference?
Was it helpful?

Solution 2

Personally, I don't believe in private. I use protected instead whenever feasible to allow for some of the major benefits of OO design.

Basically the 'information hiding' principle is not bad as a guideline. However, in practice one should not blindly follow it in all cases. - For the pure principle you would, as others suggested, need to define a set of interfaces as public and hide all the rest of your lib away with package-private classes, factory methods, and the like. Given that Java's package-private visibility has some issues that render it somewhat useless in many cases (- classes within your lib will want to cooperate across packages -) this in turn seems to prevent such an approach.

Besides, there are always at least two types of users of an API: the basic users, who will use the objects and methods you provide, and the users with complex requirements, who will want to modify the API's behavior (at least) by inheritance, which a lot of 'hidden' stuff will successfully prevent.

Don't be shy to make those things public for which it may make sense, make things protected which are not really needed to be public, and make only those things private which may cause harm if directly accessed by anything but their directly related code.

Another note: The hiding-principle has as a major purpose to simplify the use of your code by others and to imply and encourage the correct use thereof. But remember that documentation is another important means to achieve this; and documentation will be needed for a library anyway. - If you have 100 public methods and your docs state which 10 of those are needed for a use case the user of your lib will probably get along with that just as well as he would if only those 10 were visible to him.

OTHER TIPS

Classes that are package-private (i.e. don't have any visibility modifier) are only visible by the classes of the same package. That's a way to make a class visible by several other classes of your API, but not by the outside world.

Nested private classes are also useful to make a non-public class, and their scope is even narrower: they're only visible by the enclosing class.

I suggest having a look at Guava's source code for an excellent API design. You'll see all kinds of techniques to hide internals to the outside there.

I do believe in private. I've been working on framework classes quite some time and Joshua is right in telling you that you should hide as much as possible. The reason behind it is that everything that you expose will be used. And once it is used, you can't change it without breaking client code. Everything, that is not private, is accessible from clients! Basically you should work with package private classes, only allow inheritance where useful and make only those classes public that are absolutely necessary to make your lib useful. When extending functionality, the "interface segregation principle" is your friend.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top