1

I understand "how packages should be structured" is very opinion based. But java contains a rule for default package visibility, so it implies that there is a specific reason or pattern, thought in the creation of Java, of how packages should be structured in an object oriented environment using object oriented principles.

I will use the Car Example, starting with methods using the default visibility:

com.company.car.Startup#main (public)
com.company.car.engine.CoreEngine#rotate (default)

At first glance, all methods are semantically supposed to be initially declared as default (in this case except the main() which is the point of entry and should be public).

Ok, now Startup#main need to call the CoreEngine#rotate method when I start the car. But I don't want to expose that rotate() method publicly when somebody uses the CoreEngine for things other than internal purposes (like calling CoreEngine#turnEngineLightOn from a remote control device outside the car).

But... the rotate() method has a default visibility which is package restricted, It is inaccessible from main() method too!

In this case, I have few options:

  • Turn the CoreEngine#rotate method public and rely on duck typing
  • Change the package of the Engine class

I understand in practice that this is not how a real life project should consider the packages role in the design of a project. So does it mean that default visibility is something practically useless semantically? Is this a language failure or there is a design pattern to handle a project structure that solves this semantics problem?

Does a pattern like this really exist? If so, is it documented? Can you provide some real life examples using object oriented code?

Fagner Brack
  • 2,365
  • 4
  • 33
  • 69
  • Your question is almost meaningless, but the Java rules for packages and access control are well enough defined already without adding a redundant design-pattern layer on top of them. Not everything in computer science can be reduced to a design pattern, although there was a fairly serious movement in the 1990s to do exactly that. – user207421 Mar 12 '15 at 09:04
  • "What do you mean"? I mean if there's a design pattern to solve common problems in package structure leveraging, for example, the default visibility modifier (package visibility). For example, the only use I see for default visibility modifier is to unit test DI injected class members using mocks. It would be a design pattern to use the same package structure in a different "test" directory, to create the test class and access the private variables without having to unnecessarly declare the mocked members as "public". – Fagner Brack Mar 12 '15 at 09:12
  • @EJP So you are saying that package default visibility for a class has absolutely no intent to reflect in a project structure at all? It's just because it is? I will try to make the question more specific for a class default visibility. – Fagner Brack Mar 12 '15 at 09:24
  • @FagnerBrack Neither you nor I have said anything about project structure. Your question is about design patterns. – user207421 Mar 12 '15 at 09:26
  • Well, my question is if there is (or there was?) a design pattern or recommended practice regarding package structure to justify the existence of package restriction for default modifiers. Check the edited question. – Fagner Brack Mar 12 '15 at 09:52

1 Answers1

0

Try to have a look at Item 13 Minimize the accessibility of classes and members of Joshua Bloch's book, Effective Java. As the item's title said, the accessibility to your classes and methods has to be stricter as possibile.

So, if you're creating an API, you could use default package visibility for classes and methods that you don't want external components can use.

I think that there is not need of a specific pattern, but there is a need of a good design process. In your example I think there is a design problem, that is: you have two classes too tightly coupled, Startup and CoreEngine that are not in the same package.

As you stated, you can't simply unite Startup and CoreEngine into one single class, because you will violate the Single responsibility principle.

I think you should revise your use case and ask yourself what operation must be available to your user. In this way, you define which will be public methods. IMHO you have three possibilities:

  1. Following what is said here;
  2. Try to think about to use inner classes;
  3. Let unchanged the whole diagram of classes and give to your API user the javadoc of really public classes.

With respect to point 2. I suggest to have a loot at this page: Nested Classes. As reported in the article, compelling reasons for using nested classes include the following:

  • It is a way of logically grouping classes that are only used in one place: If a class is useful to only one other class, then it is logical to embed it in that class and keep the two together. Nesting such "helper classes" makes their package more streamlined.

  • It increases encapsulation: Consider two top-level classes, A and B, where B needs access to members of A that would otherwise be declared private. By hiding class B within class A, A's members can be declared private and B can access them. In addition, B itself can be hidden from the outside world.

  • It can lead to more readable and maintainable code: Nesting small classes within top-level classes places the code closer to where it is used.

