Wujek,
On Mar 14, 2013, at 9:32 PM, Wujek Srujek wrote:
> Just my 2c about the second solution (private access results in exception, but can be forced with special syntax): what purpose will it serve?
First let me please emphasize (i) below -- myself, I'm not a fan of private/protected methods.
Nevertheless if I try to put on a hat of one, I'd say
- it's nice not only to use some methods privately or for-subclassing-only (this self-evidently we all do all the time), but _also_ to explicitly mark them so, not just in comments, but in a formal way
- it's nice the compiler and runtime make sure nobody could call these methods by mistake, which means we can afford simple names.
In ObjC, I would either name my private helper sum method "__ocs_sum", or perhaps I would even use a static function with a self argument (ObjC is a C superset, so whatever C allows, ObjC does too). I would never dare to define private helper method "sum", since the name is ubiquitous, and the danger a subclass inadvertently overrides it with disastrous results (etc) is great.
In Java I could name the thing just "sum" and make it private, and that's that.
In Groovy the fact someone _can_ call it does not change anything -- just like in ObjC anyone _can_ call my __ocs_sum method does not mean it is not private. If someone does that and it blows into his face, it's _his_ funeral, not mine: the method was not part of the API contract, and _he_ took the chances to use it.
> a) library users: they call a private method, get an exception, so they think 'Ok, let's just add the exclamation mark (whatever) and get it over with' - so the private access exception is just a minor nuisance and has no real value
Quite the contrary.
Library users -- at least, those of them who are sane -- don't _want to_ call private methods, for it would potentially break their code when new library release comes.
Private methods help them to achieve the goal, for it lessens the danger of inadvertent using of private API.
Thus, they won't use the bang unless they _have to_, rebus desperatis, to work-around a library bug, or to do something highly non-standard. And they would be extra careful to check the library version before such a code gets run.
Of course, there might be also blokes who would simply use the bang without thinking all the time. Their code would be unstable, crashing, and dangerous. They would hardly have any clients. Serves them jolly well right.
> b) library developers - they must simply forget private because it will always be possible to work around it; the fact that private access throws some runtime exception will just confuse some and give a false sense of security
Again, quite the contrary.
See above: the privateness would allow them to rely on simple-named private helper methods without ugly prefixes (and thus generally better readable code).
Also to them, the bang would allow easy writing of test code. No danger there, for they manage the test code along with the library, and if one gets changed, the other does, too.
The fact that someone out there might use the bang has absolutely no consequence for the writers of libraries. It's a dangerous practice not covered by the API contract, and whomever does it, he explicitly takes the chance his code stops working at the first upgrade, and he knows that and behaves accordingly. Or does not behave accordingly and shoots his own leg, and serves him right.
That's also why it's important the bang is a specifict, distinct syntax, which can't be mistaken for normal code.
Note: as I wrote in similar situations previously, myself, I would be completely contented if there was no special language feature for this, and if instead of the bang only low-level runtime API was available, i.e.,
foo!.privateMethod(args) // nope, instead you have to do ...
foo.groovyRuntime.callPrivateMethod('foo',args) // ... something essentially like this
But I can see it would be pretty annoying for test writers, that's why I suggest the bang (or something similar).
> In general I like the fact that groovy doesn't follow Java's access restrictions, just as I like Python's lack thereof (name mangling with the __ prefix doesn't really count). These, and many other languages, are doing just great without this.
Sure, see please again (i) below :)
> I could live with either real access restrictions, or none at all, but the fact that there is some syntax to get around it (and hence making things more complex) would just break the language a tiny bit in my opinion.
I don't like _unbreakable_ rules, for always sooner or later an _exceptional_ need arises to break them. In Java, it leads to hundreds of ugly boilerplate work-arounds, where otherwise one well-marked "dangerous" line would suffice and actually be much less dangerous, for it's easier to guard for known big danger at one small place, than to find small bugs in hundreds and hundreds of "innocent" lines.
Therefore I think a language _should_ offer APIs to do all kinds of dirty stuff, to be available if needed.
On the other hand, these dangerous APIs -- like calling private methods, direct access to ivars, etc. -- should be very distinct and should never happen implicitly.
Thanks and all the best,
OC
=== original ===
> (i) myself, I would be completely contented if Groovy simply ignored all the private/protected modifiers for methods, just as it, far as I understand, more or less does now :)
>
> To compare -- ObjC does not have those things at all (all methods are always fully public in there, the only possible kind of "privateness" is that the world is not informed of their names, and it can be always solved by introspection), and I've actually never bumped into any problem due to that -- not in decades and not in millions of source lines, some of them maintained for those decades. Thus I tend to forget private/protected methods at all, am not using them myself, and if I bump into them in others' code, I tend to be surprised something like that exists at all :)
>
> (ii) as for a correct general future solution regardless backward compatibility with the current codebase... I guess something like granting the access limitations _and_ adding an extra modifier which would say "bang the rules!" would be the best way. Something roughly similar to
>
> class A { static private foo() { ... } }
> A.foo() // error, exactly as would be in Java
> A!.foo() // calls it all right, we ignore the Java rules here
>
> Would probably need some more elaboration with cases like super!.privatesupermethod() etc., but at the first look seems feasible to me.
>
> If something like this really gets ever implemented in Groovy, of course it should be consistent with the field-access rules (see my suggestion of the super-access @@ modifier in a previous message -- it would be much better to use same construction for both, of course, i.e., instead of foo.@@privatefield we should have foo!.@privatefield).
>
> (iii) as for a correct solution which would _not_ break backward compatibility with the current codebase... no idea, to be frank. Nevertheless it seems to me here the prospects are better than with fields :)