LppEdd
LppEdd

Reputation: 21104

Java package structure convention

I was working with Typescript and Javascript and I stopped for a bit thinking about namespaces and how we organize code in Java.

Now, pretty often I see multiple classes with the same purpose, just for use with different data, being placed in different packages with different names.

While placing those classes in different packages is a good practice to maintain the project/module in a good state, why would we have to give them different names? I mean, their purpose is the same.

I can answer this question myself: because often we use those classes inside the same unit and they would clash, thus requiring a long full package specification for one or the other.

But aren't we violating the DRY principle? We should use our directory (package) structure to understand in which domain space those classes works.

As I wrote above, I suppose many developers aren't respecting this DRY principle just to avoid long package names. Then, why are we creating those monstruos package hierarchies?
Googling "Java packages best practices" results in suggestions such as:

com.mycompany.myproduct.[...]

Where do those suggestions come from? Aren't we just wasting space?
We obviously do not want to write that every time.

MyClass myInstance;
com.mycompany.myproduct.mypackage.MyClass myOtherInstance;

But it could have been

myfeature.MyClass myInstance
myotherfeature.MyClass myInstance;

We could even specify the full package for both.
So, where do those best practices come from?

As it has been said, this convention dates back to the first releases of Java. Name clashes could be easily solved by qualifying the imported dependency (such as a classpath library) classes with their short packages' hierarchy, emphasizing and keeping cleaner our own code. It is also important to remember we have access to the package-level visibility, which seems overlooked nowdays.

Upvotes: 1

Views: 443

Answers (1)

David P. Caldwell
David P. Caldwell

Reputation: 3821

As a commenter points out, this convention was established at the very beginning of Java, to allow a global namespace to be used for all classes.

One thing about Java that influences this -- and is different from TypeScript and JavaScript -- the name of a class and its package (as well as all the names of classes and packages it uses) is fixed at compile time. You can't recombine classes into a different hierarchy without modifying their source code. So it's not as flexible as an interpreted language where you can just move the hierarchy around and change the locations from which you load code.

You can, of course, put everything in your application in the top-level package, for example, and be pretty confident you'll get away with it. You'll be able to do that as long as everyone else follows the existing convention. Once they stop doing that, and libraries start putting classes wherever they want, you'll have collisions, and you'll have to change your application. Or libraries will start colliding with each other, and if you don't have the source, you won't really be able to fix it.

So there are good reasons.

My opinion-based part of this -- sticking with conventions and a language's (or platform's) culture makes sense. Even if the conventions are silly, in our view. There's a place for breaking them but the advantages have to be pretty big. Other developers will be used to the convention, tools will make assumptions about the conventions ... usually it makes sense to go with the flow.

Does it really make sense to use getters and setters for every property in Java? If you understand the domain you're using well, it very well might not. But stop doing it and your code isn't going to make sense to other members of your team, you'll have to continuously revisit the decision as people join, and so forth.

If it's a one-person project and always will be, of course, you can do what you want.

Upvotes: 1

Related Questions