On 30 May 2025, at 21:29, Rowan Tommins [IMSoP] <imsop....@rwec.co.uk> wrote:
> 
> On 30 May 2025 19:21:08 BST, Alwin Garside <al...@garsi.de> wrote:
>> In the example above, I image calling or extending the `Foo::bar()` method 
>> from somewhere outside the `Acme` namespace would trigger an E_USER_WARNING 
>> or E_USER_NOTICE. The warning/notice could then be suppressed when 
>> explicitly overriding an `#[\Internal]` method with `#[\Override]`.
> 
> 
> I don't see any reason for the message to be any quieter or easier to 
> override than calling a private method.

If there were a dedicated `internal` modifier keyword, sure. However if one 
simply wants to advertise clearly to other developers that they should expect 
the code to break anytime using an attribute, I feel a compile-time critical 
error is a bit too strict.

> 
> Indeed, one use of an internal/module-private feature would be when the 
> author wants to split up a class that has a large number of private methods: 
> the new classes need to be able to talk to each other, so the existing 
> "private" keyword is no longer appropriate, but the intended surface to users 
> of the library has not changed. The user is making exactly the same decision 
> by ignoring the "internal" flag as they are if they use reflection or 
> code-rewriting to ignore/remove the "private" flag.

I understand your point, but playing devil's advocate for a minute here: I'd 
argue that if a class reaches the point where it has too many private methods, 
something has clearly gone wrong in the architecture or abstraction of that 
class. It probably means part of the functionality needs to be hoisted out to a 
separate class with its own self-contained, stable interface.

One could also argue that if the author really wishes to break private methods 
up across multiple classes, they could also use reflection (or preferably: a 
method call wrapped in a closure bound to the target class) to access their own 
private methods.

My experience with module-level visibility out in the wild (mostly in Java), 
has mostly been libraries where the authors apparently couldn't be bothered to 
dedicate to a stable interface for more specific implementations of certain 
template-pattern adapters and the like – the Android source code is full of 
this.

[rant]
I specifically remember dealing with a DB adapter interface and accompanying 
abstract class, along with implementations for several DBMSs. There was an 
implementation for the specific DBMS I wanted to use, however, per the 
interface, it was completely tied into a separate pagination construction which 
led to a leaky abstraction, and was badly optimized for my use case. I just 
needed to override one or two methods to make it work for me, but the platform 
visibility on those methods meant I had to copy-paste both the abstract class 
and the adapter class to fix the functionality, giving me more code to maintain 
in the process.
I think this is a good example where package/module-level visibility makes 
developers complacent, and not care about offering a library that is easy to 
extend or encapsulate.
[/rant]

Alwin

Reply via email to