Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.java.programmer > #26511 > unrolled thread

Fixing "typos" in enums...

Started byAndreas Leitgeb <avl@gamma.logic.tuwien.ac.at>
First post2013-11-15 16:25 +0000
Last post2013-11-19 11:14 +0000
Articles 20 on this page of 21 — 7 participants

Back to article view | Back to comp.lang.java.programmer


Contents

  Fixing "typos" in enums... Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> - 2013-11-15 16:25 +0000
    Re: Fixing "typos" in enums... markspace <markspace@nospam.nospam> - 2013-11-15 09:05 -0800
      Re: Fixing "typos" in enums... Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> - 2013-11-18 17:20 +0000
        Re: Fixing "typos" in enums... markspace <markspace@nospam.nospam> - 2013-11-18 09:33 -0800
          Re: Fixing "typos" in enums... Eric Sosman <esosman@comcast-dot-net.invalid> - 2013-11-18 13:37 -0500
          Re: Fixing "typos" in enums... Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> - 2013-11-18 18:58 +0000
            Re: Fixing "typos" in enums... markspace <markspace@nospam.nospam> - 2013-11-18 11:35 -0800
              Re: Fixing "typos" in enums... Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> - 2013-11-18 20:34 +0000
    Re: Fixing "typos" in enums... Robert Klemme <shortcutter@googlemail.com> - 2013-11-15 20:10 +0100
      Re: Fixing "typos" in enums... Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> - 2013-11-18 17:29 +0000
        Re: Fixing "typos" in enums... Robert Klemme <shortcutter@googlemail.com> - 2013-11-18 19:38 +0100
          Re: Fixing "typos" in enums... Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> - 2013-11-18 19:34 +0000
    Re: Fixing "typos" in enums... Jan Burse <janburse@fastmail.fm> - 2013-11-16 10:16 +0100
      Re: Fixing "typos" in enums... Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> - 2013-11-18 18:25 +0000
        Re: Fixing "typos" in enums... Eric Sosman <esosman@comcast-dot-net.invalid> - 2013-11-18 13:45 -0500
          Re: Fixing "typos" in enums... Robert Klemme <shortcutter@googlemail.com> - 2013-11-18 20:20 +0100
          Re: Fixing "typos" in enums... Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> - 2013-11-18 20:09 +0000
            Re: Fixing "typos" in enums... Eric Sosman <esosman@comcast-dot-net.invalid> - 2013-11-18 17:00 -0500
              Re: Fixing "typos" in enums... Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> - 2013-11-19 15:39 +0000
    Re: Fixing "typos" in enums... Arivald <NOSPAMarivald@interia.pl> - 2013-11-19 00:29 +0100
      Re: Fixing "typos" in enums... lipska the kat <"lipskathekat at yahoo dot co dot uk"> - 2013-11-19 11:14 +0000

Page 1 of 2  [1] 2  Next page →


#26511 — Fixing "typos" in enums...

FromAndreas Leitgeb <avl@gamma.logic.tuwien.ac.at>
Date2013-11-15 16:25 +0000
SubjectFixing "typos" in enums...
Message-ID<slrnl8cing.mol.avl@gamma.logic.tuwien.ac.at>
Let's assume, some non native English speaker writes up
a library, that's really useful and gaining broader use.

Now, the author may have once caught up some misspelling
of a common word (like e.g. thinking that "first" was 
spelled "furst" and that with a confidence level ways
above "I'd better look this up").

Eventually this misspelling goes into an enum constant,
and by the time the first user reports it, the library
is already too much in use to lightheartedly apply
Plan "A" (namely fixing the typo and thereby inducing a
compatibility issue)

Now, Plan B could be to rename the enum constant, but add
a public static field by the old bad name (initialized 
with the reference to the spelling-corrected field), to
alleviate the compatibility issue at least for those who
merely used the enum's field's name in their code.

 // public enum Foo { FURST, SECOND }
 public enum Foo { FIRST, SECOND; public static final FURST = FIRST; }

Any user having done a switch over that enum will still
need to modify his code. Ditto anyone doing string comparisons
on foo.name(), but that is most probably a bad idea, anyway.

I'd further denote "Just leave the typo in" as "Plan *Z*",
and ask for better strategies. (at least better than Plan Z)

