Could we get module-private visibility?

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

Could we get module-private visibility?

Mike Hearn
Hello,

Often you want a method or constructor to be private to your module. The
closest approximation for this today is package-private, but this isn't an
ideal match. Kotlin has the "internal" modifier, which makes the modified
element be visible only inside a module. This is simple and often what you
want if you have small modules (which Jigsaw makes much more practical),
however, the JVM doesn't understand it so it's not enforced for other
languages or in reflection/sandboxing.

Using package-private correctly can be tricky. Using Kotlin's notion of
internal is even worse because it gets mapped to public, so in effect the
entire Java ecosystem ignores it.

I think the underlying issue is that packages do a lot of work. They
provide at minimum:

   1. Better organisation of an API in JavaDocs, so types can be given
   descriptions and broken up to make exploration easier for users.
   2. Organisation of a codebase for developers who work on it, to stop
   their IDEs being overwhelmed with giant lists of classes.
   3. An abstraction boundary, so implementation details can be hidden from
   the API user.
   4. A sandboxing boundary, so capabilities can be implemented more easily.
   5. A VCS access control boundary, because they map to directories and
   many version control systems let developers own directories.
   6. An IDE autocomplete boundary, so you can glob import and get better
   auto completion.

So it's not surprising that they get used in various different ways. The
JDK is filled with weird "secrets" classes that exist mostly because of
mismatches between what level of visibility is needed vs provided.
Nestmates have helped mop up some tech debt in this area, but what's
offered to users hasn't changed much. Writing code for sandboxed usage is
hard when you simultaneously want e.g. one package per backend of your API
but also need those backends to access internal methods in top-level
generic API classes. Calls cross package boundaries so package-private
isn't quite right.

An internal modifier like Kotlin's but supported by the JVM would help a
lot for crafting good APIs.

Alternatively, an interesting move might be to do invokedynamic but in
reverse: allow methods/c'tors/fields in class files to declare other
methods as 'guards' which decide at runtime if a link should be allowed or
not. Then languages can implement whatever visibility rules they want in
their standard library, and more of the JVM's linker logic can be moved
into Java itself.
Reply | Threaded
Open this post in threaded view
|

Re: Could we get module-private visibility?

Michael Rasmussen-2
Well, public is technically module-private for any non-exported package.

/Michael
________________________________
From: jigsaw-dev <[hidden email]> on behalf of Mike Hearn <[hidden email]>
Sent: 24 September 2019 18:24
To: [hidden email] <[hidden email]>
Subject: Could we get module-private visibility?

Hello,

Often you want a method or constructor to be private to your module. The
closest approximation for this today is package-private, but this isn't an
ideal match. Kotlin has the "internal" modifier, which makes the modified
element be visible only inside a module. This is simple and often what you
want if you have small modules (which Jigsaw makes much more practical),
however, the JVM doesn't understand it so it's not enforced for other
languages or in reflection/sandboxing.

Using package-private correctly can be tricky. Using Kotlin's notion of
internal is even worse because it gets mapped to public, so in effect the
entire Java ecosystem ignores it.

I think the underlying issue is that packages do a lot of work. They
provide at minimum:

   1. Better organisation of an API in JavaDocs, so types can be given
   descriptions and broken up to make exploration easier for users.
   2. Organisation of a codebase for developers who work on it, to stop
   their IDEs being overwhelmed with giant lists of classes.
   3. An abstraction boundary, so implementation details can be hidden from
   the API user.
   4. A sandboxing boundary, so capabilities can be implemented more easily.
   5. A VCS access control boundary, because they map to directories and
   many version control systems let developers own directories.
   6. An IDE autocomplete boundary, so you can glob import and get better
   auto completion.

So it's not surprising that they get used in various different ways. The
JDK is filled with weird "secrets" classes that exist mostly because of
mismatches between what level of visibility is needed vs provided.
Nestmates have helped mop up some tech debt in this area, but what's
offered to users hasn't changed much. Writing code for sandboxed usage is
hard when you simultaneously want e.g. one package per backend of your API
but also need those backends to access internal methods in top-level
generic API classes. Calls cross package boundaries so package-private
isn't quite right.

An internal modifier like Kotlin's but supported by the JVM would help a
lot for crafting good APIs.

Alternatively, an interesting move might be to do invokedynamic but in
reverse: allow methods/c'tors/fields in class files to declare other
methods as 'guards' which decide at runtime if a link should be allowed or
not. Then languages can implement whatever visibility rules they want in
their standard library, and more of the JVM's linker logic can be moved
into Java itself.
Reply | Threaded
Open this post in threaded view
|

Re: Could we get module-private visibility?

Mike Hearn
Yes, I know. I'm talking about module-private inside exported packages.
Otherwise it can be quite difficult to allow exported and non-exported
packages to work closely together without weakening visibility, and at any
rate, whilst the compatibility considerations are obvious, having a
visibility level of "public" that's actually private to a scope is not a
design anyone would pick if they had a blank slate I imagine!
Reply | Threaded
Open this post in threaded view
|

Re: Could we get module-private visibility?

Remi Forax
----- Mail original -----
> De: "Mike Hearn" <[hidden email]>
> À: "Michael Rasmussen" <[hidden email]>
> Cc: "jigsaw-dev" <[hidden email]>
> Envoyé: Mercredi 25 Septembre 2019 11:30:00
> Objet: Re: Could we get module-private visibility?

> Yes, I know. I'm talking about module-private inside exported packages.
> Otherwise it can be quite difficult to allow exported and non-exported
> packages to work closely together without weakening visibility, and at any
> rate, whilst the compatibility considerations are obvious, having a
> visibility level of "public" that's actually private to a scope is not a
> design anyone would pick if they had a blank slate I imagine!

at the same time, a public method is not really public if the class is not public too,
so it's like russian dolls all the way down.

Rémi