I agree -- I prefer to keep things open, too. Somehow I didn't even
think about those when I wrote my last mail, in many ways 'final' is
evil just for having too many meanings. I think it's the cult of having
less keywords that C++ created -- was it 'virtual' or 'const' that won
the price for the most meanings there?

  Peter



On Sun, 2009-02-15 at 07:28 +0100, Alexander Snaps wrote:
> I don't think a class should be marked final except if there is good
> reason for doing so...
> As for the rest I usually don't see much value in doing it. Though if
> the project adopts it as a coding standard, why not. I'll just code
> consistent with the style. Though it doesn't add much value IMHO.
> Alex
> 
> On 2/15/09, Reinier Zwitserloot <[email protected]> wrote:
> >
> > And when we need to make another modification, we.... rename the
> > parameter to 'reallyOldConfigKey'?
> >
> > Peter: Me too, I spread final all over the place. on classes, on
> > attributes, on methods.
> >
> > The only place where I rarely use it is for method locals :P
> >
> > While immutability would be great, what's really the key modifier is
> > 'Side-Effect-Free'. Immutability is not well defined in practice. SEF
> > is mostly well defined in practice (with exceptions where you really
> > want to force it for e.g. logging, which seems like a side-effect but
> > ought to be considered SEF). For example:
> >
> > Your class has all-final fields, and each field's type is neccessarily
> > immutable (primitive, or a final class that is itself immutable).
> > There is a static map (irrelevant for object's mutable/immutable
> > state) that binds instances of this class to a String. The object uses
> > this to sneakily be fake mutable. In fact, is an instance of this
> > class an immutable in the first place?
> >
> > What about something like java.io.File, which is immutable (final and
> > all its internal state never changes), but you can call things that
> > mutate stuff on it, stuff that is generally considered to be part of
> > the state of files, such as deleting them, creating them, etcetera.
> >
> >
> > Side-Effect-Free avoids these hairy issues. You do need ways to say: I
> > know this LOOKS like a side-effect, but consider it SEF. For example,
> > logging. It would be completely unusable if the act of logging forces
> > you to declare a method call SEF.
> >
> > You can also define an object as utterly safe and entirely memoizable
> > if it contains only SEF methods and all its fields are final, and of
> > safe types. This is a very useful distinction.
> >
> >
> > APT processing might actually allow you to get somewhere with this,
> > with annotations that allow you to specify intent (e.g.: This method
> > is supposed to be SEF, so if it isn't, warn or error), and some
> > serious class introspection. It would definitely help if you cached
> > the SEF state of core java library calls (e.g. cache that after some
> > analysis, you determine that calling string.toLowerCase() is
> > harmless).
> >
> >
> > On Feb 14, 7:43 pm, Robert Fischer <[email protected]>
> > wrote:
> >> You're right -- I don't like the academic discussion of "final", because
> >> it's in practicalities
> >> where "final" really shows its power.
> >>
> >> Comments intermingled below.
> >>
> >>
> >>
> >> Reinier Zwitserloot wrote:
> >> > If we allow modification in the pre-amble, this is easy, bordering on
> >> > the trivial (lines //V2 have been added/modified in the update):
> >>
> >> > public List<ConfigDirectives> readConfig(String configKey) {
> >> >     configKey = translateOldKeyNames(configKey); //V2
> >>
> >> >     try {
> >> >         Logger.get(this.getClas()).log("Request for config file: " +
> >> > configKey);
> >> >         return readConfigDirectivesFromDisk(new FileInputStream
> >> > ("configfiles/" + configKey + ".cfg"));
> >> >     } catch ( FileNotFoundException e ) {
> >> >         return Collections.emptyList();
> >> >     }
> >> > }
> >>
> >> > The one doing the editing really could get away with not even looking
> >> > at what the actual body of the method does. Nice.
> >>
> >> > Now lets try with your rule:
> >>
> >> > Urgh. We can't.
> >>
> >> Really?  What about this?
> >>
> >> public List<ConfigDirectives> readConfig(final String oldConfigKey) {
> >>      final String configKey = translateOldKeyNames(configKey); //V2.1
> >>
> >>      try {
> >>          Logger.get(this.getClas()).log("Request for config file: " +
> >> configKey);
> >>          return readConfigDirectivesFromDisk(new FileInputStream
> >> ("configfiles/" + configKey + ".cfg"));
> >>      } catch ( FileNotFoundException e ) {
> >>          return Collections.emptyList();
> >>      }
> >>
> >> }
> >>
> >> That's a simple, easily makable, and readable change.  In fact, now I've
> >> got the original version
> >> still kicking around (in case I want it later), and I've got the
> >> translated version -- which is
> >> really semantically different than "configKey" in the previous version --
> >> automatically being used.
> >>
> >> I'm pretty sure that change meets all your criteria.
> >>
> >> > The optimal way to solve this one in a functional view of the world is
> >> > to first create a new variable (keyNormalized or something), and then
> >> > UNDEFINE the old one. This way anyone that tries to use the original
> >> > gets an error which should quickly lead to him or her coming up with
> >> > the right solution (either use the normalized version or create a new
> >> > paramRaw variable to make it abundantly clear what's happening).
> >> > However, java doesn't support that.
> >>
> >> I just did it.  Now, I didn't undefine the old variable, but I also don't
> >> see how undefining the
> >> variable is a part of the "the optimal way to solve this one in a
> >> functional view of the world".
> >> Sure, it's common to build up structures like:
> >>
> >> let foo = "f" in
> >> let foo = foo + "o" in
> >> let foo = foo + "o" in ...
> >>
> >> But that's more a hack around immutability than part of the functional
> >> view of the world.  Insofar
> >> as that code can be conceived of as functional, this would be just as
> >> functional:
> >>
> >> let f = "f" in
> >> let fo = f + "o" in
> >> let foo = fo + "o" in ...
> >>
> >>
> >>
> >> > Hence, my theory is: In anything but the most trivial of examples,
> >> > inlining the transformation as you did in your myConcat method, is a
> >> > bad thing more often than it being a good thing. Yes, there was a typo
> >> > in your code (double 'left'), but I found that utterly unconvincing,
> >> > because this typo is exactly as likely in your 'correct' method:
> >>
> >> > String myConcat(final String left, final String right) {
> >> >    if ( left == null ) return myConcat("", left);
> >> >    if ( right == null ) return myConcat(left, "");
> >> >    return left + right;
> >> > }
> >>
> >> We're now back into the academic, but since we're arguing what types of
> >> errors are more likely, I'd
> >> argue that an alarm bell is more likely to ring when you're putting a
> >> variable named "left" into the
> >> right side of an argument list as opposed to accidentally assigning the
> >> wrong variable.  So this
> >> error case is less likely than the other.
> >>
> >> Even if it's "just as likely", you're still not demonstrating the grievous
> >> harm (or whatever) that
> >> "final" apparently does.
> >>
> >> ~~ Robert Fischer.
> >> Grails Training        http://GroovyMag.com/training
> >> Smokejumper Consultinghttp://SmokejumperIT.com
> >> Enfranchised Mind Bloghttp://EnfranchisedMind.com/blog
> >>
> >> Check out my book, "Grails Persistence with GORM and
> >> GSQL"!http://www.smokejumperit.com/redirect.html
> > >
> >
> 
> 


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "The 
Java Posse" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/javaposse?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to