Do you think that a solution like the following could solve your problem?

// Class Car provides the public API to interact with a car, but
// it delegates the specific functionalies to its inner classes.
public class Car {
   private Startup startup;
   private CoreEngine core;
   // ...
   private class Startup {
      // The class can access to 'core', then it can 
      // invoke rotate() method
      public void main() { /* ... */ } 
   }
   private class CoreEngine {
      public void rotate() { /* ... */ }
   }
}

What is missing in Java is the possibility to nest scopes. In Scala and Js you can do it.

Community
  • 1
  • 1
riccardo.cardin
  • 7,971
  • 5
  • 57
  • 106
  • In this case I am already using the "stricter" approach by declaring everything default first. The car example shows that if I start with default visibility then I will have problems with my structure when I start accessing methods in the modules located in different packages. The only way to solve this would be declaring those methods public, but that may expose internals that I don't want exposed. Is there a silver bullet pattern to solve this problem without making the method public (duck typing) or changing the Engine class package? – Fagner Brack Mar 12 '15 at 14:53
  • The point is that you should minimize the methods that code in other packages needs to access at all, and only mark those methods public. Anything that doesn't need to be accessed from another package can be marked package private. – Louis Wasserman Mar 12 '15 at 17:32
  • You may have mentioned a valid pattern here, where "two tightly coupled classes should stay in the same package". I initially used Startup#start instead of "main", maybe using "main" creates some confusion with the default "main" method instead of the main startup mode. Anyway, I really don't see how this design is a problem, I have exposed basic public actions in the parent package and internal separated modules. If this is a limitation with java default visibility, then it should exist an objective convention for package structure that prevent this kind of problem from happening, right? – Fagner Brack Mar 13 '15 at 06:24
  • Just fixing things "as it goes" seems to be a waste of time, the level of verbosity a package change can cause in SCM diffs is huge. – Fagner Brack Mar 13 '15 at 06:25
  • I don't know the full diagram class of your application, but what I was trying to say is that probably the classes `Startup` and `CoreEngine` have to be re-engineered into one class. – riccardo.cardin Mar 13 '15 at 06:29
  • This is not actually a real application, but a thought experiment. If I change the main startup method to the CoreEngine, then the CoreEngine would have 2 responsibilities, to start the car and to rotate the engine. This violates the single responsibility principle. How would you engineer this in order to make the "rotate" visibility change irrelevant and still keeping the object oriented semantics? – Fagner Brack Mar 13 '15 at 06:37
  • Ok, I've got the point. I think you should revise your use case and ask yourself what operation must be available to your user. In this way, you define which will be public methods. For example, I don't think that class `CoreEngine` should be public to anyone :P IMHO you have two possibilities: 1) Following what is said [here](http://stackoverflow.com/questions/6470556/pros-and-cons-of-package-private-classes-in-java); 2) Try to think to internal classes. Let me know. What is missing in Java is the possibility to nest scopes. In Scala and Js you can do it. – riccardo.cardin Mar 13 '15 at 06:59
  • Can you please update the question with details to prevent other users from diving into the comments to find the correct information? Then I accept the answer. – Fagner Brack Mar 15 '15 at 10:01
  • Just an observation when you say "I don't think that class CoreEngine should be public to anyone". Yeah I agree, but it seems not practical to put the car components, like Engine, and all engine components inside the same class or package just for the sake of it not being public. It doesn't seem to scale. So if I am going to split the CoreEngine car component into a different public class, then it means I should put in a different package to be able to add additional car components if necessary (and maybe create separate child packages for each group of engine components). – Fagner Brack Mar 15 '15 at 10:10
  • I need to ask one more thing, sorry to bother: What you mean for "Try to think to internal classes"? You mean try to think about using internal classes instead of splitting through packages? – Fagner Brack Mar 15 '15 at 11:13
  • Yes, I meant that...sorry for my english :( – riccardo.cardin Mar 15 '15 at 11:15