Kotlin to support package protected visibility

I have just recently switched from Java to Kotlin for microsevice implementation. I like the language but the absence of package private visibility is what discourages me the most so far.

I’m surprised no one yet mentioned anything about two major practices for structuring your code: package by layer vs package by feature. This article describes the subject really well: Java Practices->Package by feature, not layer

So what you Kotlin team did is made all the people who use package by feature to structure the code quite unhappy.

Basically i want my package to become my second most primitive module unit after the class itself. Package scope (visibility) is an essential unit for code modularization and you have thrown it away making package a mere unit for structuring physical files.

The thing is, these modifiers are visibility modifiers. Not access modifiers. They don’t provide encapsulation - there’s no real encapsulation in OOP. They let you constraint the code visibility. And we are using that to express ourselves. Not to protect our code from being accessed. Yes you can access my code and i’m ok with that because you can only do that in an unnatural way implying that you shouldn’t be doing that in the first place.

  • This is not about encapsulation - this is about modularization by means of visibility constraints
  • This is about the design, about being able to draw the line while structuring your program
  • This is the second most simple and one of the most important methods for modularization in Java, enforced by the language designers by default
  • No package scoping in the language forces us to make all of the package private classes private staffed inside the single file which is just bad
  • No package scoping in the language provokes the pollution of the classpath rendering code autocompletion useless
  • internal visibility modifier is useless when you work on the same codebase and has no actual value in this context thus can’t be considered as package private replacement
  • The larger the codebase the more of the problem absence of the package scoping really is

I don’t need to protect my code. I want to express myself. I want to hide implementation details in my package to make my design and intentions clear to others and to myself when i revisit the codebase.
With package scoping i can design the module around the package exposing only it’s public API and leverage DI framework to actually wire the “package modules”. If my package grows i separate it into the actual module or even microservice of it’s own. When i use DDD with “package by feature” i can naturally implement everything related to one aggregate root within single package and later make that a separate microservice without much effort.

Please, Kotlin team, reconsider this and incorporate the package visibility scope into the language.

I couldn’t agree more.

package private was very cleverly chosen to be the default scope. And Kotlin throws it away making everything wide-open by default. And internal is the same “wide-open” in the context of a single code base. Most of the classes we write are an implementation details related to the package we are in so public isn’t suitable as the default scope, is it?

14 Likes

@eugene, What you describe is easily achieved by creating a nested “internal” package within each feature package.

It allows package by feature and expresses the intended access of the class within the app or library. One feature accessing another feature’s internal details is “unnatural” since it has to reach into the other feature’s internal package.

Note: I use package by feature in this way and I am quite happy.

@nickallendev, you invented your own convention with the dedicated nested package, correct?
While i see how it helps to address part of the problem in question, i still can’t see it as a replacement for proper visibility scope control: granted a medium to large codebase one could easily use your internal classes without the second thought on a couple of successful autocompletion attempts. And validating the class packages against the convention on every autocompletion would be so inconvenient, one could consider that a waste of time.

In the end, i don’t want to ask everyone to follow my convention and not use classes from the “internal” package, i want to have a way to enforce that by means of the language. Furthermore, i want to reduce the set of wide-openly visible types and the corresponding mental overhead.

Constraints liberate.

2 Likes

@eugene

you invented your own convention with the dedicated nested package

Not exactly, my team shamelessly stole this particular convention from other libraries:
https://github.com/ReactiveX/RxJava/tree/2.x/src/main/java/io/reactivex/internal
https://github.com/Kotlin/kotlinx.coroutines/tree/master/kotlinx-coroutines-core/common/src/internal
https://github.com/square/moshi/tree/master/moshi/src/main/java/com/squareup/moshi/internal

one could easily use your internal classes without the second thought on a couple of successful autocompletion attempts

It’s quite easy for auto-complete to expose classes of an external library not even within the same project in Java.

i don’t want to ask everyone to follow my convention

I don’t advise anybody to randomly start using their own conventions within a team and demand others to adhere. Do what works for your team.

