Derek Sivers asks:
How do you know when you've found the right solution? Is the ugly solution ever the best solution? ... Which got me wondering how other programmers handle this situation: when you've written something that WORKS, but goes against your good taste in design. Is the ugly solution ever the best solution? Is it not right until it's as simple as possible? I keep thinking that ugly solutions are always a sign of the wrong approach. Is anything that works "good enough"? Or do you strive to find the truly beautiful solution to everything? Thoughts, anyone?
I've been programming professionally for about 25 years.
At the beginning I was very big on the concept of elegance. I would do things the elegant way, because I had faith that that was the way to write great code. It was a kind of magic guide. Except, gradually I noticed that sometimes if I had done things less elegantly, but with more attention to certain other factors, I would have avoided a bug or the code would have been easier to maintain. The downside usually was that an "elegant" solution tends to solve problems in such a perfect, simple way that sometimes it's not even obvious what problems are being solved. That is, the elegant solution is sometimes so concise and brief, serving more than one purpose at a time, that there is no explicit and readable statement or what purposes are being served. So, people working with the code later may not understand everything that is happening in the elegant solution, and may unknowningly make a change that alters some of the necessary behavior. Also the elegant solution is sometimes bug-prone in its original form -- due to its conciseness it doesn't necessarily handle every possible situation in a very explicit way, and so there is a somewhat greater tendency to leave some combination of circumstances uncovered, leading to unpredictable behavior when that combination appears at run time.
Gradually, I have come to the conclusion that elegance is much less important than it often appears to be to young programmers who have a natural love of programming. (I would assume Derek Sivers is in the category -- as I understand it, CDBaby was his first major programming effort, and that wasn't that long ago. And it is obvious that he is very talented, which usually implies having a love of the craft.)
In fact, at this point, elegance is fairly low on my list of properties that make for a good programming effort. The highest property is readability. But a very close second is encapsulation -- making little units of code that perform some work without variables or other things hanging around that could cause problems. For instance situations where a variable is available and appears to have a certain use is dangerous if there are hidden occasional conditions when that use cannot be relied upon. It's better to encapsulate so that programmers working on other aspects of the code are not able to access that variable and are therefore not in danger of misunderstanding it. (That doesn't always mean creating a function or class to carry out that work. For instance, sometimes it's simply a matter of consciously striving to make sure that every relevant aspect of a variable is easily understood from its name. Also, some modern languages such as Python support "functional programming" constructs such as "list comprehensions" that enable you to write a line of code that is encapsulates meaningful work.)
There is sometimes a conflict between readability concerns and functional programming concerns. And there are many other factors as well. It is an intuitive integration of the various factors which can seem esthetic -- a matter of one solution being more "tasteful" than others. Elegance may be the sugar of programming taste. When you're young, it seems very important. And indeed there is real value in it. It's arguably the first meaningful guidepost that is available to intuition. But when you're older, and have the benefit of many years of hard-won experience, other more subtle taste factors, with greater nourishment value, rise to the fore and tend to predominate.
Thanks very much for that. Great advice. I've also just recently learned about encapsulation the hard way: by doing the opposite for a few years, and feeling the pain. :-)
Posted by: Derek Sivers | August 09, 2004 at 07:31 PM
In my vocabulary, what you call elegance I call cleverness. The elegant solution to me is the one that you describe when talking about readability and encapsulation. I think we should be striving for elegance, and not cleverness, but we need to understand what really is elegant.
Posted by: Hans Fugal | August 10, 2004 at 11:36 AM
In my vocabulary, cleverness is not the same as elegance, although some "elegant" solutions are clever.
Also, I don't think that what I mean by readibility and encapsulation jibe very well with dictionary definitions of "elegance." In fact I think they can appear distinctly inelegant, as most people use the term. That is specifically the point I'm making.
If you have a different concept of "elegance" then what I'm saying won't mean anything to you. That's OK.
Posted by: Gary Robinson | August 10, 2004 at 12:02 PM
I strive to write software that works and is maintainable. Do that with a bit of planning and you often end up writing what most people would call an elegant solution, plus you write it quickly so can bugger off to the pub early or read blogs.
Posted by: David Cantrell | August 10, 2004 at 02:54 PM