Hi Paul,
1) for me, if you have to explain a name better, then it is already a
bad name. Intuitively suggesting the correct interpretation to another
developer, without requiring him to thoroughly read through the
documentation, is the art of picking good names (which imho Groovy
overall does a good job at).
With regards to @KnownImmutable, "someone (the compiler or the
developer) knows" is even more confusing. If it is in fact irrelevant
who knows it, why is there a "Known" in the name in the first place ?
And why is therefore e.g. @IsImmutable not a better name (it could also
carry a parameter which can be true or false, with false allowing a
developer to express that a class is definitely not immutable (even if
it might look that way on first glance; e.g. effectively blocking or
issuing a warning in certain parallel execution scenarios)).
2) There seems to be a contradiction in your statements: You say that
"Once @ImmutableBase (or whatever name) processing has finished its
checks, it can then vouch for the class and puts the marker interface
[@KnownImmutable] "rubber stamp" on it", but further down you say that
"These changes [that @ImmutableBase applies] alone don't guarantee
immutability.". Is it a "known immutable" after @ImmutableBase has done
its thing, or not ?
3) If I did not miss something the new @Immutable meta annotation is
made up of the following annotations:
@ImmutableBase
@KnownImmutable
@ToString
@EqualsAndHashCode
@MapConstructor
@TupleConstructor
How is any of the last four necessary for a class to be immutable ?
Immutability to me means, that the state of the class cannot be changed
after it has been created. How are @ToString, @EqualsAndHashCode,
@MapConstructor, and @TupleConstructor helping with this ?
At least one ctor to initialize the class fields is basically necessary
to make this a practically usable immutable class, yes, but @IsImmutable
it must be after @ImmutableBase does its job, or it will not be
immutable in the end. All the other annotations are just icing on the
cake (see "@Immutable should be named @ImmutableCanonical").
If you keep @ImmutableBase, at least consider replacing @KnownImmutable
with @GuaranteedImmutableTag or @GuaranteedImmutableMarker ? The "Tag"
or "Marker" postfix at least expresses that this annotation just tags
the class as having certain properties, and that this is a general fact,
and not only known to developers or compilers in the know...
I hope I do not completely miss your point, but this is how it looks to
me from what I read :-),
Cheers,
mg
On 15.01.2018 14:08, Paul King wrote:
Response below.
On Sun, Jan 14, 2018 at 6:11 AM, MG <mg...@arscreat.com
<mailto:mg...@arscreat.com>> wrote:
Hi Paul,
now I get where you are coming from with @KnownImmutable. I agree
with splitting the two concepts: Flexible & elegant :-)
Transferring the parameter name knownImmutables (which exists
inside the @Immutable context) to the annotation name
KnownImmutable (which has no such context) still does not work for
me, though.
In addition having @Immutable = @KnownImmutable + @ImmutableBase
violates the definition you give for @KnownImmutable, because
either the class is "known to be immutable" = "immutable by
implementation by the developer", or it becomes immutable through
@ImmutableBase & Groovy...
Well that is perhaps an indication that it needs to be explained
better rather than necessarily a bad name. I'll try again. It just
means that someone (the compiler or the developer) knows that it is
immutable. If that marker interface is on the class there is no need
to look further inside the class, you can assume it is vouched for as
immutable. Once @ImmutableBase (or whatever name) processing has
finished its checks, it can then vouch for the class and puts the
marker interface "rubber stamp" on it.
What do you think about:
@IsImmutable
@ImmutableContract
@GuaranteedImmutable
instead
?
Thinking about this some more, still don't like @ImmutableBase.
Sounds too much like a base class to me - and what would be the
"base" functionality of being immutable ? Something either is
immutable, or not (@ImmutableCore also fails in this regard ;-) ).
So still would prefer @ImmutableOnly o.s. ..
@ImmutableOnly indicates that it is somehow immutable at that point -
it isn't really a finished immutable class until all the other related
transforms have done their thing. Perhaps it is useful to reiterate
what it does. It does a whole pile of validation (you can't have
public fields, you can't have certain annotation attributes on some of
the other annotations that wouldn't make sense for an immutable
object, you can't have your own constructors, it can't be applied on
interfaces, it checks spelling of property names referenced in
annotation attributes) plus some preliminary changes (makes class
final, ensures properties have a final private backing field and a
getter but no setter, makes a copyWith constructor if needed). These
changes alone don't guarantee immutability. Would you prefer
@ImmutablePrelim?
Cheers,
mg
-------- Ursprüngliche Nachricht --------
Von: Paul King <pa...@asert.com.au> <mailto:pa...@asert.com.au>
Datum: 13.01.18 13:17 (GMT+01:00)
An: MG <mg...@arscreat.com> <mailto:mg...@arscreat.com>
Betreff: Re: Making @Immutable a meta-annotation
I should have explained the @KnownImmutable idea a bit more. I
guess I was thinking about several possibilities for that in
parallel. What I really think is the way to go though is to split
out the two different aspects that I was trying to capture. One is
triggering the AST transformation, the other is a runtime marker
of immutability. With that in mind I'd suggest the following:
@KnownImmutable will be a marker interface and nothing more. Any
class having that annotation will be deemed immutable.
E.g. if I write my own Address class and I know it's immutable I
can mark it as such:
@KnownImmutable
class Address {
Address(String value) { this.value = value }
final String value
}
Now if I have:
@Immutable
class Person {
String name
Address address
}
Then the processing associated with @Immutable won't complain
about a potentially mutable "Address" field.
Then we can just leave @ImmutableBase (or similar) as the AST
transform to kick off the initial processing needed for immutable
classes.
The @Immutable annotation collector would be replaced by the
constructor annotations, ToString, EqualsAndHashcode and both
ImmutableBase and KnownImmutable.
The name KnownImmutable matches existing functionality. Two
alternatives to annotating Address with KnownImmutable that
already exist would be using the following annotation attributes
on @Immutable:
@Immutable(knownImmutableClasses=[Address]) or
@Immutable(knownImmutables=[address]).
Cheers, Paul.
On Sat, Jan 13, 2018 at 1:43 PM, MG <mg...@arscreat.com
<mailto:mg...@arscreat.com>> wrote:
Hi Paul,
I think the core of the problem is, that @Immutable as a
meta-annotation woud be better off being called something
along the line of @ImmutableCanonical (see: If you do no need
the immutability, use @Canonical), since it does not solely
supply immutability support - then it would be natural to call
the actual core immutability annotation just "Immutable".
That is probably off the table, since it would be a breaking
change - so we are stuck with the problem of naming the
immutability annotation part something else.
@ImmutableClass would imply to me that the "Class" part
carries some meaning, which I feel it does not, since
a) "Class" could be postfixed to any annotation name that
applies to classes
b) The meta-annotation should accordingly also be called
"ImmutableClass"
Because of that I find postfixing "Immutable" with "Class"
just confusing. It also is not intuitive to me, which
annotation does only supply the core, and which supplies the
extended (canonical) functionality...
I do not understand where you are going with @KnownImmutable
(known to whom ?-) To me this seems less intuitive/more
confusing than @ImmutableClass...).
@ImmutableCore is similar to @ImmutableBase (because I
intentionally based it on it :-) ), but different in the sense
that it imho expresses the semantics of the annotation: Making
the object purely immutable-only, without any constructors,
toString functionality, etc.
How about:
@ImmutableOnly
@PureImmutable
@ModificationProtected
@Locked
@Frozen
@Unchangeable
@Changeless
@InitOnly
@InitializeOnly
@Constant
@Const
@NonModifieable
@NonChangeable
?
mg
On 12.01.2018 08:01, Paul King wrote:
@ImmutableCore is similar to @ImmutableBase - probably okay
but I don't think ideal. Another alternative would be
@ImmutableInfo or have an explicit marker interface with a
different package, e.g. groovy.transform.marker.Immutable but
that might cause IDE completion headaches. Perhaps
@KnownImmutable as a straight marker interface might be the
way to go - then it could be used explicitly on manually
created immutable classes and avoid the need to use the
knownImmutableClasses/knownImmutables annotation attributes
for that case.
Cheers, Paul.
On Thu, Jan 11, 2018 at 9:34 PM, mg <mg...@arscreat.com
<mailto:mg...@arscreat.com>> wrote:
Hi Paul,
great to make @Immutable more fine granular / flexible :-)
what about
@ImmutabilityChecked
or
@ImmutableCore
instead of @ImmutableClass ?
Cheers
mg
-------- Ursprüngliche Nachricht --------
Von: Paul King <pa...@asert.com.au
<mailto:pa...@asert.com.au>>
Datum: 11.01.18 08:07 (GMT+01:00)
An: dev@groovy.apache.org <mailto:dev@groovy.apache.org>
Betreff: Making @Immutable a meta-annotation
There has been discussion on and off about making
@Immutable a meta-annotation (annotation collector) in
much the same way as @Canonical was re-vamped. (This is
for 2.5+).
I have a preliminary PR which does this:
https://github.com/apache/groovy/pull/653
<https://github.com/apache/groovy/pull/653>
Preliminary because it still needs a bit of refactoring
to reduce some duplication of code that exists between
the normal and immutable map and tuple constructors. I
still need to do this but that can happen transparently
behind the scenes as an implementation detail if we don't
finish it straight away. As well as reducing duplication,
the pending refactoring will enable things like the pre
and post options for MapConstructor and TupleConstructor
which aren't currently working.
I am keen on any feedback at this point. In particular,
while most of the functionality is pushed off into the
collected annotations/transforms, I ended up with some
left over checks which I kept in an annotation currently
called @ImmutableClass. I tried various names for this
class, e.g. @ImmutableBase and @ImmutableCheck but
finally settled on @ImmutableClass since the annotation
causes the preliminary checks to be performed but also
acts as a marker interface for the MapConstructor and
TupleConstructor transforms to do the alternate code
needed for immutability and to indicate that a class is
immutable when it might itself be a property of another
immutable class. Let me know if you can think of a better
name or have any other feedback.
Cheers, Paul.