Using a package naming pattern is a simple way to express intentions. It can be especially helpful when using a tool (like an annotation processor) that requires public classes. It is not the only way to express such intentions and it is definitely not a replacement for modularization.

If a project is too large then you also have to deal with other problems like long build times and commit histories that are cluttered. While package private can de-clutter your autocomplete, it is not a solution that fully replaces modularizing your project. If you do modularize your project, then Kotlin’s internal visibility will work quite well.

Not if they properly used visibility modifiers.

1 Like

Yes, I also look forward to recursive package visibility

If there are so many people that are asking for a package private visibility why you just don’t implement it?
I am also a big fan of code encapsulation etc.
Maybe it is very hard or even impossible to implement that kind of visibility in Kotlin because of some architectural decisions already made and implemented in Kotlin? If not, please just do it, for the sake of the community.
The protected modifier works even better in Kotlin than in Java (protected things are not visible inside package). Ideally there could be an access visibility like local or whatever, which works as package private in Java and could be combined like local protected (the combination could work as protected in Java)

For top level elements, private is private to the file, not to the class. As such there is a way to encapsulate related code in Kotlin that is not available in Java.

I know that, but having a lot of classes in one file is not a good idea because:

  • they are hidden in the IDE’s project source tree
  • such a file can have 2000+ of lines which makes it very hard to navigate through (you will eventually get frustrated after working with that kind of file for a while)

Another thing that needs package private visibilty iin Kotlin is writting libraries.
Using internal will work well only if you are using the library in Kotlin app.
If you use Kotlin library in Java you will see all the internal classes as public ones which ruins the quality of the library API.
You can use single files with multiple classes of course…

1 Like

I don’t understand why this extreme concern against the implementation of package-visibility.

I see in this thread very good reasons why not to use them and why to use them.

No philosophy seems better than the other, the same way a knife can be used to cook or kill.

Saying that package-visibility can be misused and thus let’s not implement it, is the same as assuming every developer using Kotlin is dumb and has no idea what is doing.

Why not allow package-visibility modifiers to exist, and it boils down to the will of each developer which style he/she prefers to use.

I see very good reasons for the two philosophies and there is no way anyone in this thread is able to say that only one philosophy is the correct philosophy. And for that, I would allow this feature.

Certainly Kotlin has implemented other features that are much more “dubious” of their usefulness/correctness/requested than this feature, and there was much less (or no) obstacles to it.

2 Likes

I don’t see that in this thread. There are a few people here that don’t think package visibility is necessary for kotlin and others who argue it is. Yes AFAIK JetBrains is part of the first group (or at least they used to be), but I don’t think this can’t ever change.
There are good reasons to implement package visibility. If you guys are serious about it you should write a KEEP for it as this is the official way of changing the language. Whether it get’s approved is another question but until then nothing will change.

Basically i want my package to become my second most primitive module unit after the class itself.

Exactly. Encapsulation is Packaging. I also want to do it in Tree manner like inner package/class.

1 Like

Are all the Kotlin devs this arrogant?

5 Likes

Sorry :pensive: I was a jerk there

5 Likes

I’m missing package private too. Currently I’m planning to enforce it externally in the build pipeline with jqassistant. But that is obviously a workaround.

Thanks for mentioning jqassistant, at least we can have some clunky half-way solution to this.

I also urge Jetbrains to implement package-level visibility modifiers. It greatly enables better code organization in clean architecture/ddd/screaming architecture designs.

I’ve never heard about jqassistant but can it handle a public class with some package-private methods?
If so how can I tell jqassistant that I want some method in a Kotlin class to not be used outside the package?

I want to know how can I open class only to test class in kotlin? currently in Java class I can use package-private
First asked on https://stackoverflow.com/questions/59158369/how-can-i-open-class-only-to-test-class

1 Like

In Kotlin there’s no way for a class to have methods “more visible” to a test class than to the rest.

For the record Java isn’t really different, even if you use package visibility anyone can create a class in that package and call your package private members.

I’ve been using the Experimental API as a way to quasi-hide implementation details: https://kotlinlang.org/docs/reference/experimental.html
It’s pretty ideal for creating tags and the compiler forces you to either propagate or add a @UseExperimental for them.