As Simple As Possible, But No Simpler
February 11th, 2008
Simplicity is a feature. It’s a feature shared by too few software projects, and as such should be highly sought after and implemented wherever possible. Sadly, the reason it’s so often not implemented is because developers do not believe they have time to implement it.
“I would have written a shorter letter, but I didn’t have time.”
—attributed to Blaise Pascal
The idea that simpler solutions are better, more elegant, more easily maintained, more creative, more clever, more beautiful, seems nearly ubiquitous in the world of computing.
I once had the (silly) idea to create a multi-user blog system using the same model for users as for blog posts. Essentially, there would be only one type of record. The fields would simply be ambiguous, and the model would be tweaked to allow for multiple interpretations. Where a blog post would have a “title”, a user would have a “username”. Same field could be used. Where a blog post would have “content”, a user might have “About” or “Biography” information. A blog post would have a “created on” date field, which would be analogous to the opening date of a user’s account… And so on. I thought it would be an elegant system, because the model would be “simple”.
And it could certainly be done. The problem is, it’s actually an attempt to implement a sort of “simplicity” that would have to be shoe-horned into the system forcefully and inelegantly. A blog post would wind up having an optional “password” field that it would likely never use. A useful user record would include separate fields for firstname, lastname, email address, none of which would be needed by a blog post record.
In short, it’s not actually a good idea. But it’s a good demonstration of the idea that a system should be as simple as possible, but no simpler.
Determining that something has been made as simple as possible (but no simpler) could actually be somewhat time consuming. It involves some projecting of the consequences of the design & architecture choices being made during the planning stages. It might not be evident, at first, that a given design is too simple, or not simple enough. You have to think about it for awhile.
Some ideas, like the shared model for users and blog-posts, are pretty easy to spot with a little consideration as being too simple (in that case, it would actually be forcing a faux simplicity which would create more complexity). In practice, most decisions that matter may not be so easy to spot. We need to keep looking for them anyways.
Simple is also not analogous with “quick & dirty”. Quick and dirty may actually not be simple at all—a brute force searching algorithm is quick to code, but not quick to execute. Or, do a Google search for methods of finding prime numbers. The most obvious solutions are in general not the most efficient, while the most efficient solutions are rarely obvious, and may even take quite a bit of pondering to see how and why they work.
Too Clever to be Simple
That introduces a whole new question: is the most efficient solution really the simplest? That is, if you write an algorithm in one line that does some complicated thing in a very clever way that only five people understand (and two of those people are Donald Knuth), is it really a “simple” solution? That’s a great question.There’s a whole school of thought in software development which derides “Overly Clever” solutions, because they may be difficult to understand when maintaining the code. I don’t personally like this very much, as clever, elegant solutions are what makes programming interesting in the first place.
It may be a fact of life in development at work; that doesn’t mean it must be liked.
For starters, let’s take it as a given that code should be meaningfully commented. That means that:
# assign '2' to x x = 2
is superfluous and not a meaningful comment. Unless you expect your code to be maintained by individuals to whom assigning variables is a fearful, arcane mystery. While, on the other hand,
#fill an array with 100 numbers between 0 - 99
for x in 0..99 do
somenums[x]=Integer(rand * 100)
end
# check whole array from both ends for the number 42, report all instances
for x in 0..49 do
for n in [x, 99 - x] do
if somenums[n] == 42: puts "#{n} is 42!"
end
end
end
might be some moderately more useful comments. (Whether the actual algorithm is a Good Idea or not is beside the point, really.)
That’s a weak example of a “clever” algorithm — refer to the aforementioned search for methods of finding prime numbers for something more arcane — but the point is, even if you’re doing something “elegant”, a well written comment can do wonders in making the code easier to decipher.
If that’s important. It’s relevant to mention that you might enjoy doing clever things just because it’s fun, so, you may not even care to leave comments. It depends; I think if you’re working on any code that Someone Who Is Not You may have to maintain, comments (meaningful ones) are a Good Thing. Heck; if you have trouble reading your own code a month after you’ve written it, you may at least want to leave yourself some clues.
All this to say:
The simplest solution, as simple as possible (but not simpler) may take some effort. That’s why it’s worth finding.
This post’s title is from “Software Engineering: A Practitioner’s Approach” by Roger S. Pressman. It’s a very corporate-programming-centric volume, as the title may indicate, but there are some interesting tidbits within.

Sorry, comments are closed for this article.