Saturday, July 14, 2012

Variables and Other Demons


if (someverylong.variable.name.m_bSomething == true)
{
    another.ridiculously.longname.m_bSomething = 
    another.ridiculously.longname.m_bSomething  &&  
    true;
}
else
{     
    another.ridiculously.longname.m_bSomething  = 
    another.ridiculously.longname.m_bSomething  &&  
    false;
}

This is a real piece of code, except for the variable names which have been altered to protect their identities. The original names were the same length though.
Now, since I suffer from a rare case of Compulsive Refactoring Disorder, whenever I run into a sub-optimal piece of code I immediately try to make it better. I take medication for it, but still every day is a struggle. Anyway, this one turned out to be interesting.

This code doesn't immediately scream "I'm wrong". I mean, it's a bit heavy on the eyes, but that stuff just happens when you have huge structs within huge structs. What's a programmer to do?
Spoiler alert: this code is wrong. If you can see the solution right now, you win 2 points!

I'll use a magic trick here which I've learned from arch-druids versed in the arts of mystical runes.
This one arcane rune is called ampersand, and when properly used it grants you the power to command a demon as if you knew its True Name, by binding the beast to a name of your choosing. And it works on variables, too!
I'm going to rename these two demons X and Y, and also drop their protective braces temporarily. Check this out.

bool &X = someverylong.variable.name.m_bSomething;
bool &Y = another.ridiculously.longname.m_bSomething;

if (X == true)
    Y = Y &&  true;
else
    Y = Y &&  false;

Can you see it yet? You get 1 point if you do. And if you don't:

X==true
X==false
Y==true
true
false
Y==false
false
false

Well, that looks familiar, doesn't it?
What I'm trying to say is that the entire monstrosity up there sums up to:

Y = Y && X;

This expression actually has less elements than the original code has lines.

I admit that the names X and Y aren't very informative and might not even fit the occasion.
But the purpose of this live example was to show how something like long variable names can be enough to effectively blind you to the code's meaning and purpose. In this case as soon as the names were made shorter, it was much easier to see what actually happens, and the inherently suspicious bits were much more visible than before.

If you have any interesting examples of your own, don't hesitate to comment!

2 comments:

  1. In which languages ampersand is used? Never met this creature before... or do you mean defining new variables with shorter names for the old variables? Isn't that dangerous a bit?

    ReplyDelete
    Replies
    1. Sorry, I should probably have elaborated a bit on what I was actually talking about there.

      What I had in mind (and what this code was written in) is C++. Defining a reference like I did in the second piece of code up there means that X is, in every way I can think of, completely identical to the variable someverylong.variable.name.m_bSomething.

      The point, of course, applies to any other similar technique in any language that allows you to refer to a variable using a shorter name.

      Delete