I hate KISS (Keep It Simple, Stupid)! It’s possibly the world’s WORST advice ever given about software design and development. First of all, I take exception at being called stupid. I am not a moron, and most of the people I have worked with (whether they are good at their jobs or not aside) are not idiots. Who the heck gives advice by first verbally abusing the person that you gave the advice to? Oh, sure, I want to take advice from a person who has resorted to name calling.
Secondly, I take exception with the world “simple.” Define simple. Let me help. Here’s a snippet from dictionary.com:
| 1. |
easy to understand, deal with, use, etc.: a simple matter; simple tools. |
| 2. |
not elaborate or artificial; plain: a simple style. |
| 3. |
not ornate or luxurious; unadorned: a simple gown. |
| 4. |
unaffected; unassuming; modest: a simple manner. |
| 5. |
not complicated: a simple design. |
| 6. |
not complex or compound; single. |
| 7. |
occurring or considered alone; mere; bare: the simple truth; a simple fact. |
| 8. |
free of deceit or guile; sincere; unconditional: a frank, simple answer. |
| 9. |
common or ordinary: a simple soldier. |
| 10. |
not grand or sophisticated; unpretentious: a simple way of life. |
| 11. |
humble or lowly: simple folk. |
| 12. |
inconsequential or rudimentary. |
Which one of these terms works for you to describe your code? “Common or ordinary,” perhaps? Or do you prefer “inconsequential or rudimentary?” Of course, you’d probably pick “easy to understand, deal with, use, etc.” Ok, here’s a handsaw, go cut me some boards to build a house. It’s simple after all, so by the K.I.S.S. philosophy this is what you ought to be using to get the job done. Forget a saw mill – it’s too complicated!
The problem with simple is that it means too many things to too many people. Simple is subjective. Simple isn’t simple to define or pick out. Definition is in the eye of the beholder.
How about a practical example? I worked on a team at the start of my career that developed software for the Ortho Autovue (check it out here if you’re curious: Ortho Autovue). It was my first job out of college, and my mentor was the most senior member of the team. He is a great guy; I haven’t talked to him in years but I loved working with him. He was the epitome of the grumpy old (I’m sure he won’t take offense) programmer. He was eccentric. We worked in a small building, and he loved to play his music loud enough in his office that I could hear it in mine. Yes, I had a real office with a door I could close and a window I could open! How I miss those days when I’m sitting in my cost-saving crappy cube. He loved to curse at the code, a habit that I picked up and took years to train myself out of once I didn’t have the privacy of an office anymore. And for all his coding ability, the only shortcoming I can think of was that he was a fan of KISS. He told it to me first, and it’s the one thing that I learned to disagree with him about.
His idea of KISS was code readability. Could the average idiot pick it up and understand what he was doing? That was KISS to him. And so when he had to deal with translating multiple values into a single value, his choice was a giant if..then..else statement or nested if..then..elses. It might go on for pages and pages. Why? Well, to him it followed the KISS philosophy. My solution to the same problem was an N-dimensional array. Simply reference the cell you want using the inputs as indices into the array and ta-da!
His code might be:
int TranslateValue(int X1, int X2) {
if (X1 == 1) {
if (X2 == 1) {return 1;}
else if (X2 == 2) {return 3;}
else if (X2 == 3) {return 1;}
} else {
if (X2 == 1) {return 6;} ...
Easy to read, sure. Simple? I think you’d have to agree that it is by some definition. Good? Not so much. How about my solution?
int TranslateValue(int X1, int X2, int LookupTable[][10]) {
return (LookupTable[X1][X2]));
}
Better? I think so. Simple? There’s that eye of the beholder thing again. In my opinion, this is a much better solution. It’s a data driven approach. You can’t tell from the code what the any combination of X1, X2 will return, but it’s easy to expand the function to return new values, can work for any array passed in (provided it’s second dimension is 10 elements in this really basic example), and allows for the lookup table to be read from a file or modified on the fly. It isn’t all hard coded. This still isn’t exactly what you’d call difficult code. It works (I didn’t compile it and haven’t coded C in a long time so it might not compile), it’s easy to understand (even if you might have to look in a different place to understand the values in the lookup table), and above all it’s a more elegant solution. It does everything that the giant if..then..else chain does and then some!
So, what if he was doing more than returning the value based upon examining two other values? What if he was executing a bunch of code that had side-effects? Then my solution no longer works, right? WRONG! Instead I can make the table a two dimensional array of function pointers. Sure, function pointers scare the heck out of most people, but they are extremely powerful (compare handsaw vs. saw mill). In his giant if-then-else he’d either be forced to copy and paste code or write functions to be called. I still have to write functions, but I maintain the ability to read from a file (say I was using functions by name in a DLL) or change the lookup table on the fly.
Now, I will admit there are non-simple things people do in code. I think they’re best described as anti-patterns (http://en.wikipedia.org/wiki/Anti-pattern). Things that you do because you think they’ll be super-cool and end up handcuffing you rather than freeing you like you imagined they would.
But simple… simple is a terrible word that encourages people to write code that needs lots of maintenance every time something changes in order to provide readability or some other perceived benefit instead of doing something elegant, something so “simple” that nobody would believe it’d work.
Another great example of the right kind of simple is Ethernet. Prior to Ethernet you had managed networks like token-ring where each computer got a turn on the network. It required token passing and resulted in a sluggish network whenever the size of the network grew because the token had to be passed around in case any computer wanted to do something. Ethernet was a kick in the teeth to token-ring. Instead of coordinating traffic, Ethernet did the most beautifully simple thing possible. It’s was called Aloha or CSMA/CD (carrier select multiple access/collision detect). Basically:
- Listen. If no one is talking on the network at the immediate moment, go! If they are, wait a short random amount of time and then listen again.
- Send your data and listen at the same time.
- If what you hear doesn’t sound like what you sent, your data collided with someone else’s. Wait a short random amount of time and start over.
It’s fantastic! It’s brilliant! It’s unbelievably super-simple. No coordination, no need to manage the network. Pure “chaos” with just 3 simple steps works really well!
So the next time someone else tells you to K.I.S.S., I think you should tell them to K.I.S.S-off. Do the right thing and build the beautiful, elegant solution that’s so simple nobody can believe it works and is adaptable to change. Don’t succumb to mediocrity.