PS: I vaguely remember that even Sun Java had some typos in its
  API, but that predated enums, so adding a second constant with
  same value but corrected name was a triviality back then...

PPS: a similar problem could arise with misspelled class names,
  but that's not currently in my focus.

[toc] | [next] | [standalone]


#26512

Frommarkspace <markspace@nospam.nospam>
Date2013-11-15 09:05 -0800
Message-ID<l65k8a$t2d$1@dont-email.me>
In reply to#26511
On 11/15/2013 8:25 AM, Andreas Leitgeb wrote:

>   @Deprecated public enum Foo { FURST, SECOND }

>   public enum Fooing { FIRST, SECOND }
>

[toc] | [prev] | [next] | [standalone]


#26536

FromAndreas Leitgeb <avl@gamma.logic.tuwien.ac.at>
Date2013-11-18 17:20 +0000
Message-ID<slrnl8kj3g.42s.avl@gamma.logic.tuwien.ac.at>
In reply to#26512
markspace <markspace@nospam.nospam> wrote:
> On 11/15/2013 8:25 AM, Andreas Leitgeb wrote:
>>   @Deprecated public enum Foo { FURST, SECOND }
>>   public enum Fooing { FIRST, SECOND }

This solution would require duplicating lots of other
code, like methods taking that enum as parameter...

Also, in my case at hand the enum itself already has the
one and only correct name for that task (and it's of course
not really "Foo"). Giving it a different name would be like
replacing one misnomer by another misnomer ;-)

Anyway, thanks for the suggestion. In other situations it
might be just the right thing to do.

[toc] | [prev] | [next] | [standalone]


#26538

Frommarkspace <markspace@nospam.nospam>
Date2013-11-18 09:33 -0800
Message-ID<l6dj1q$nin$1@dont-email.me>
In reply to#26536
On 11/18/2013 9:20 AM, Andreas Leitgeb wrote:
> markspace <markspace@nospam.nospam> wrote:
>> On 11/15/2013 8:25 AM, Andreas Leitgeb wrote:
>>>    @Deprecated public enum Foo { FURST, SECOND }
>>>    public enum Fooing { FIRST, SECOND }
>
> This solution would require duplicating lots of other
> code, like methods taking that enum as parameter...

So you change the old method to a new method that takes the new type. 
It's called refactoring.  You don't duplicate methods, that's dumb.

>
> Also, in my case at hand the enum itself already has the
> one and only correct name for that task (and it's of course

I dislike adding a "2" onto new interface names, so I showed that coming 
up with a new name is better.  I'm sure if you really think about it, 
you can come up with a new name.  So far in the Java API, we've had 
Date, Calendar and now LocalDateTime to all mean essentially the same 
thing.  A little creativity and thought is required.


[toc] | [prev] | [next] | [standalone]


#26540

FromEric Sosman <esosman@comcast-dot-net.invalid>
Date2013-11-18 13:37 -0500
Message-ID<l6dmod$fb4$1@dont-email.me>
In reply to#26538
On 11/18/2013 12:33 PM, markspace wrote:
> On 11/18/2013 9:20 AM, Andreas Leitgeb wrote:
>> markspace <markspace@nospam.nospam> wrote:
>>> On 11/15/2013 8:25 AM, Andreas Leitgeb wrote:
>>>>    @Deprecated public enum Foo { FURST, SECOND }
>>>>    public enum Fooing { FIRST, SECOND }
>>
>> This solution would require duplicating lots of other
>> code, like methods taking that enum as parameter...
>
> So you change the old method to a new method that takes the new type.
> It's called refactoring.  You don't duplicate methods, that's dumb.

     If you change the method signatures, haven't you already
given up on backwards compatibility?  And if you're willing to
sacrifice compatibility, why not just fix the damn' typo and
break for lunch?

-- 
Eric Sosman
esosman@comcast-dot-net.invalid

[toc] | [prev] | [next] | [standalone]


#26543

FromAndreas Leitgeb <avl@gamma.logic.tuwien.ac.at>
Date2013-11-18 18:58 +0000
Message-ID<slrnl8kops.42s.avl@gamma.logic.tuwien.ac.at>
In reply to#26538
markspace <markspace@nospam.nospam> wrote:
> On 11/18/2013 9:20 AM, Andreas Leitgeb wrote:
>> markspace <markspace@nospam.nospam> wrote:
>>> On 11/15/2013 8:25 AM, Andreas Leitgeb wrote:
>>>>    @Deprecated public enum Foo { FURST, SECOND }
>>>>    public enum Fooing { FIRST, SECOND }
>> This solution would require duplicating lots of other
>> code, like methods taking that enum as parameter...
> So you change the old method to a new method that takes the new type. 
> It's called refactoring.  You don't duplicate methods, that's dumb.

Not quite as simple. I'd need a *copy* of each method (even as an
overload) taking the new Fooing, while the original would be
changed to @Deprecated and left at taking the Foo argument.

  @Deprecated void applyRank(Foo rank) { ... blah ... }
  void applyRank(Fooing rank) { ... mostly the same blah ... }

