Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use private Java classes for effective API design

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?
like image 900
IAmYourFaja Avatar asked Feb 18 '23 02:02

IAmYourFaja


2 Answers

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.

like image 83
JB Nizet Avatar answered Mar 04 '23 15:03

JB Nizet


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.

like image 27
JimmyB Avatar answered Mar 04 '23 13:03

JimmyB