Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.java.programmer > #26511 > unrolled thread
| Started by | Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> |
|---|---|
| First post | 2013-11-15 16:25 +0000 |
| Last post | 2013-11-19 11:14 +0000 |
| Articles | 20 on this page of 21 — 7 participants |
Back to article view | Back to comp.lang.java.programmer
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 →
| From | Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> |
|---|---|
| Date | 2013-11-15 16:25 +0000 |
| Subject | Fixing "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]
| From | markspace <markspace@nospam.nospam> |
|---|---|
| Date | 2013-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]
| From | Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> |
|---|---|
| Date | 2013-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]
| From | markspace <markspace@nospam.nospam> |
|---|---|
| Date | 2013-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]
| From | Eric Sosman <esosman@comcast-dot-net.invalid> |
|---|---|
| Date | 2013-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]
| From | Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> |
|---|---|
| Date | 2013-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]
| From | markspace <markspace@nospam.nospam> |
|---|---|
| Date | 2013-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]
| From | Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> |
|---|---|
| Date | 2013-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]
| From | Robert Klemme <shortcutter@googlemail.com> |
|---|---|
| Date | 2013-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]
| From | Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> |
|---|---|
| Date | 2013-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]
| From | Robert Klemme <shortcutter@googlemail.com> |
|---|---|
| Date | 2013-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]
| From | Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> |
|---|---|
| Date | 2013-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]
| From | Jan Burse <janburse@fastmail.fm> |
|---|---|
| Date | 2013-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]
| From | Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> |
|---|---|
| Date | 2013-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]
| From | Eric Sosman <esosman@comcast-dot-net.invalid> |
|---|---|
| Date | 2013-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]
| From | Robert Klemme <shortcutter@googlemail.com> |
|---|---|
| Date | 2013-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]
| From | Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> |
|---|---|
| Date | 2013-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]
| From | Eric Sosman <esosman@comcast-dot-net.invalid> |
|---|---|
| Date | 2013-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]
| From | Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> |
|---|---|
| Date | 2013-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]
| From | Arivald <NOSPAMarivald@interia.pl> |
|---|---|
| Date | 2013-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