> So, we have to go out of our way to say: This one method we invoke at the very end is JUST FOR PROCESSING and nothing else!
Just using it on the constructor, it can work for validation of deeply
immutable values.
If the user want the setter to revert the old value in case of failure
( I really do not think is a good idea)
then you may set at the end of setters a 'different method', that can
do the revert if the user want.
So, to be more precise:
Feature:
the user can write @Post("methName") and annotate
- a class (meaning on all the autogenerated constructor)
- a method
-a field, meaning the generated getter.
the user can write @PostSet("methName") and annotate
- a field, meaning generated setters
Behavious:
The code is desugared so that the method call is injected at the end
of the method, in a try-finally block.
For PostSet, the method may have one argument, that is going to
receive the old value of the setter, or zero argument, to not receive
it.
Usage to support validation:
Case of deeply immutable class
@Post("check")@Value class Foo{String baz; void check(){if
(this.baz.size()<10)throw Error("....");} }
Case of Data class:
@Post("check")@Data@AllArgsConstructor class Foo{
@PostSet("check") String baz;
void check(){if (this.baz.size()<10)throw Error("....");}
}
Case of Data class with reversion of setter effect:
@Post("check")@Data@AllArgsConstructor class Foo{
@PostSet("checkBaz") String baz;
void check(){if (this.baz.size()<10)throw Error("....");}
void checkBaz(String baz){ try{check():}finally{this.baz=baz;} }
}
This design is interesting since it makes possible for the user to
write personalised checks for each field, knowing both the new and the
old value.
It makes clear that the user must 'take care' or injecting checks when
is needed, and that the system does not offer any guarantee that the
object is going to be valid in any moment.
> If we spec this feature to be for validation, then its interaction with setters is daft (the invalid set goes through and THEN an exception occurs), or the feature is very complicated. But it would cover it all.
I hope my proposal is not not too complicated.
I think it covers all the realistic use cases, and is 'as sound as you
can' in miserable Java...
We could generate a warning if the user do not annotate with @PostSet
all setters, where @PostSet() would just silent the annotation.
There are so many more warnings we could design and discuss, but since
you can not do it 'right' anyway.. more warnings would just make the
user that prevent them more 'confident' that is 'guaranteed
correct'....
Ideas?
Marco.