[Newbie Question] Magic Number's dangerous?

R

Roedy Green

IMO, far from more readable
than a simple named constant. My preference would be to use named
constants but I am not saying there isn't a useful application of Java
enums.

I quite like them. They are much more than just a replacement for C
style enums. They are a way of wrapping all kind of auxiliary facts
around the enum in an OO way. It makes for much tidier and shorter
code.
 
H

Hendrik Maryns

Mike Gaab schreef:
I am not up on recent Java features but I did look at the enum type prior to
deciding to use named constants in the example above. Seemed to me like
using Java enums confused the issue as they don't appear to be implemented
as they are in many other languages. Not that implementing them differently
is a bad thing , just not implemented as one would expect.
It´s more like, the old-style enums are implemented in a very primitiveway.
For instance, how
do I assign a value to each element?
Why would you want to?
What are the default values?
Why do you care?
In the
case above one could expect the values to be Sun=0, Mon=1 and so onbut at a
quick glance they did not appear to have those values. How do I get at each
elements value to possibly re-assign its value?
Again, why would you want to?

IM(H)O, if you explicitly assign values to (Java´s) enum constants, you
don´t get the idea of what enums are for.

H.
--
Hendrik Maryns

==================
www.lieverleven.be
http://aouw.org
 
M

Mike Gaab

Mike Gaab schreef:
I am not up on recent Java features but I did look at the enum type prior
to deciding to use named constants in the example above. Seemed to me like
using Java enums confused the issue as they don't appear to be implemented
as they are in many other languages. Not that implementing them
differently is a bad thing , just not implemented as one would expect.
It´s more like, the old-style enums are implemented in a very primitive way.
For instance, how
do I assign a value to each element?
Why would you want to?
What are the default values?
Why do you care?
In the
case above one could expect the values to be Sun=0, Mon=1 and so on but at
a quick glance they did not appear to have those values. How do I get at
each elements value to possibly re-assign its value?
Again, why would you want to?

IM(H)O, if you explicitly assign values to (Java´s) enum constants, you
don´t get the idea of what enums are for.

H.
--
Hendrik Maryns

==================
www.lieverleven.be
http://aouw.org
 
R

Roedy Green

Why would you want to?
What are the default values?
Why do you care?

lots of reasons. An enum can have associated with it such things as:
1. aliases
2. long form English text
3. compact persistent representations for databases
4. boolean properties
5. associated files
6. associated methods

Stop thinking of enums in the C-like way and think of them more
high-level.

So for example, if you have 12 different recording formats, each
represented by an enum, what other data do you want about each enum.
Here are some ideas:
1. name
2. mime type
3. typical extensions.
4. readers that handle it
5. icon to represent it in HTML
6. proprietary?
7. URL of format definer
8. checksum computer
9. min/max frequency
 
R

Roedy Green

Could be.
Please explain what you think I am not understanding.

Enums values are enum constant objects. This is how type safety is
maintained so you don't pass a gender enum to a
favouriteFlavourOfIceCream parameter.

Enums have automatically assigned sequential ordinals ( similar to
the values assigned manually C ). You can of course have fields and
methods to add C-style non-sequential ints as well.
 
H

Hendrik Maryns

Roedy Green schreef:
lots of reasons. An enum can have associated with it such things as:
1. aliases
2. long form English text
3. compact persistent representations for databases
4. boolean properties
5. associated files
6. associated methods

Stop thinking of enums in the C-like way and think of them more
high-level.

I am, I never used C enums. But this was a reaction to the question why
you can´t change the enum value. That is something entirely different
than the things you propose here, and which I totally agree to. Only,
they should be stictly separated from the internal enum constant value.
So for example, if you have 12 different recording formats, each
represented by an enum, what other data do you want about each enum.
Here are some ideas:
1. name
2. mime type
3. typical extensions.
4. readers that handle it
5. icon to represent it in HTML
6. proprietary?
7. URL of format definer
8. checksum computer
9. min/max frequency

Good example. And again, this cannot be expressed by one single value
which is accidentally the value with which the enum constant is
recognised internally.

I hope this is an answer to Mike´s question too.

H.

--
Hendrik Maryns

==================
www.lieverleven.be
http://aouw.org
 
R

Roedy Green

Only,
they should be stictly separated from the internal enum constant value.

You keep thinking in C. There is no value to assign. The enum value
is a reference to an enum constant object. The closest thing to the
C-style value is the ordinal -- automatically assigned by counting off
the enum objects.
 
H

Hendrik Maryns

