10 bad programming habits we secretly love

10 bad programming habits we secretly love

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

Credit: Kevin

Bad programming habit No. 5: Not declaring types

The folks who love typed languages have a point. We write better, more bug-free code when we add clear declarations of the data type of each variable.

Pausing a moment to spell out the type helps the compiler flag stupid errors before the code starts to run. It may be a pain, but it helps. It’s a belts-and-suspenders approach to programming that stops bugs.

Times have changed. Many of the newer compilers are smart enough to infer the type by looking at the code. They can work backward and forward through the code until they can be sure that the variable must be a string or an int or something else. And if these inferred types don’t line up, then the compilers can raise an error flag. They don’t need us to type the variables any more.

This means it’s now easier to save a few bits by leaving off some of the simplest declarations. The code becomes a bit cleaner, and the reader is usually quite able to guess that the variable named i in a for loop is an integer.

Bad programming habit No. 6: 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 additional load. Smart programmers who write fast code design their architectures to minimise 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 to integers.

Sure, you could rewrite all of your code to minimise 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 the technical debt 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.

Bad programming habit No. 7: 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 features 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.

Bad programming habit No. 8: Old-fashioned loops

Long ago, someone creating the C language wanted to encapsulate all of the abstract possibilities in one simple construct. There were some things to be done at the start, some things to do each time through the loop, and some way to tell when it was all done. At the time, it seemed like a perfectly clean syntax for capturing infinite possibilities.

That was then. Now some modern scolds see only trouble. There are too many things going on. All of those possibilities for goodness are also equally capable of badness. It makes reading and grokking that much harder. They love the more functional paradigm where there are no loops, just functions applied to lists, computational templates mapped to some data.

There are times when the loopless way is cleaner, especially when there’s just one neat function and an array. But there are times when the old-fashioned loop is much simpler because it can do much more. Searching for the first match, for instance, is simpler when you can stop as soon as it’s found.

Furthermore, mapping functions encourages sloppier coding when there are multiple things to be done to the data. Imagine you want to take the absolute value and then the square root of each number. The quickest solution is to map the first function and then the second, looping over the data twice. 

Bad programming habit No. 9: 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.

Bad programming habit No. 10: 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. 

Brand Post

Show Comments