>> Also, in my case at hand the enum itself already has the
>> one and only correct name for that task (and it's of course
> I dislike adding a "2" onto new interface names, so I showed that coming 
> up with a new name is better.  I'm sure if you really think about it, 
> you can come up with a new name.  So far in the Java API, we've had 
> Date, Calendar and now LocalDateTime to all mean essentially the same 
> thing.  A little creativity and thought is required.

We learn from history, that alternatives for canonical names 
always get an "Ex" appended... ;)  At least, it is then obvious,
which is the older and which the newer...  (otoh, consider a
fix for some Color class being called Colour ;-)

[toc] | [prev] | [next] | [standalone]


#26546

Frommarkspace <markspace@nospam.nospam>
Date2013-11-18 11:35 -0800
Message-ID<l6dq60$5v8$1@dont-email.me>
In reply to#26543
On 11/18/2013 10:58 AM, Andreas Leitgeb wrote:
> Not quite as simple. I'd need a *copy* of each method (even as an
> overload) taking the new Fooing, while the original would be
> changed to @Deprecated and left at taking the Foo argument.
>
>    @Deprecated void applyRank(Foo rank) { ... blah ... }
>    void applyRank(Fooing rank) { ... mostly the same blah ... }

OK I see what you mean.  You'd have to duplicate your own API everywhere 
for the new type.  Maybe

public enum Foo { @Deprecated FURST, SECOND, FIRST }

