-1

Many questions have been asked about the nature of elegant code and design, but the underlying assumption seems to be that elegance is a good thing. Therefore it is acceptable or even desirable to make some extra effort to create elegant solutions.

But is it really worth it?

I am not asking what is elegant; neither am I asking about good code. I assume that "you know it when you see it", and it can also be vaguely characterized by verifying that there is nothing left to take away, in a sense that the mental model you have in your mind is expressed directly and unobscrured in the language of your choice (programming language, object oriented design, relational schema etc.), without distractions.

However, a corollary to it is that elegance is always relative (and in a way subjective); it depends on what you think the problem is and what the solution should look like. The problem of course is that both the problem domain and your understanding of it constantly change (additionally, your knowledge about the programming language / patterns / tools develops, but that's not what I am mainly concerned about).

This implies that in order to keep your design elegant, you have to constantly rethink it as the problem / your undestanding of it evolves. Practically, doing so would result in almost endless refactoring.

Furthermore, I even maintain that by striving to develop elegant solutions maintainability necessarily suffers. The most elegant solutions are the most tightly coupled to the problem domain, for if they weren't, then there would be something to take away from it, hence they would not be most elegant anymore. If there is something abundant in your solution, then you can simplify it and make it more elegant by removing that abundant part, right?

But then, sometimes, when you have a really elegant design and are required to implement a change, you first have to "untighten" your solution, just in order to be able to make an unforeseen (as are most of them) change at all. However, the open/closed-principle states that this should not be necessary. So, another more concrete formulation of the question is:

To some degree, aren't elegance and open/closed-principle at odds with each other?

What do you think?

closed as primarily opinion-based by user40980, GlenH7, gnat, Robert Harvey, david.pfx Jul 22 '14 at 14:52

Many good questions generate some degree of opinion based on expert experience, but answers to this question will tend to be almost entirely based on opinions, rather than facts, references, or specific expertise. If this question can be reworded to fit the rules in the help center, please edit the question.

  • Why the downvote? This is a reasonable question. – Doval Jul 18 '14 at 14:42
  • 1
    You have a very sui-generis concept of what elegant means. – Tulains Córdova Jul 18 '14 at 15:12
  • I should clarify what I mean by elegance: suppose there are two components and one of them talks to another through an interface. I assume that it would not be elegant to make that interface bigger than required - it should contain only necessary operations, no more and no less - but that always depends on the way how these components are supposed to interact, hence for every kind of interaction a dedicated interface is required. Obviously this is impractical, albeit the force leading to this kind of design was striving for elegance (designing interfaces as simple as possible). – proskor Jul 18 '14 at 16:20
  • An interface should encapsulate the contracts required for proper decoupling of code. There is no hard fast rule on the size of the interface. I've gone down the road of splintering interfaces down to very fine levels and it does get counter productive. Interfaces are a great tool when used appropriately, but their use does not necessarily imply elegance. It's more about using the most appropriate tool for the job. Interfaces aren't always the answer, they can simplify some problems and complicate others. – Berin Loritsch Jul 19 '14 at 19:11
3

Isn't striving for elegance counter-productive?

Past a certain point, yes.

But is it really worth it? I am not asking what is elegant; neither am I asking about good code. I assume that "you know it when you see it"

Well ... you probably should [ask "what is elegant"]. "You know it when you see it" implies that you don't know it, until you see it as well -- and then, your effort to write elegant code is effort spent with lacking direction (or, effort spent in the wrong direction).

This implies that in order to keep your design elegant, you have to constantly rethink it as the problem / your undestanding of it evolves. Practically, doing so would result in almost endless refactoring.

No, it doesn't imply that you should constantly rething the problem. You should think the problem well at the beginning. The more thought you put in at the beginning, the less you will have to change afterwards. If you do not have a clear thought of where you are/should be (at the beginning) then you will need to change the code. To avoid endless refactoring, you should (first) decide how the solution should look like, how an elegant solution should look like, then implement that.

You will know you are doing it right, when you end up spending up to 10 times* on interface design (and tests) then you spend on implementation.

Furthermore, I even maintain that by striving to develop elegant solutions maintainability necessarily suffers.

If a solution is not maintainable, how can you call it elegant? An elegant solution should be (by my definition) a solution that fits the problem, design, maintainability and performance requirements well. Otherwise, it may not be a solution to your problem at all (let alone an elegant one). This also makes my point above (about needing to ask "what is elegant" before you go searching for elegant solutions).

The most elegant solutions are the most tightly coupled to the problem domain, for if they weren't, then there would be something to take away from it, hence they would not be most elegant anymore.

In my book, those are not elegant solutions, they are inflexible solutions (and by definition, as opposed to elegant as you can get).

If there is something abundant in your solution, then you can simplify it and make it more elegant by removing that abundant part, right?

Uhh ... no. Doing so would depend on what you would gain by such a change, and if the gain is worth it at all.

you first have to "untighten" your solution

AFAIK, this is called implementing a loosely coupled design, and is considered a cornerstone of writing elegant code. It is not something that goes against elegant design, it is a part of it.

To some degree, aren't elegance and open/closed-principle at odds with each other?

No. An elegant solution would be one that took the open/closed principle into account from the start.


  • this idea was taken from Alexander Stepanov, the designer of the C++ STL (and it's an idea I can confirm through experience).
  • "You should think the problem well at the beginning. The more thought you put in at the beginning, the less you will have to change afterwards" - well, in an ideal world that might be true. However in reality both problems and your understanding of them evolve over time. No one can design an elegant solution upfront, it's utopian. That's what I meant by endless refactoring. You just can't affort that luxury. And, sort algorithms? Really? I mean, who is making a living by designing sort arlgorithms and staff the like on a daily basis? – proskor Jul 18 '14 at 15:36
  • "That's what I meant by endless refactoring. You just can't affort that luxury." Is keeping your code from devolving into an unmaintainable spaghetti mess really a luxury? – Doval Jul 18 '14 at 16:16
  • @Doval Well, sometimes, it is. Sad but true. But that's not what I am talking about. I am talking about keeping your code as elegant as possible at all times, i.e. the opposite of letting it devolve into spaghetti mess. Theoretically, if elegance is a good thing then doing it to the bitter end would also be a good thing, and this is exactly what I challenge. I suggest that having the most elegant solution is sometimes not as good as having a less elegant one to begin with. – proskor Jul 18 '14 at 16:41
  • "Theoretically, if elegance is a good thing then doing it to the bitter end would also be a good thing" That conclusion is only valid if pursuing elegance costs nothing or if you have infinite resources to spend. It's kind of like saying "if food is good, then eating nonstop is good". I think you're arguing against a statement that nobody's tried to make. – Doval Jul 18 '14 at 16:56
  • @Doval That is true, but there is a difference between not being able to pursue something to the end because of some limitations like lack of time or because it's costly, and the fact that this thing can become bad in itself if you do it too much. For example, there is nothing wrong with being healthy; you cannot be too healthy. On the other hand, although eating food is good, too much eating is bad. So, my claim was that striving for elegance can indeed become a bad thing in itself. Not just because it's costly to do, but because the result will be less maintainable than else, for example. – proskor Jul 18 '14 at 17:11
3

I see no justice in this statement:

... by striving to develop elegant solutions maintainability necessarily suffers. The most elegant solutions are the most tightly coupled to the problem domain, for if they weren't, then there would be something to take away from it, hence they would not be most elegant anymore.

An example of an elegant solution that is not tightly coupled to the domain is generic sort algorithms. You have six items in a list (vector/array/whatever) that need to be sorted; do you hand craft the 12 lines of code that take advantage of the inherent partial ordering of the list, or do you invoke a sort function in one line?

Similarly, do you explicitly craft an algorithm and re-implement it several places or do you extract a method and make it generic?

In both of those cases, the elegant solution is much shorter and more understandable. The given solutions are also more maintainable.

This is a straw man argument:

in order to keep your design elegant, you have to constantly rethink it as the problem / your undestanding of it evolves. Practically, doing so would result in almost endless refactoring.

Striving for elegance is always balanced against all of the other needs of the project.

  • Generic sort algorithms are tightly coupled to the problem domain; that domain is sorting. But I even doubt that generic programming in general leads to more elegant solutions. If the only type of objects to be sorted is fixed and known in advance, then why should I bother implementing a generic sort algorithm at all? Sure, it might be used to sort other things in the future, but is it elegant to do more than is required? – proskor Jul 18 '14 at 15:06
  • "is it elegant to do more than required?" -- this. Very often the more elegant solution arises from expanding the problem domain beyond the one right in front of you. Only trivial programs sort only one type of thing in only one way. Similarly, anticipating the types of requests made by the customer leads to less program rot as the years go by. – BobDalgleish Jul 18 '14 at 15:32
  • @proskor No, the comparator function is. The sort function itself is not. – Izkata Jul 19 '14 at 1:47
3

However, the open/closed-principle states that this should not be necessary. This isn't a useful interpretation of the open/closed principle.

There's always a requirement your design can't accommodate. Think of it this way - a program can be thought of as a domain-specific library whose components are combined in a particular way by the main function to solve some problem. If that library is flexible enough to do anything without changes to its source code, it's turing complete and you've created a programming language on top of your programming language and are no better off than when you started. For the library to be useful, it must be tailored to a particular, well-defined task, and when the scope of that task changes, so must the library.

(The alternative would be to write every possible program, so that when someone comes to you with a new problem, you've already got a program for it. The problems with this approach are obvious.)

Furthermore, the Open/Closed Principle was originally coined in 1988, when our understanding of OOP was still young. Bertrand Meyer probably had extension through inheritance in mind when he coined it, but it turns out you can't override arbitrary methods from a class without your subclasses breaking further down the line when the parent class is updated. In other words, the base class must be designed up front with inheritance in mind and you can only safely override whatever the base class says you may override. The promise of being able to handle unforeseen tasks through ad-hoc inheritance was false. This is known as the fragile base class problem.

I'd argue that a more useful interpretation of the open/closed principle is that when the scope of your requirements expand to include a new task, your code shouldn't be hard-coded to that particular instance of the task. E.g. If you now need to sort a list of dates, it's very likely you'll need to sort other kinds of things as well. Rather than writing a function that only sorts lists of dates, you might as well write a function that can sort lists of anything that can be compared.

Once you acknowledge that it's insane to anticipate every possible change, "elegance" is simply finding the most clear, simple, or "beautiful" way of expressing the solution to your particular problem.

3

it can also be vaguely characterized by verifying that there is nothing left to take away, in a sense that the mental model you have in your mind is expressed directly and unobscrured in the language of your choice (programming language, object oriented design, relational schema etc.), without distractions.

I'm not sure I agree with this. I know of many barebones, or concise solutions for a problem that are directly and clearly implemented without being elegant. I mean, if I brute force your password, the code will be a clear description of what I'm trying to accomplish - but the solution itself isn't elegant in the least.

To me, an elegant solution is one where things "fall away". Consider the composite pattern. Many times, judicious use of this pattern yields this sort of effect. Without the pattern, the "is this a single thing, or is it many things" problem has to be propagated everywhere that uses the interface. By using the composite pattern, you hide away that complexity so that consumers need not care.

Elegant solutions are ones that don't just solve a problem, but prevent problems from ever happening. So no, striving for elegance isn't counter productive.

2

When you take time to study elegance outside the constructs of code, you gain an appreciation for what truly is elegant. According to the great art masters (like Da Vinci), and some of the greatest mathematical minds (like Einstein), a very common attribute of elegance is simplicity.

What Elegance Is Not

In reading your question, it seems to me that you are equating elegance with fancy solutions that use complex black boxes that hide implementation details from you. That is the furthest thing from elegance, for the following reasons:

  • Hidden details and swallowed exceptions can hide what the real problem is.
  • Reflection as a major feature of a framework/etc. makes it very difficult to trace what is going on in an application.
  • It muddies understanding of the code, and of the problem domain.
  • It requires you to learn a new language and thought process in addition to the language you are using.

These are attributes of the cumbersome problems that probably started as a good idea, and then carried too far. These issues all complicate maintaining code, have difficult to grasp concepts, and in general do not improve the bottom line. Even if some people have a simple solution and tout solutions like this as "elegant", if it doesn't remain elegant in a more complex solution then it truly is not elegant.

Defining Elegance

Elegant code simplifies the solution in a way that is comprehensible by all members of the team. If you are working with an object oriented language, an elegant solution does not force you to change the way you think in terms of a functional language. The reverse also applies. The following are attributes of elegant solutions:

  • Debugging and following code flow is very easy
  • It greatly reduces clutter code that hides the intent of a method
  • The concepts and method of thinking fit well within the language used, and truly elegant also makes the problem domain easier to comprehend in the code.
  • It improves the efficiency of the developers working with the code

Can we learn newer ways of approaching a problem that are more elegant than the ones we are using? Absolutely. Is it worth retrofitting existing code with the newer, simpler, and more elegant solution? Not always. That's a project management decision that requires you to balance the cost of the change against what gain that solution will provide.

Should We Pursue Elegance?

The pursuit of elegance is synonymous with simplifying code and making it more understandable. Anything you can do to lighten the already heavy cognitive load a developer has when maintaining code, the better. Sometimes all you can afford to do are small improvements (light refactoring) here and there as you go in and work on code. Sometimes there is so much code rot due to changing requirements that you really need to rewrite a section of the code to satisfy the current needs better and enable new features. It doesn't change the fact that pursuing elegance is synonymous with making your life easier and improving the maintainability of the code.

Not the answer you're looking for? Browse other questions tagged or ask your own question.