Roedy Green schreef:
You keep thinking in C. There is no value to assign. The enum value
is a reference to an enum constant object. The closest thing to the
C-style value is the ordinal -- automatically assigned by counting off
the enum objects.

That´s what I meant, just don´t know the terminology. And I never
mentioned the word `assign´. Anyway, I really do agree with you.

H.
--
Hendrik Maryns

==================
www.lieverleven.be
http://aouw.org
 
M

Monique Y. Mudama

byte[] buff = new byte[8192];

byte[] buff = new byte[SOME_BUFFER_LENGTH];

Monique Y. Mudama said:
Seems like you're dodging the issue here by giving a poor example.
The fact is that you must have chosen 8192 for a reason, and that
reason can be documented with a well-chosen variable name.

Nah, I don't see that that's necessarily the case. When choosing
buffer sizes, it's generally a matter of taking a guess. Usually,
the guess is a power of two, because it works better with MMU/paging
architectures where memory is typically allocated in pages of a
power of two in size. Tuning can be done later if it becomes a
performance problem of some kind. If there's some other kind of
ultimate method of calculating ideal buffer sizes, then most of us
haven't yet been informed.

I typically choose buffers of size 32768 unless I have some reason
not to. Obviously, Thomas Hawtin commonly uses 8192. Why? No
particular reason. If it starts mattering in a measurable way, then
I'm sure they'll get tuned, and then a comment will be added
explaining the method used to choose the buffer size and the
observed consequences of making it too large/small.

In any case, even if the buffer size is carefully tuned, I very much
doubt that you could explain the method or logic behind the choice
in a reasonable identifier name.

Sorry for the late reply.

What if you get run over by a bus? The next guy to look at your code
won't know if you chose 32768 because it's your favorite number or
because you found it to be the best via experimentation. So the new
guy will probably avoid touching the magic 32768, whereas at least a
comment that "I pulled this number from my orifice; feel free to tweak
as needed" would give the guy some insight.

And as soon as you find that you need to pass the buffer chunks around,
it's better to use a constant instead of hard-coding the number in
several places.
 
C

Chris Smith

Monique Y. Mudama said:
Sorry for the late reply.

No problem.
What if you get run over by a bus? The next guy to look at your code
won't know if you chose 32768 because it's your favorite number or
because you found it to be the best via experimentation. So the new
guy will probably avoid touching the magic 32768, whereas at least a
comment that "I pulled this number from my orifice; feel free to tweak
as needed" would give the guy some insight.

Well, I sorta operate the other way around. If there isn't a comment by
a buffer size, then I'd assume it's safe to tweak. Certainly someone
who did the testing and did not bother to document the results would be
negligent at a minimum.

Regardless, this isn't really relevant to the desire to use an
identifier. You don't explain benchmarking results in identifier names.
(At least, hopefully you don't.)
And as soon as you find that you need to pass the buffer chunks around,
it's better to use a constant instead of hard-coding the number in
several places.

No, that's absolutely not the case. When I pass that buffer around, it
carries with it the size. All someone needs to do is write
"buffer.length" and, voila, they've discovered the length of the buffer!

--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
M

Monique Y. Mudama

Well, I sorta operate the other way around. If there isn't a
comment by a buffer size, then I'd assume it's safe to tweak.
Certainly someone who did the testing and did not bother to document
the results would be negligent at a minimum.

I guess I've worked with a lot of brittle and poorly documented code.
A lot of times, I was working with code written by people who were not
great at software, but understood the problem domain (Aerospace and
all of its fiddly bits) better than I did. An experienced Aerospace
person might (did) often assume that it's "obvious" why this was the
right number ... and I had no idea.
Regardless, this isn't really relevant to the desire to use an
identifier. You don't explain benchmarking results in identifier
names. (At least, hopefully you don't.)

Okay, true. Names are just one type of breadcrumb. I'm a strong
advocate of breadcrumbs =)
No, that's absolutely not the case. When I pass that buffer around,
it carries with it the size. All someone needs to do is write
"buffer.length" and, voila, they've discovered the length of the
buffer!

Ah, yeah! I guess I was thinking of other languages ...
 
M

Mike Schilling

Chris Smith said:
No, that's absolutely not the case. When I pass that buffer around, it
carries with it the size. All someone needs to do is write
"buffer.length" and, voila, they've discovered the length of the buffer!

I misread Monique's comment as "And if you want to create the same-sized
buffer in multiple places...", which is a good reason, even in Java.

In general, I obey the principal that 0 and 1 are the only unnamed numeric
constants I use.
 
C

Chris Smith

Mike Schilling said:
I misread Monique's comment as "And if you want to create the same-sized
buffer in multiple places...", which is a good reason, even in Java.

And in that case (that is, if it really MATTERS that the two buffers be
the same size), there is also likely to be a good symbolic name that
expresses the significance of that number.

--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
M

Monique Y. Mudama

I misread Monique's comment as "And if you want to create the
same-sized buffer in multiple places...", which is a good reason,
even in Java.

In general, I obey the principal that 0 and 1 are the only unnamed
numeric constants I use.

I do have some magic numbers in the code I'm currently maintaining, but
they are commented as such. For example, through experimentation I
found that 4 was a good starting point for getting an aesthetically
pleasing number of labels on the Y axis for our particular graph. So I
use the number 4, but I do have a comment explaining why it's there and
that it's not sacred.

I'm just a big fan of leaving a breadcrumb trail for others (or my later
self) to follow. Some indication of the thought process that resulted
in the current code. I recognize that sometimes, time constraints
don't allow me to use the best possible design or flow, but I like to
at least sprinkle comments to that effect.

I absolutely hate the dreaded "But you can't put comments indicating the
code might be flakey; the customer might see it and realize we're not
perfect!" whine from managers. Fortunately not an issue in my current
project.
 
C

Chris Uppal

Chris said:
Well, I sorta operate the other way around. If there isn't a comment by
a buffer size, then I'd assume it's safe to tweak.

Especially when:
a) it's used for the size of a buffer or similar;
b) it's an obviously arbitrary value such as an unimportant power of two.

Values I'd be more cautious about tweaking (in the absence of further
information):
137 (not a power of two)
256 (may be 2**number-of-bit-in-a-byte)
8097 (not a power of two)

Values I would tweak:
8096
8096+1 (wouldn't change the +1 but would tweak the 8096).
1024 * <almost anything>

OTOH, I wonder how much old 'C' software is now using undersized buffers (and
similar) because the old code didn't:
#define BIG_BUFFER_SIZE (8 * 1024)
#define BUFFER_SIZE (2*1024)
#define SMALL_BUFFER_SIZE 512
which could nowadays be updated to use much bigger numbers while still
respecting the intent of the author.

-- chris
 
O

Oliver Wong

Monique Y. Mudama said:
I guess I've worked with a lot of brittle and poorly documented code.
A lot of times, I was working with code written by people who were not
great at software, but understood the problem domain (Aerospace and
all of its fiddly bits) better than I did. An experienced Aerospace
person might (did) often assume that it's "obvious" why this was the
right number ... and I had no idea.

<fable>
Person A inherits some code from somewhere, and sees an array which is
declared to be of size 1073. Why 1073? He does a quick search and sees that
1073 never appears anywhere else in the source code. So he pours through the
code and eventually figures out that the array is being used as a hashtable,
and that the hashing function being used generates fewer collisions when the
size of the table is a prime number, so Person A declares a new constant:

#DEFINE SOME_PRIME_NUMBER 1073

A few years later, Person Z inherits the code long after Person A has passed
it on to someone else, who has then passed it on to someone else, who has
passed it on to someone else, etc. This was back in the days before
versioning systems, so there was no way for Person Z to know that there
existed a Person A who made changes, nevermind what those changes were.

So Person Z goes through the code, and sees the following line:

#DEFINE SOME_PRIME_NUMBER 1073

And he says to himself "WTF? 1073 = 23*37. How is that prime?" He changes
the value to 1087, which IS a prime number.

#DEFINE SOME_PRIME_NUMBER 1087

Ever since that day, the code has been breaking in subtle and mysterious
ways.
</fable>

- Oliver
 
T

Thomas Hawtin

Oliver said:
#DEFINE SOME_PRIME_NUMBER 1073

And he says to himself "WTF? 1073 = 23*37. How is that prime?" He changes
the value to 1087, which IS a prime number.

It would be easier to just add a zero in front of the number.

#define SOME_PRIME_NUMBER 01073

Sorted. Proper maintenance craftsmanship.

Tom Hawtin
 
O

Oliver Wong

Thomas Hawtin said:
It would be easier to just add a zero in front of the number.

#define SOME_PRIME_NUMBER 01073

Sorted. Proper maintenance craftsmanship.

Nice.

But the advantage of using 1087 is that it is a bigger number than the
previous one, and thus less likely to result in
ArrayIndexOutOfBoundsException, or whatever the C equivalent to that is.

- Oliver
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,599
Members
45,175
Latest member
Vinay Kumar_ Nevatia
Top