DEV Community

Cover image for Why you should avoid package-private scope in Java

Why you should avoid package-private scope in Java

Igor Konoplyanko on November 26, 2019

Recently I was discussing in my project about package-private visibility modifier. "Wait, what is package-private in Java?" It's also sometimes ca...
Collapse
 
snuk87 profile image
Dennis

I don’t share your view. In my opinion package private should be used frequently and should always be used if you don't have to make a class public.

The more restricted your access level the less chances to create unnecessary dependencies that will end up in a big ball of mud. In a lot of architectural styles like clean architecture, layered architecture, hexagonal architecture and domain driven design (DDD) it is important to have clean boundaries between your modules. In case of DDD you have different contexts and you only want to provide access to a domain through a well defined interface. The simplest way to achieve this is with package private scope.

It's also important to organize your packages in a proper way. I have seen a lot of people tend to create too many packages and sub packages but a java package should contain all classes of a specific domain/context. E.g. the web interface, business logic / service layer, DAO layer of one domain should be in one package and only provide functions to other packages through interfaces.

Collapse
 
cauchypeano profile image
Igor Konoplyanko

My position here is that to avoid unnecessary dependencies we need to use better mechanism as we have with Package scopes. It's too poor and will not help us to achieve hexagonal architecture/DDD but will annoy us during refactoring.

That's also reason why java got jigsaw - to overcome those issues in much nicer way.

So far all reasons I've heard in favor for package-private - is to achieve DDD/Hexagonal architecture based on package scopes.

Collapse
 
snuk87 profile image
Dennis

Can you give me an example of anything that becomes annoying when you use package private?
I never faced any problems ... quite the contrary, it showed me when my domain design wasn't good.

In your blog post you said that you agree with oracles recommendation on using the most restrictive access level but in the next sentence you say Life will be much easier for your project if everything will be public/private. So you say it's better to use public instead of package private. Those two sentences are a contradiction.

The main reason why JAVA got jigsaw was to modularize the JDK. That you can use it for your projects is just a nice side effect. I totally agree that jigsaw is a much cleaner solution than using package scopes but in reality jigsaw is mostly used for green field projects and old projects are rarely refactored to use jigsaw. So I think it will take a few more years that the majority of JAVA applications will shift to jigsaw.

That's why package private is so important. You need a clean architecture when you have a project with 1M+ lines of code and working with 20 other developers. Also it's much easier to slice your application into micro services when you have a clean architecture.

Collapse
 
darkknightpl profile image
Marcin Jarząbek • Edited

I don't think I'd agree with title statement - of course it's important to choose apropriate scope to specific case we're dealing with, but package scope is definetely being used too rarely.
Devs, left with choice either public or private tend to choose public to make things easier. But making class or method public it means it is part of your contract - functionality your package expose to other parts of code. If another part is using this class/method it's much harder to change/refactor it and code becomes tightly coupled.

An alternative is to make only one class in package public - and this class, facade, becomes your contract. All other classes can be package private. Then you test your package behaviour via facade class and refactoring is much easier.
Following this pattern makes also reading code easier - if you need only some functionality from package you only need to read facade class - and it's immediately visible - because it's public. Only if you need to change sth inside you need to go deeper and read another classes.

Architecture pattern that adapts this package-private style easily is hexagonal architecture, or ports-adapters architecture. You expose functionality of domain via public port, and rest of it is hidden with package-private scope. Following BDD you test domain via ports - like a black box.

Good talk about hex architecture and package scope :)
youtube.com/watch?v=sOaS83Ir8Ck

Collapse
 
cauchypeano profile image
Igor Konoplyanko

thank you for your reply!
Regarding your comment: I am generally agree with you, especially that I am also fan of hexagonal architecture. But in my opinion packages+package scope is very constrained and rigid mechanism to do so.

For example if you have more than 20 classes - you can't split them into subpackages so easily. Subpackages do not see package-private classes above them! For me the better way will be going with modularized application, especially with project jigsaw on top of it. In this way we will be really in control what part of our module we can expose and what part we want to hide as internal implementation details.

Collapse
 
darkknightpl profile image
Marcin Jarząbek • Edited

Thanks for replying for my comment :)

My concern is that many other developers don't have much experience with jigsaw, or maybe won't use it because project isn't especially big. Therefore I think package scope shouldn't end up on the scrap heap yet ;) If used properly can be very helpful in maintaining project architecture clean and modules loosely coupled.

Collapse
 
calinzbaenen profile image
Calin Baenen

Java needs an equivalent to internal from C#.
Another reason "package-private" is bad is because you can't use those pckg-prvt things from a "super-package". But why not? Wouldn't it make sense to treat a super as part of that family?

Collapse
 
developmind profile image
Dirk Detering

Well , in my opinion this article is too short-sighted.

It doesn't even state it's conclusion clearly.
This conclusion is not "avoid package private", as the title suggests, but "jigsaw modules are a better way to solve the visibility problem".

Would it be written with this conclusion in mind, I would mostly agree. In theory at least.

In practice, the picture is far more complicated. "Avoid package private" sounds first like an advice of an experienced architect who has come to this conclusion due to being faced with heavy pains over years in many ways when working with PP.

But in my experience this advice is only valid for a new small project starting with jigsaw from ground up.

This advice is not applicable and simply dangerous for large legacy codebases which are still maintained (refactored, enhanced) with many dependencies, based on a legacy toolchain to build it and still based on JEE application servers.

Here "jigsaw the world" is simply not an option. Point.
Packages are the only way to modularise beyond jars (which are mostly fat), and the lack of using package-private where possible, useful and needed in the past already led to heavy pains due to leaking implementation details into APIs.
The way to solve that is by refactoring into usage of PP, not away from it.

Large legacy codebases of enterprise systems are in 2020 still on JDK8 (being LTS) and are still on the way to migrate to JDK11(being the current LTS).
But this migration - a painful one btw - still doesn't produce a jigsawed system, but a system using all possible legacy flags and single-module-all-the-shit solutions, just to get the migration done in shortest time (in our company now round about ten month, still not done).

So my advice is: Use package-private where you haven't been aware of this possibility before (some young developers indeed weren't). It's an undervalued tool in your box!
Perhaps add a dev-comment ("pp by purpose"), as due to Java's default behaviour a reader cannot be sure if the modifier wasn't simply forgotten, so some new maintainer may try to add 'public' to "correct" that. That's the only quirk I see with PP.