So what I plant to do is renaming things to something like these
(suggestion for better names are welcome):

ZeroArgumentNonVoidMethodPolicy.BEAN_AWARE_THEN_EXPOSE_AS_METHOD
ZeroArgumentNonVoidMethodPolicy.BEAN_AWARE_THEN_EXPOSE_AS_PROPERTY
ZeroArgumentNonVoidMethodPolicy.BEAN_AWARE_THEN_EXPOSE_AS_PROPERTY_AND_METHOD

And then maybe I would also add policies where we don't care about
bean stuff, as it should be in theory with records. I don't think many
user will want such a purist approach, but it can be useful in
ensuring that our implementation is sound (because then it should be
possible to implement such a policy).

On Wed, Apr 3, 2024 at 8:38 PM Simon Hartley
<scrhart...@yahoo.co.uk.invalid> wrote:
>
> > Hm... I have to think about what future requirements we could run
> > into, and if therefore it's actually a better idea to go the other way
> > around, that is, to address the existence of Java Bean properties
> > inside ZeroArgumentNonVoidMethodPolicy (i.e., include BEAN_PROPS
> > this-and-that in the enum names).
>
> I'm also still thinking things through, including 
> BeansWrapper.EXPOSE_PROPERTIES_ONLY
>
> > .... the main issue with this
> > new setback in the Java language design is exactly that I can only
> > tell that it's a zero argument method that returns non-void, but I
> > don't know if it's an accessor, or it sends out mails to all users if
> > I call it, or what. (When these started with "get"/"is", at least you
> > had a strong guess.)
>
> Good point: there's no language difference between e.g.
> an adjective/state method "active" and a verb/operation method "activate".
> (Well, there are components in records, but nothing to distinguish things in 
> normal classes.)
>
> > Fixed it, and thanks for spotting this!
>
> Great! Thank you very much.
>
>
> Cheers,
> Simon
>
>
>
> On Wednesday, 3 April 2024 at 17:03:54 BST, Daniel Dekany 
> <daniel.dek...@gmail.com> wrote:
>
>
>
>
>
> > NonBeanAccessorsPolicy.XXX (as opposed to 
> > ZeroArgumentNonVoidMethodPolicy.XXX)
>
> Hm... I have to think about what future requirements we could run
> into, and if therefore it's actually a better idea to go the other way
> around, that is, to address the existence of Java Bean properties
> inside ZeroArgumentNonVoidMethodPolicy (i.e., include BEAN_PROPS
> this-and-that in the enum names). And also, the main issue with this
> new setback in the Java language design is exactly that I can only
> tell that it's a zero argument method that returns non-void, but I
> don't know if it's an accessor, or it sends out mails to all users if
> I call it, or what. (When these started with "get"/"is", at least you
> had a strong guess.)
>
> > For 2.3.32:
> > * non-bean class accessors could only be methods
> > * bean class accessors could be methods and properties
>
> Some mostly terminology related clarifications for this. The
> FreeMarker template language doesn't have anything called properties.
> The Java Bean specification talks about properties, and hence
> BeansWrapper (and hence DefaultObjectWrapper, which is its subclass).
> In tempataes, Java Bean properties are only exposed as sub-variables
> (like foo.bar), not as methods with that(!) name (i.e. "bar"). That
> the Java Beans property read method (foo.getBar(), or foo.isBar()) is
> also exposed is unrelated to the fact that it's a Java Bean property
> read method. It's because Java Beans expose them as "actions" (I don't
> know why, but that what they did). The name of these actions (usually)
> differs from the property name ("foo" VS "getFoo").
>
> > * non-bean record accessors could only be methods
>
> By default, yes. Though the MethodAppearanceFineTuner was always pluggable.
>
> > * bean record accessors are generally a mistake
>
> Actually, they are probably often there on purpose, since existing
> libraries expect "properties" exposed via getXxx/isXxx methods.
> Because they decided to break this pattern (instead of doing what
> people have been asking for since forever), now we will sometimes end
> up with hacks like @lombok.Getter public record MyRecord(String bar,
> boolean accessible) { }. In this case, myRecrod.bar() and
> myRecord.getBar() are both accessor methods to get the value of "bar",
> and there was no intention to create a "getBar"
> property/sub-variable/component/attribute/whatever-we-call-it.
>
> > With the current implementation, both of the following cause an error when 
> > the "active" property is used!
> > record MyRecord(boolean isActive) {
> >    public boolean active() {
>
> Maybe people who do that deserve their fate. :) So, if you have no
> active() there, then myRecord.active gives a boolean, because that's
> just an accidental Java Bean property in this case, and then
> myRecord.isActive will not give a boolean (but a method), since that
> method now was taken over by the Java Beans logic. Not great, but
> maybe not too bad. But, if you add MyRecord.active() to that class as
> well, then that's a Java Bean "action" (the term for things meant to
> be exposed as methods), and by default methods shadow properties with
> clashing names (although that's configurable via
> BeansWrapper.methodsShadowItems).
>
> > record MyRecord(boolean active) {
> >  public boolean isActive() {
>
> That I expect to be a typical use-case, because of the backward
> compatibility hacks needed sometimes. I missed that case in the JUnit
> tests, and as the usual punishment for that, of course it was broken.
> Fixed it, and thanks for spotting this!
> https://github.com/apache/freemarker/commit/9cc2b9cb6d1196fffa010430920331a36e7cbf49
> Also deployed to the snapshot repo
> (https://repository.apache.org/content/repositories/snapshots/org/freemarker/freemarker/2.3.33-SNAPSHOT/).
>
> On Mon, Apr 1, 2024 at 6:49 PM Simon Hartley
> <scrhart...@yahoo.co.uk.invalid> wrote:
> >
> > In terms of language, for a record's read methods, Java calls them 
> > accessors.
> > For beans, I'm used to the term getter, but when expanding to also describe 
> > how boolean return methods are handled,
> > the term accessor is again used. It seems that zero-argument non-void is 
> > trying to be distinct from the term accessor,
> > because that's what we believe is necessary for backwards compatibility and 
> > compatibility with beans
> > (and a project could have a mixture of bean and non-bean style classes).
> >
> > But trying to move the problem slightly, what do you think of the following 
> > idea?
> > NonBeanAccessorsPolicy.XXX (as opposed to 
> > ZeroArgumentNonVoidMethodPolicy.XXX)
> > Note: I've used a plural here to try to highlight we're saying the methods 
> > are non-bean, rather than the classes.
> > So how does this help us when there's a conflict?
> > We've implied that logic for bean accessors may be being applied as well; 
> > this can be supplemented with documentation.
> > Also not every future option should hang off 
> > ZeroArgumentNonVoidMethodPolicy,
> > since our original intent was to describe non-bean related behavior.
> >
> >
> > For 2.3.32:
> > * non-bean class accessors could only be methods
> > * bean class accessors could be methods and properties
> > * non-bean record accessors could only be methods
> > * bean record accessors are generally a mistake
> >
> > For 2.3.33:
> > * non-bean class accessors were added to address use cases for both records 
> > and classes.
> > * we haven't introduced an option to turn-off bean accessors for records to 
> > solve the problem for records
> > * for some projects, an option to turn-off bean accessors for classes may 
> > be useful,
> >  but some projects would want a mixture
> > * where there is a mixture here are some approaches:
> >  - prefer exposing bean properties (more likely to be backwards compatible?)
> >  - prefer exposing non-bean properties (would work better with records?)
> >  - error (force the user to resolve ambiguity by either using a method 
> > invocation or changing their Java code)
> >  - expose both (collisions?)
> >
> >
> > Property collisions
> > ---------------
> >
> > What happens when a record has fields/components of both active and 
> > isActive?
> > record Evil(boolean active, boolean isActive) {}
> >
> > With the current implementation, both of the following cause an error when 
> > the "active" property is used!
> > record MyRecord(boolean isActive) {
> >    public boolean active() {
> >        return false;
> >    }
> >    // implicit method isActive()
> > }
> > record MyRecord(boolean active) {
> >    public boolean isActive() {
> >        return false;
> >    }
> >    // implicit method active()
> > }
> >
> > So collisions are already there, not a potential risk.
> >
> > Simon
> >
> >
> >
> >
> >
> > On Monday, 1 April 2024 at 12:35:44 BST, Daniel Dekany 
> > <daniel.dek...@gmail.com> wrote:
> >
> >
> >
> >
> >
> > I think we need the current behavior for the
> > almost-backward-compatible behavior that incompatibleImprovements
> > 2.3.33 promises. (Although it's "incompatible", there's a promise that
> > as far as it's 2.3.x, it only enables changes that are most likely
> > won't break your application, hence when someone discovers that they
> > need some of the improvements it brings, they can usually crank it up,
> > and get all the other improvements too, instead of people having some
> > unique permutation of "improvements" enabled.) So maybe
> > ZeroArgumentNonVoidMethodPolicy.PROPERTY_ONLY should be called
> > PROPERTY_UNLESS_BEAN_PROP_READ_METHOD (oh my...), and
> > BOTH_PROPERTY_AND_METHOD should called
> > PROPERTY_UNLESS_BEAN_PROP_READ_METHOD_AND_METHOD (even funnier name).
> > And then later we can introduce other policies if needed, which are
> > less backward compatible, but might be seen cleaner or more obvious.
> >
> > On Sun, Mar 31, 2024 at 4:49 PM Simon Hartley
> > <scrhart...@yahoo.co.uk.invalid> wrote:
> > >
> > > If I was trying to do something here's an idea or two
> > > (please don't feel any pressure to implement this, I'm just thinking out 
> > > loud):
> > >
> > > How properties are implemented is from two sources: beans and simple 
> > > non-voids.
> > > When the logic of both is being applied, then it's not a surprise that 
> > > there are some strange interactions.
> > > If I could enable them separately, then I could turn off bean properties 
> > > on records and have it work as I hoped.
> > >
> > > Otherwise perhaps I would need to have a backwards compatibility mode 
> > > which is only enabled when using the default values.
> > > Or perhaps a setting which said whether beans or simple non-voids take 
> > > precedence.
> > >
> > > I'm more than happy with the status quo; a few rough edges aren't the end 
> > > of the world.
> > > I very much appreciate the effort you've already put in and what's been 
> > > done is a huge improvement.
> > >
> > > Thank you so much,
> > > Simon
> > >
> > >
> > >
> > >
> > > On Sunday, 31 March 2024 at 02:05:32 BST, Daniel Dekany 
> > > <daniel.dek...@gmail.com> wrote:
> > >
> > >
> > >
> > >
> > >
> > > Yeah, it is confusing/complicated if somebody digs into it. So you
> > > have `boolean isAccessible()` in a record. Because it's in a record,
> > > it's a good question what the intent of the author was (plus, now that
> > > the Java language makers make a mess, people will start using the same
> > > pattern in all kind of classes, randomly mixed with old-style
> > > getters). Like maybe it looks as a Java Beans property read method
> > > only accidentally, and they want this property-like thing to be called
> > > "isAccessible". But I think the most likely, by far, is that the
> > > authors are just confused about what the convention now is. Also,
> > > Java's java.beans.Introspector tells us that that's what it is: a Java
> > > Beans property called "accessible". FreeMarker doesn't try to guess if
> > > from the name. Also, this happens to be the most backward compatible
> > > behavior too.
> > >
> > > The end result is as below.
> > >
> > > These will work:
> > > myRecord.accessible - boolean value, because it's a Java Beans
> > > property called "accessible"
> > > myRecord.isAccessible() - which returns boolean, because a such a
> > > public method exists in Java, and therefore people expect it to work
> > > like in Java.
> > >
> > > This doesn't work:
> > > myRecord.accessible() - because there's no such method in Java, so it
> > > would be quite absurd
> > > myRecord.isAccessible - is not a boolean value, but a method, because
> > > that's how it always was with JavaBean property read methods.
> > >
> > > And then, you say, maybe myRecord.isAccessible should also be a
> > > boolean? I don't know... It's more backward incompatibility risk for
> > > sure.
> > >
> > > Also, note that if something is related to JavaBean properties, the
> > > ZeroArgumentNonVoidMethodPolicy doesn't apply. We decided that it's a
> > > JavaBean property read method, and end of story.
> > >
> > > That the ZeroArgumentNonVoidMethodPolicy name doesn't convey the exact
> > > meaning is true. Not sure what a better name could be though, that's
> > > not comically long.
> > >
> > > On Sat, Mar 30, 2024 at 1:11 AM Simon Hartley
> > > <scrhart...@yahoo.co.uk.invalid> wrote:
> > > >
> > > > Similarly, for a record with a field (component) called isActive,
> > > > its property name is currently "active" and not "isActive".
> > > > Additionally, this exposed property is callable as a method even when 
> > > > the setting is PROPERTY_ONLY,
> > > > due to it being considered a bean property and not a record property.
> > > >
> > > > Is this the compromise we're making and something we'll live with,
> > > > or should we add more complexity so that this doesn't always apply?
> > > >
> > > >
> > > >
> > > > On Friday, 29 March 2024 at 23:29:31 GMT, Simon Hartley 
> > > > <scrhart...@yahoo.co.uk.invalid> wrote:
> > > >
> > > >
> > > >
> > > > I've worked out what my confusion was:
> > > >
> > > > I was setting it to METHOD_ONLY and then becoming confused that the 
> > > > bean get method still worked as a property.
> > > > Of course, this setting only affects zero-argument non-void methods 
> > > > which ALSO aren't bean getter methods.
> > > >
> > > > I think that means that if a class was using non-bean style and has a 
> > > > field called isActive,
> > > > then if you create a method for it called isActive, then its property 
> > > > name is "active", not "isActive"
> > > > (even when set to BOTH_PROPERTY_AND_METHOD or PROPERTY_ONLY).
> > > > i.e. It's not exposed as both "active" (from the bean property syntax) 
> > > > and "isActive" (from the non-bean style).
> > > >
> > > > I hope that's right and all as intended!
> > > >
> > > > Cheers,
> > > > Simon
> > >
> > >
> > >
> > >
> > > --
> > > Best regards,
>
> >
> > > Daniel Dekany
> >
> >
> >
> > --
> > Best regards,
> > Daniel Dekany
>
>
>
> --
> Best regards,
> Daniel Dekany



-- 
Best regards,
Daniel Dekany

Reply via email to