We have approximately 100 billion neurons and we use it intensively, but the real power of our brain is not in cell itself (soma), it is in axons and dendrites, in other words - connections.
We have several trillions
connections and we use it to process our daily life, our fantasies, our fears,
our happiness, in other words everything, with these connections life have
meaning.
It is similar in programming.
Good programs always have
constraints - a lot of them.
And what are constrains -
connections. We define how one thing is related to another. With this approach
we can constraint ourselves in our own universe of definitions.
So, what does it mean?
Well, this post is dedicated to
constants. I hate 'em.
OK, it is not so bad you say, after
all, constants are useful and they are providing you a way to repeat yourself
less, to be more explicit in your code and eventually your code will
be also less obscured.
But... I’ve seen it many times that
constants are really misused.
Constants can be used just to
replace plain data, not for code itself - for code branching or any other way
involved in code execution.
So in case that you have function
like this:
public int Foo(int p)
{
return p + 20;
}
It is good idea to replace naked
constant with the real constant like:
private const int PAGE_PADDING = 20;
public int Foo(int p)
{
return p + PAGE_PADDING;
}
But what about this:
public int Foo(string key)
{
if (key == "CommandOpen")
{
return 1;
}
else if (key == "CommandSave")
{
return 2;
}
else
{
return 0;
}
}
You say, it easy one, you just need
to rewrite it:
public const string KEY_COMMAND_OPEN = "CommandOpen";
public const string KEY_COMMAND_SAVE = "CommandSave";
public int Foo(string key)
{
if (key == "CommandOpen")
{
return 1;
}
else if (key == "CommandSave")
{
return 2;
}
else
{
return 0;
}
}
But this is BAD!
Your constants are part of code
execution, you use it to evaluate something and it is really, really BAD!
But OK, what can be done?
You could define enumeration, you
could define class itself, it is fine with me, but just don’t use constants in
this way.
Bu you could say that enumerations
are the same thing, only a bit fancier constants, but then you just don’t seem
to understand what are the enumerations.
First, let’s see how can be this rewritten with enumeration:
public enum Commands
{
Open,
Save,
}
public int Foo(Commands key)
{
if (key == Commands.Open)
{
return 1;
}
else if (key == Commands.Save)
{
return 2;
}
else
{
return 0;
}
}
No, let’s see how this function is
called when we use constants:
Foo(KEY_COMMAND_OPEN);
And with enumeration:
Foo(Commands.Open);
OK, it’s almost the same, no big
differences – WRONG!
In first example, your function
really doesn’t tell you nothing, it receives string and it is totally
acceptable to pass something like this:
Foo("CommandCopyToExcel");
Or
Foo("Something is
passed here - probably it’ll work");
But you can say it is bad to pass
string anyway; you should infer which constants are used where. OK, but how can
I know where your constants are defined? I mean, you could write function in
one class and use constant from another class just because you don’t want to
have redundancy, which is OK, but how can I know that as consumer of your
class, your function doesn't tell that, even if you wrote somewhere
comment it will be probably skipped by my eyes. But what if you decided to
remove some constants from your definitions, just because you don’t won’t to
support some part anymore, like:
public const string KEY_COMMAND_OPEN = "CommandOpen";
public int Foo(string key)
{
if (key == "CommandOpen")
{
return 1;
}
else
{
return 0;
}
}
But in my code I am still calling
your function like:
Foo(KEY_COMMAND_SAVE);
How can I know that this is not
supported anymore?
Well, I will find it
in run-time which is probably the worst case you can have.
And, now let’s go back to
enumerations (or you can use classes also).
You can’t pass anything, you can try
to pass another enumeration because function is expecting enumeration but you
will be enforced by compiler to change your opinion and
that's because function exactly tells you which enumeration it expects. If you delete
some enumeration value it will be automatically detected by compiler and you
will know it and you will fix it before you even run project or make any test.
So, to summarize, if you are using
constants as values it is OK, but if you are using for code branching then it
is BAD, really BAD.
No comments:
Post a Comment