Intellectuals solve problems; geniuses prevent them. ~ Albert Einstein
Jon Skeet said:
I can't in your way of doing things - but I can add it wherever I like
when I'm assigning values manually, because there's nothing to say that
the order in the source code has to be ascending in value. I can do:
Something = 0,
SomethingIForgotToPutInBefore = 100,
TheOriginalSecondLine = 1
No problem. You can't do that if you don't assign values explicitly.
(You can change to assigning them manually at the point you need to do
the above, of course, so long as you're careful.)
But why in the world world would it make a difference where I added a value
in an Enum other than esthetics? (And of course the point we are
discussing.) Assigning them a value only makes them less abstract a more
concreted. In other word, brittle.
And while we all want binary compatibility, who are the few that have to
deliver on this? And if I am one of those few, I am probably faced with the
Open-Closed principle in point of fact on all of the public code I share. I
just a given.
In what way am I arguing that? In what way is the order in which the
values are defined in source code part of the interface?
I am not sure what you were refering to. I did not understand what you meant
by "It doesn't have to be if you specifiy the value though". What is "It"
refering to? I assumed you mean from my previous sentance that the interface
was written in stone.
The enum, if public, is part of you software interface. Interfaces, which
have been around a long time before Java and C# coined the expression, are
any contract between the client and the called code. Right? And as such are
subject to the Open-Closed principle.
Sure. I don't believe that the source code forms part of the interface
though.
Any part of the contract is part of the interface. If you supply a type,
Enum, or other portions of code as public, you are supplying them to fufill
the contract. If you change the enum that your method takes, you
fundamentally have changed that contract. If the client of that code uses a
method that takes the same arguments, including the Enum you changed, then
did the method change, or is it the same? What if the method now does not
throw (or return an error, or null
like it used to because a value has
been added to the Enum. But, the client code expects that to be an error.
That could be a bug. And one that is hard to detect, because there is no
error now. It was a contract, and the the contract was broken.
So you'd use a separate map? That seems a bit of a waste to me.
Has worked very well for me in the few places where I actually need it. And
its not a data map, but a mapping class.
Hang on though - a minute ago you were accusing me of breaking things
by changing numbers (which I wasn't). Now you're suggesting that the
"specific implementation" of the enum (by which I assume you mean the
values) shouldn't be relied upon?
This is the very point I have been suggesting all along. The code should not
use explicit values of an Enum. (Except the case as aformentioned when you
are using a bit flag, or other compelling reason.)
Whereas the way I'd do it, you'd still only have one place to change
them for conversion (not that they should be changed, as we've agreed
above) - but that place would also be the definition of the enum. You'd
have one piece of source code doing both jobs, which I believe is more
compact. If an extra code is needed, you only need to add it in one
place rather than two.
I think we agree on this. But, are you saying that you too do not use the
value of the Enum after it is assigned? So, you are only using the value as
a means of reading to/from the external or other system that required you to
set them to that value to begin with? Because this is the main part of my
suggestion. I prefer not to assign them or assume anything about their value
(except the bit flag or other compelling case) and use a mapping class to
set them. And from what I think you are saying, this is basically the same,
except you use the actual Enum as you mapping. ???
The only difference, this being the case, is the choice of mapping
technique.
Not necessarily. In particular, if you assume that and you use the MS
HttpStatusCode enumeration, you may find that a webserver has given you
a value you don't understand. If the value is coming from outside your
control, you *should* be defensive about whether or not it's one that
you understand. You don't need to use a map to do that though.
I don't know how this would have anything to do with the code in the Enum.
Sure, I would be defensive that I only understand values in the enumeration.
And perhaps, only a subset of those. But I would not assume that, for
example, the HttpStatusCode.OK necessarily equals 200, even though that may
have been the actual code sent back. I would not compare my enum against a
value of 200. I would have no need to do this. I would check against the
enum name.
You're the one claiming the value should have no signficance, as I
understand it. I'm saying that the value should have the same
significance inside the code as in the external system, for the sake of
clarity and maintenance. If you get passed a value you don't understand
from the external system, you should react appropriately (whatever that
reaction is for the situation.)
Yes, I am claiming that the value has no significance, or at least should
have not significance. But you said you could just change your value to
start at zero. If it does not matter if its zero or twelve, then what does
it matter at all?
And I am claiming that you must make sure that you correctly take a system
that for example passes an int 200 as the return of a status code for and
http service, and map it to HttpStatusCode.OK (assuming that is how you
would like to use it internally). And then, from there on, who cares if it
was status code 200, 501, 400, etc.? Its a HttpStatusCode.OK. Isn't that
enough? Why would I need to know its internal representation?