public void applyRank( Foo rank ) {
   if( rank == FIRST || rank == FURST )
      //...
   else
      // second ...

Which I think you will have to do with your solution as well.

My previous solutions allows you to migrate the entire API to the new 
type.  Yours allows you to keep the old type.  I think you're stuck with 
"FURST" forever though if you keep the old type.

[toc] | [prev] | [next] | [standalone]


#26548

FromAndreas Leitgeb <avl@gamma.logic.tuwien.ac.at>
Date2013-11-18 20:34 +0000
Message-ID<slrnl8kufc.42s.avl@gamma.logic.tuwien.ac.at>
In reply to#26546
markspace <markspace@nospam.nospam> wrote:
> On 11/18/2013 10:58 AM, Andreas Leitgeb wrote:
>> Not quite as simple. I'd need a *copy* of each method (even as an
>> overload) taking the new Fooing, while the original would be
>> changed to @Deprecated and left at taking the Foo argument.
>>    @Deprecated void applyRank(Foo rank) { ... blah ... }
>>    void applyRank(Fooing rank) { ... mostly the same blah ... }
> OK I see what you mean.  You'd have to duplicate your own API everywhere 
> for the new type.  Maybe
>
> public enum Foo { @Deprecated FURST, SECOND, FIRST }
>
> public void applyRank( Foo rank ) {
>    if( rank == FIRST || rank == FURST )
>       //...
>    else
>       // second ...
>
> Which I think you will have to do with your solution as well.

Not with the "extra-static-final-field" approach.
As my FIRST and FURST would both refer to the identical instance,
there'd be no need to check equality with both of them. Instead,
comparing equality with *either* of them does the job in this
case, which is nice w.r.t compatibility (but not sufficient overall).

> My previous solutions allows you to migrate the entire API to the new 
> type.  Yours allows you to keep the old type.  I think you're stuck with 
> "FURST" forever though if you keep the old type.

You're right, that the transition would be more smooth for the users your
way (not counting the discomfort of a less than canonically named enum).

In my approach, I might start with creating the extra field with
the corrected name, and leave the constant as is, allowing simple
users (who just use the constants directly) to change their code to
Foo.FIRST immediately, but those who use Foo more intensely will have
to adapt their program in sync with a future library upgrade that will
eventually swap FURST and FIRST.

[toc] | [prev] | [next] | [standalone]


#26514

FromRobert Klemme <shortcutter@googlemail.com>
Date2013-11-15 20:10 +0100
Message-ID<ben9u0FeoueU1@mid.individual.net>
In reply to#26511
On 15.11.2013 17:25, Andreas Leitgeb wrote:
> Let's assume, some non native English speaker writes up
> a library, that's really useful and gaining broader use.

> Eventually this misspelling goes into an enum constant,
> and by the time the first user reports it, the library
> is already too much in use to lightheartedly apply
> Plan "A" (namely fixing the typo and thereby inducing a
> compatibility issue)
>
> Now, Plan B could be to rename the enum constant, but add
> a public static field by the old bad name (initialized
> with the reference to the spelling-corrected field), to
> alleviate the compatibility issue at least for those who
> merely used the enum's field's name in their code.
>
>   // public enum Foo { FURST, SECOND }
>   public enum Foo { FIRST, SECOND; public static final FURST = FIRST; }
>
> Any user having done a switch over that enum will still
> need to modify his code. Ditto anyone doing string comparisons
> on foo.name(), but that is most probably a bad idea, anyway.

Not at all: a String could be read from some configuration file or 
database and then the corresponding enum value searched via valueOf() or 
values().

Another issue: serialized values.  You might be able to remedy that via 
the deserialization callbacks.  This is at least something that needs to 
be checked.

Even if certain practices are "bad ideas": they are applied nevertheless.

> PPS: a similar problem could arise with misspelled class names,
>    but that's not currently in my focus.

A published API is basically set in stone.  Keeping the wrong value 
might actually be the best option.

Cheers

	robert

-- 
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

[toc] | [prev] | [next] | [standalone]


#26537

FromAndreas Leitgeb <avl@gamma.logic.tuwien.ac.at>
Date2013-11-18 17:29 +0000
Message-ID<slrnl8kjkk.42s.avl@gamma.logic.tuwien.ac.at>
In reply to#26514
Robert Klemme <shortcutter@googlemail.com> wrote:
>>   // public enum Foo { FURST, SECOND }
>>   public enum Foo { FIRST, SECOND; public static final FURST = FIRST; }
>> Any user having done a switch over that enum will still
>> need to modify his code. Ditto anyone doing string comparisons
>> on foo.name(), but that is most probably a bad idea, anyway.

> Not at all: a String could be read from some configuration file or 
> database and then the corresponding enum value searched via valueOf() or 
> values().

Fair enough. De-serialization from some persistent storage sure is
a legit task, that would suffer from such an API-change.

Basic Object-(de)serialization would be less of a problem, as that is
already specified as unsuitable for long-time storage.

> A published API is basically set in stone.  Keeping the wrong value 
> might actually be the best option.

I just don't yet want to accept it, even though I can't refute it. ;-)

[toc] | [prev] | [next] | [standalone]


#26541

FromRobert Klemme <shortcutter@googlemail.com>
Date2013-11-18 19:38 +0100
Message-ID<bev54gF3iq5U1@mid.individual.net>
In reply to#26537
On 18.11.2013 18:29, Andreas Leitgeb wrote:
> Robert Klemme <shortcutter@googlemail.com> wrote:
>>>    // public enum Foo { FURST, SECOND }
>>>    public enum Foo { FIRST, SECOND; public static final FURST = FIRST; }
>>> Any user having done a switch over that enum will still
>>> need to modify his code. Ditto anyone doing string comparisons
>>> on foo.name(), but that is most probably a bad idea, anyway.
>
>> Not at all: a String could be read from some configuration file or
>> database and then the corresponding enum value searched via valueOf() or
>> values().
>
> Fair enough. De-serialization from some persistent storage sure is
> a legit task, that would suffer from such an API-change.
>
> Basic Object-(de)serialization would be less of a problem, as that is
> already specified as unsuitable for long-time storage.

Well, but it *can* be used for that purpose which means it *will* be. 
And telling them "it's your fault" is often not a good option as there 
can be numerous ugly ways that can backfire...

