Every comic book supervillain, every James Bond villain, and every cartoon villain all suffered from the fatal flaw of making things overly complex. Everyone remembers the laser designed to cut Mr. Bond in half -- you know, the one that started near his feet and moved at about an inch a minute? Conveniently, of course, the villain du jour departs the scene before the deed is done, leaving Mr. Bond to his inevitable fate... except, of course, his fate is rather evitable (that actually is a word!), as we see mere moments later when he escapes.
Or perhaps you recall the comic book villain, who uses sleeping gas to capture a superhero, only to have him or her completely at the villain's mercy, perhaps confined or tied up, so that said villain can not only revel in the victory (an understandable trait -- who doesn't like winning?) but also go on and on about every detail of his nefarious plan. Like the Bond villain, the comic book villain then sets up some elaborate mechanism to do our hero in (a ticking bomb is popular, as is some device slowly filling with water, or the hero being slowly lowered into a vat of acid, or some other similar, time consuming death that, of course, must be completed while the villain and all of his henchmen attend to their other, more important tasks).
Software engineers do this, too. It is especially common among students and new programmers, but you actually see it all the time, at every company, from every engineer. Sometimes it manifests itself by the use of a specialized, complex algorithm when in reality a much simpler approach would be 99% as effficient. Other times it shows up more purely as premature optimization, perhaps trying to squeeze a few microseconds out of code that quite evidently to everyone (including the programmer in question) isn't a bottleneck. Sometimes it is pride that drives us to be clever, but so often that pride leads us astray that we must guard against it as best we can.
Sometimes the shadow of over-complexity will show up as a series of deeply nested loops, meandering through lists and data structures that are insuitable representations of the problem at hand, instead of finding the right representation and accessing the data more directly. This can be a result of ignorance, or late night programming, or simply having a blind spot because you're too deep in the code. Other times, it will be code taking the form of a comfy blanket of familiarity such as this (pardon the python):
myhash = some_function_returning_a_hash()
ret = []
for key in myhash.keys():
ret.append(myhash[key])
return ret
This, though, is much more simply represented as
return myhash.values(). The frequency of 'make a return variable, stuff the values into it' is so common, though, that many times it slips through when there actually is a simpler approach.The villain's flaw of overly explaining their intentions sometimes creeps up, too. Here's one of my favorite examples:
# use -1 as our smallest value
minval = -1
# loop over the keys of myhash and find the smallest of the hash's values
for key in myhash.keys():
# check if myhash's value for key is less than min
if myhash[key] < minval:
# if it is, we assign min to be myhash's value for key
minval = myhash[key]
Argh! Of all of those comments, only the first is perhaps of any use (as it establishes that myhash's values will be greater than -1). The rest go into painfully pointless detail on code that is completely legible to anyone who knows the language. Worse, it is also an example of overly complex code! We could instead just use
minval = min(myhash.values()) -- simpler, more efficient, and it doesn't rely on some sentinel value like -1. Plus, I would argue it is much easier to understand.At the very heart of all of this is complexity and indirectness versus simplicity and directness. Very often, simple directness is the right choice. You don't need a laser to kill James Bond, especially once you have him tied up -- just get a gun and do it, no delays, no monologues.. Likewise, know your language, always ask how you could make something shorter, and question whether a subroutine is, in fact, a vat of acid or if it is as simple and direct as it can be. Above all... write less code! When you come back six months later, you will thank yourself :)