Monday, June 25, 2012

Learning From The Worst

(I've decided to keep my posts short for now. I sure hope it's the right decision!)

I often complain about how poorly universities teach students how to program, but in one way it's a bit hard to blame them. After all, there's no magic formula for "how to write good code", and there are very few tricks that can be applied universally; the right way to do one thing is rarely the right way to do everything else. I could come up with an absolutely brilliant solution for a software problem I'm facing, and a million other programmers with a million different problems would all agree that my solution is absolutely useless for them.
Luckily, there's another way.

I think you can learn a lot from looking at the wrong stuff. The right kind of person, once they realize that a problem exists, often starts to think of ways to either solve or avoid that problem.
I believe this applies nicely to code. Assuming you have the basic ability to tell good from bad (e.g. shorter is better), and are an obnoxious overcritical perfectionist like me, looking at really horrible code should immediately make you start thinking of everything that could have been done to avoid that sort of code. And this, in my experience, can provide insights that are much easier to apply when solving different problems.

So here's an example of a completely real function in a completely real project. As far as I know, this was written by a sane person with a master's in comp sci:
Mbx ORFirstMbxWithSecondMbx (mbx1, mbx2);
The functionality, granted, is fairly obvious to anyone who knows what Mbx is, which probably includes everyone who ever had to work with this code. But the name... oh my, the name.

The worst part, I think, is that I've seen people look at that function without having a seizure, without collapsing in tears, without so much as an asthma attack. I find that inexplicable.
This is insane. It's an abomination. This is the exact equivalent of replacing a+b with AddFirstNumberToSecondNumber(a,b). And by that logic, assigning that value into c would have to call the function AssignNumberIntoNumberVariable afterwards. And really, that way madness lies; if you're using a low level language like C++ there's nothing stopping you from finding yourself with MultiplyFirstUnsignedThirtyTwoBitIntegerBySecondUnsignedThirtyTwoBitInteger

Alright, the last one was a bit of an exaggeration. But the thing is, if you don't see why ORFirstMbxWithSecondMbx is a bad thing, then why would you think that that 32 bit example is bad? Where do you draw the red line?

I hope that this is obvious, but the function should have been named just |. This is, after all, why operator overloading was invented. If you can write a|b for a bitwise OR operator between a and b when they're integers, there's no reason why it shouldn't work for any type of a and b where an OR operation is a clear and sensible thing to do.
Even if the big boss absolutely refuses to see operator overloading in the code (or, you know, you're in a language without this feature), you can just name it OR. It still says everything it needs to, and it's 10-20 times shorter.

So I think that this example can draw our attention to the sort of excessively-verbose names we need to avoid, as well as remind us to thank the Flying Spaghetti Monster for giving us operator overloading.
If anyone noticed other useful lessons that are hidden in this, feel free to share them!

No comments:

Post a Comment