>> A published API is basically set in stone.  Keeping the wrong value
>> might actually be the best option.
>
> I just don't yet want to accept it, even though I can't refute it. ;-)

:-)  At the university we had a lecture about exactly this kind of 
problem and other issues specific to API changes in OO languages. 
Unfortunately I neither remember the professor's nor the lecture's name 
to dig up some pointers.  What I took away was that sentence ("...set in 
stone") and that there is quite a number of surprising and subtle ways 
failure can be caused by API changes.  That had two effects: it made me 
think thrice whenever I am tempted to change an API; and I try to give 
extra thought whenever I am designing an API (not only the public ones 
as often all of a sudden what has been private becomes public).

Kind regards

	robert

-- 
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

[toc] | [prev] | [next] | [standalone]


#26545

FromAndreas Leitgeb <avl@gamma.logic.tuwien.ac.at>
Date2013-11-18 19:34 +0000
Message-ID<slrnl8kquu.42s.avl@gamma.logic.tuwien.ac.at>
In reply to#26541
Robert Klemme <shortcutter@googlemail.com> wrote:
> On 18.11.2013 18:29, Andreas Leitgeb wrote:
>> Fair enough. De-serialization from some persistent storage sure is
>> a legit task, that would suffer from such an API-change.
>> Basic Object-(de)serialization would be less of a problem, as that is
>> already specified as unsuitable for long-time storage.
> Well, but it *can* be used for that purpose which means it *will* be. 

Picking some Enum from the JLS (awt): java.awt.Dialog.ModalityType:
typically used as a parameter to some method(or c'tor) in order to
specify a certain behaviour for some object.

Normal applications using it, will most likely merely name such a
constant upon construction of a Dialog. 

Then there might be some GUI-Construction tool, that needs to save
options used with Dialogs, but they're more likely to closely follow
development of the library and just release an update with a manual
re-mapping of that one word upon loading back old files. (and they
might even be happy about the change for no longer receiving bug-
reports about what their users may believe to be their typo.)

The enum that triggered my OP was of quite a similar usage pattern.

Considerations of 99%-uses versus 1%-uses may be relevant for the
decision on whether to accept an incompatible change or not - at
least at some major-version bump time...

> [...] What I took away was that sentence ("...set in 
> stone") and that there is quite a number of surprising and subtle ways 
> failure can be caused by API changes.  That had two effects: it made me 
> think thrice whenever I am tempted to change an API; and I try to give 
> extra thought whenever I am designing an API (not only the public ones 
> as often all of a sudden what has been private becomes public).

yeah, yeah, avoiding mistakes in the furst(*) place is always best.

(*) ;-)

[toc] | [prev] | [next] | [standalone]


#26517

FromJan Burse <janburse@fastmail.fm>
Date2013-11-16 10:16 +0100
Message-ID<l67d4o$7bl$1@news.albasani.net>
In reply to#26511
Andreas Leitgeb schrieb:
>   // public enum Foo { FURST, SECOND }
>   public enum Foo { FIRST, SECOND; public static final FURST = FIRST; }

Maybe mark FURST also as deprecated.
And put a comment that says what should
be used instead of FURST, which could
go into javadoc.

And of course replacing FURST by FIRST
shouldn't be an issue when your project
and the clients of your project are in
the reach of refactoring tools. But yes
for public APIs, this is annoying.

In as far APIs behave similar as natural
language since for whatever reason synonyms
develop, and even word meanings disappear
over the time. Overloading of methods even
allows a form of polysemy.

Bye

[toc] | [prev] | [next] | [standalone]


#26539

FromAndreas Leitgeb <avl@gamma.logic.tuwien.ac.at>
Date2013-11-18 18:25 +0000
Message-ID<slrnl8kmsm.42s.avl@gamma.logic.tuwien.ac.at>
In reply to#26517
Jan Burse <janburse@fastmail.fm> wrote:
> Andreas Leitgeb schrieb:
>>   // public enum Foo { FURST, SECOND }
>>   public enum Foo { FIRST, SECOND; public static final FURST = FIRST; }
>
> Maybe mark FURST also as deprecated.
> And put a comment that says what should
> be used instead of FURST, which could
> go into javadoc.

Definitely a good idea, which I forgot about. Thanks for reminding!

> In as far APIs behave similar as natural
> language since for whatever reason synonyms
> develop, and even word meanings disappear
> over the time. Overloading of methods even
> allows a form of polysemy.

It would be nice, if enum had the concept of synonyms:
<dream-mode>
  - each synonym is an alias for a particular constant
  - synonyms would be recognized by valueOf(String)
  - synonyms could be annotated as @Deprecated
  - synonyms could be used in a switch, but then the
      canonical name (or any other synonym for the same
      constant) must not be used in the same switch.
</dream-mode>
Well, I know it's not going to happen. Just wanted it off my chest ;-)

[toc] | [prev] | [next] | [standalone]


#26542

FromEric Sosman <esosman@comcast-dot-net.invalid>
Date2013-11-18 13:45 -0500
Message-ID<l6dn7i$i9a$1@dont-email.me>
In reply to#26539
On 11/18/2013 1:25 PM, Andreas Leitgeb wrote:
> Jan Burse <janburse@fastmail.fm> wrote:
>> Andreas Leitgeb schrieb:
>>>    // public enum Foo { FURST, SECOND }
>>>    public enum Foo { FIRST, SECOND; public static final FURST = FIRST; }
>>
>> Maybe mark FURST also as deprecated.
>> And put a comment that says what should
>> be used instead of FURST, which could
>> go into javadoc.
>
> Definitely a good idea, which I forgot about. Thanks for reminding!
>
>> In as far APIs behave similar as natural
>> language since for whatever reason synonyms
>> develop, and even word meanings disappear
>> over the time. Overloading of methods even
>> allows a form of polysemy.
>
> It would be nice, if enum had the concept of synonyms:
> <dream-mode>
>    - each synonym is an alias for a particular constant
>    - synonyms would be recognized by valueOf(String)
>    - synonyms could be annotated as @Deprecated
>    - synonyms could be used in a switch, but then the
>        canonical name (or any other synonym for the same
>        constant) must not be used in the same switch.
> </dream-mode>
> Well, I know it's not going to happen. Just wanted it off my chest ;-)

     It'd make a mess of EnumMaps, too ...

     I don't think there's any single Right Way to address your
problem, no one-size-fits-all solution.  Elsethread it's written
that a published API is "set in stone," but there are many kinds
of stone.  Of all posters to this thread, only you know whether
the stone is obsidian or talc; only you know how hard a tool is
required to scratch it.

-- 
Eric Sosman
esosman@comcast-dot-net.invalid

[toc] | [prev] | [next] | [standalone]


#26544

FromRobert Klemme <shortcutter@googlemail.com>
Date2013-11-18 20:20 +0100
Message-ID<bev7keF42qiU1@mid.individual.net>
In reply to#26542
On 18.11.2013 19:45, Eric Sosman wrote:

>      I don't think there's any single Right Way to address your
> problem, no one-size-fits-all solution.  Elsethread it's written
> that a published API is "set in stone," but there are many kinds
> of stone.  Of all posters to this thread, only you know whether
> the stone is obsidian or talc; only you know how hard a tool is
> required to scratch it.

I like that analogy with the different kinds of stone.  That fits really 
well here.

Cheers

	robert


-- 
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

[toc] | [prev] | [next] | [standalone]


#26547

FromAndreas Leitgeb <avl@gamma.logic.tuwien.ac.at>
Date2013-11-18 20:09 +0000
Message-ID<slrnl8ksvr.42s.avl@gamma.logic.tuwien.ac.at>
In reply to#26542
Eric Sosman <esosman@comcast-dot-net.invalid> wrote:
> On 11/18/2013 1:25 PM, Andreas Leitgeb wrote:
>> It would be nice, if enum had the concept of synonyms:
>> <dream-mode>
>>    - each synonym is an alias for a particular constant
>>    - synonyms would be recognized by valueOf(String)
>>    - synonyms could be annotated as @Deprecated
>>    - synonyms could be used in a switch, but then the
>>        canonical name (or any other synonym for the same
>>        constant) must not be used in the same switch.
>> </dream-mode>
>> Well, I know it's not going to happen. Just wanted it off my chest ;-)
> It'd make a mess of EnumMaps, too ...

Nope, don't see what you mean here.  The synonyms wouldn't be
separate extra instances, of course, so by the time I'm holding
an instance, its .name() is the canonical one.
Also, if "C" is a canonical constant of enum Foo, and "S" a
synonym of "C" in Foo, then (Foo.S==Foo.C) would be true.

Part of that "extension" can be mimicked by creating a static
final field in the enum by synonym's name initialized to its
canonical meaning.

Maybe valueOf() for a particular enum could be patched by
means of bytecode "instrumentation" to fall back to some
HashMap<String,Foo> of synonyms, if canonical name lookup
fails. Not sure, if the bytecode verifier would accept
thusly patched valueOf() implementations upon loading
Foo.class

Unfortunately, it is not feasible to hook into the compiler
to make it accept arbitrary static final fields of the enum
as switch case-labels.

>      I don't think there's any single Right Way to address your
> problem, no one-size-fits-all solution.  Elsethread it's written
> that a published API is "set in stone," but there are many kinds
> of stone.  Of all posters to this thread, only you know whether
> the stone is obsidian or talc; only you know how hard a tool is
> required to scratch it.

Nice parable :)  Yep, there's some material analysis ahead.

[toc] | [prev] | [next] | [standalone]


#26549

FromEric Sosman <esosman@comcast-dot-net.invalid>
Date2013-11-18 17:00 -0500
Message-ID<l6e2mo$tla$1@dont-email.me>
In reply to#26547
On 11/18/2013 3:09 PM, Andreas Leitgeb wrote:
> Eric Sosman <esosman@comcast-dot-net.invalid> wrote:
>> On 11/18/2013 1:25 PM, Andreas Leitgeb wrote:
>>> It would be nice, if enum had the concept of synonyms:
>>> <dream-mode>
>>>     - each synonym is an alias for a particular constant
>>>     - synonyms would be recognized by valueOf(String)
>>>     - synonyms could be annotated as @Deprecated
>>>     - synonyms could be used in a switch, but then the
>>>         canonical name (or any other synonym for the same
>>>         constant) must not be used in the same switch.
>>> </dream-mode>
>>> Well, I know it's not going to happen. Just wanted it off my chest ;-)
>> It'd make a mess of EnumMaps, too ...
>
> Nope, don't see what you mean here.  The synonyms wouldn't be
> separate extra instances, of course, so by the time I'm holding
> an instance, its .name() is the canonical one.
> Also, if "C" is a canonical constant of enum Foo, and "S" a
> synonym of "C" in Foo, then (Foo.S==Foo.C) would be true.

     Sorry; I didn't pay close enough attention to the details
of your dream.  :)  Still, you've got to admit it might be a
wee bit confusing if you did

	theMap.clear();
	assert theMap.size() == 0;  // Okay, it's empty.
	theMap.put(Foo.C, "FIRST");
	assert theMap.size() == 1;  // Okay, one mapping.
	theMap.put(Foo.S, "FURST");
	assert theMap.size() == 2;  // Why does this fail???

