9 bad programming habits we secretly love

Breaking the rules can bring a little thrill -- and produce better, more efficient code

Page 2 of 2

Programming habit No. 5: Yo-yo code

Programmers like to call it "yo-yo code." First the values are stored as strings. Then they're parsed into integers. Then they're converted back to strings. It's terribly inefficient. You can almost feel the CPU struggle under all the wasted load. Smart programmers who write fast code design their architectures to minimize the conversions. Their code runs faster because of their planning.

But believe it or not, sometimes it makes sense. Sometimes you have a whiz-bang library that does a bazillion intelligent things inside its proprietary black box. Sometimes the boss wrote a seven-figure check to license all of the genius inside that black box. If the library wants the data in strings, you give it to the library in strings even if you recently converted it into integers.

Sure, you could rewrite all of your code to minimize the conversion, but that would take time. Sometimes it’s OK for the code to run an extra minute, hour, day, or even week because rewriting the code would take even more time. Sometimes running up a technical debt like this is cheaper than building it right in the first place.

Sometimes the library isn't proprietary code, but code you wrote yourself long ago. Sometimes it's faster to convert the data one more time than rewrite everything in that library. So you go along and you write yo-yo code. It’s OK -- we’ve all been there.

Programming habit No. 6: Writing your own data structures

One of the standard rules is that a programmer should never write code for storing data after completing the data structures course in their sophomore year. Someone else has already written all of the data structures we'll ever need, and their code has been tested and retested over the years. It’s bundled with the language and it’s probably free. Your code could only have bugs.

But sometimes the data structure libraries are a bit slow. Sometimes they force us into a structure that may be standard but wrong for our code. Sometimes the libraries push us into reconfiguring our data before we use the structure. Sometimes the libraries include belts-and-suspender protections with items like thread locking, and our code doesn’t need them.

When that happens, it's time to write our own data structures. Sometimes it's much, much faster. And sometimes it makes our code much cleaner because we don't include all of the extra code for reformatting the data exactly so.

Programming habit No. 7: Breaking out of loops in the middle

Somewhere along the line, a rule-making group declared that every loop should have an "invariant," which is to say a logical statement that is true throughout the loop. When the invariant is no longer true, the loop ends. It's a good way to think about complex loops, but it leads to crazy prohibitions -- like forbidding us from using a return or a break in the middle of the loop. This is a subset of the rule forbidding goto statements.

This theory is fine, but it usually leads to more complex code. Consider this simple case that scans an array for one entry that passes a test:

while (i<a.length){
   ...
   if (test(a[i]) then return a[i];
   ...
}

The loop invariant lovers would rather we add another boolean variable, call it notFound, and use it like this:

while ((notFound) && (i<a.length){
...
if (test(a[i])) then notFound=false;
...
}

If this boolean is well-named, it’s a great piece of self-documenting code. It may make it easier for everyone to understand. But it’s also added complexity. And it means allocating another local variable and clogging up a register that the compiler may or may not be smart enough to fix.

Sometimes a goto or a jump is cleaner.

Programming habit No. 8: Using short variable names (but i and x and and make sense)

Edgar Allan Poe used to say that every word in a story should build to a single conclusion. By this, he meant that every word must say something to the reader. The coding rules insist on the same. Each variable name should explain what it's doing and why it's there. This is taken to insane lengths by Java programmers who’ve embraced the idea of using camel case variable names to tell elaborate details about what the variable does. Some programmers write variable names that have five, six, or even more words glued together.

But sometimes it's easier to use an inscrutable one-letter variable. Sometimes it's simpler to use only i or j for the iterators in loops. Sometimes it's simpler to use a for an array and l for a list, even if it's indistinguishable from the number 1.

Yes, an earlier part of this article encouraged self-documenting code over long comments. In this case, a one-letter variable name is self-documenting. The letter i is the universal iterator. The smart programmer will know immediately.

Programming habit No. 9: Redefining operators and functions

Some of the most fun languages let you do truly devious things like redefine the value of elements that look like they should be constant. Python, for instance, lets you type TRUE=FALSE, at least in Version 2.7 and before. This doesn't create some kind of logic collapse and the end of the universe; it simply swaps the meaning of TRUE and FALSE. You can also play dangerous games like this with C preprocessors and some other languages. Still other languages let you redefine operators like the plus sign.

This is a stretch, but there will be points within a big block of code when it’s faster to redefine one or more of these so-called constants. Sometimes the boss wants the code to do something entirely different. Sure, you could work through the code and change every occurrence, or you could redefine reality. It can make you look like a genius. Instead of rewriting a huge library, you simply flip a bit and it does the opposite.

Perhaps it’s good to draw the line here. You shouldn’t try this at home, no matter how clever and fun it can be. This is too dangerous -- really ... honest.

Related articles

| 1 2 Page 2