>>       I don't think there's any single Right Way to address your
>> problem, no one-size-fits-all solution.  Elsethread it's written
>> that a published API is "set in stone," but there are many kinds
>> of stone.  Of all posters to this thread, only you know whether
>> the stone is obsidian or talc; only you know how hard a tool is
>> required to scratch it.
>
> Nice parable :)  Yep, there's some material analysis ahead.

     Perhaps a trifle over-poetic, but there's serious intent.
There'll be some amount of pain no matter which route you take,
and you're better able to assess it than any of us is.

-- 
Eric Sosman
esosman@comcast-dot-net.invalid

[toc] | [prev] | [next] | [standalone]


#26552

FromAndreas Leitgeb <avl@gamma.logic.tuwien.ac.at>
Date2013-11-19 15:39 +0000
Message-ID<slrnl8n1hr.42s.avl@gamma.logic.tuwien.ac.at>
In reply to#26549
Eric Sosman <esosman@comcast-dot-net.invalid> wrote:
> On 11/18/2013 3:09 PM, Andreas Leitgeb wrote:
>> Eric Sosman <esosman@comcast-dot-net.invalid> wrote:
>>> On 11/18/2013 1:25 PM, Andreas Leitgeb wrote:
>>>> It would be nice, if enum had the concept of synonyms:
>>>> <dream-mode>
>>>>     - each synonym is an alias for a particular constant
>>>>     - synonyms would be recognized by valueOf(String)
>>>>     - synonyms could be annotated as @Deprecated
>>>>     - synonyms could be used in a switch, but then the
>>>>         canonical name (or any other synonym for the same
>>>>         constant) must not be used in the same switch.
>>>> </dream-mode>
>>>> Well, I know it's not going to happen. Just wanted it off my chest ;-)
>>> It'd make a mess of EnumMaps, too ...
>> Nope, don't see what you mean here.  The synonyms wouldn't be
>> separate extra instances, of course, so by the time I'm holding
>> an instance, its .name() is the canonical one.
>> Also, if "C" is a canonical constant of enum Foo, and "S" a
>> synonym of "C" in Foo, then (Foo.S==Foo.C) would be true.
>      Sorry; I didn't pay close enough attention to the details
> of your dream.  :)  Still, you've got to admit it might be a
> wee bit confusing if you did
>
> 	theMap.clear();
> 	assert theMap.size() == 0;  // Okay, it's empty.
> 	theMap.put(Foo.C, "FIRST");
> 	assert theMap.size() == 1;  // Okay, one mapping.
> 	theMap.put(Foo.S, "FURST");
> 	assert theMap.size() == 2;  // Why does this fail???

This would be true, only if that "feature" got explicitly misused.
(The mere possibility of misuse is often taken as an argument
against a feature, but I don't follow this logic, myself)

Putting it into context of corrected spellings, then it would
look more like this one:

	theMap.clear();
	assert theMap.size() == 0;  // Okay, it's empty.
	theMap.put(Foo.SUPERCALIFRAGILISTICEXPIALID0CIOUS, "1st");
	assert theMap.size() == 1;  // Okay, one mapping.
	theMap.put(Foo.SUPERCALIFRAGILISTICEXPIALIDOCIOUS, "1st");
and the resulting size()==1 would be far less surprising.

Of course, no one would write such code, short of for trolling...
Normal code would contain only one variant. Mixtures would only
happen where a transition has been begun but not (yet) completed.

[toc] | [prev] | [next] | [standalone]


#26550

FromArivald <NOSPAMarivald@interia.pl>
Date2013-11-19 00:29 +0100
Message-ID<l6e7t9$b60$1@news.dialog.net.pl>
In reply to#26511
W dniu 2013-11-15 17:25, Andreas Leitgeb pisze:
> Let's assume, some non native English speaker writes up
> a library, that's really useful and gaining broader use.
>
> Now, the author may have once caught up some misspelling
> of a common word (like e.g. thinking that "first" was
> spelled "furst" and that with a confidence level ways
> above "I'd better look this up").
>
> Eventually this misspelling goes into an enum constant,
> and by the time the first user reports it, the library
> is already too much in use to lightheartedly apply
> Plan "A" (namely fixing the typo and thereby inducing a
> compatibility issue)
>
> Now, Plan B could be to rename the enum constant, but add
> a public static field by the old bad name (initialized
> with the reference to the spelling-corrected field), to
> alleviate the compatibility issue at least for those who
> merely used the enum's field's name in their code.
>
>   // public enum Foo { FURST, SECOND }
>   public enum Foo { FIRST, SECOND; public static final FURST = FIRST; }
>
> Any user having done a switch over that enum will still
> need to modify his code. Ditto anyone doing string comparisons
> on foo.name(), but that is most probably a bad idea, anyway.
>
> I'd further denote "Just leave the typo in" as "Plan *Z*",
> and ask for better strategies. (at least better than Plan Z)
>
> PS: I vaguely remember that even Sun Java had some typos in its
>    API, but that predated enums, so adding a second constant with
>    same value but corrected name was a triviality back then...
>
> PPS: a similar problem could arise with misspelled class names,
>    but that's not currently in my focus.
>

Leave current API as is. But with major upgrade of library, change 
package name (ex com.me.superlib => com.me.superlib2), and in new 
version use correctly spelled enums and other names.

Anyone who switch to new version of library will need to adapt and 
refactor code anyway, so fixing misspelling wont be a problem.

-- 
Arivald

[toc] | [prev] | [next] | [standalone]


Page 1 of 2  [1] 2  Next page →

Back to top | Article view | comp.lang.java.programmer


csiph-web