79

Do you know that feeling when you just need to show off that new trick with Expressions or generalize three different procedures? This does not have to be on Architecture Astronaut scale and in fact may be helpful but I can't help but notice someone else would implement the same class or package in a more clear, straightforward (and sometimes boring) manner.

I noticed I often design programs by oversolving the problem, sometimes deliberately and sometimes out of boredom. In either case, I usually honestly believe my solution is crystal clear and elegant, until I see evidence to the contrary but it's usually too late. There is also a part of me that prefers undocumented assumptions to code duplication, and cleverness to simplicity.

What can I do to resist the urge to write “cleverish” code and when should the bell ring that I am Doing It Wrong?

The problem is getting even more pushing as I'm now working with a team of experienced developers, and sometimes my attempts at writing smart code seem foolish even to myself after time dispels the illusion of elegance.

6
  • 5
    slightly off topic, but thedailywtf.com/Articles/…
    – user81
    Jul 11, 2011 at 20:43
  • @Joe: this is very on-topic, thanks! I've read the article but it's a pleasure to rediscover it now.
    – Dan
    Jul 11, 2011 at 21:15
  • 34
    Debug a lot of clever code... that should do the trick.
    – Dan Olson
    Jul 11, 2011 at 23:31
  • @Joe the database of databases link in that article is to die for.
    – jnewman
    Jul 12, 2011 at 4:34
  • Short answer: shortest, simplest code wins. Eliminate duplication, but don't add layers "just because". Fowler's Refactoring may give you some insight. Aug 28, 2012 at 19:04

17 Answers 17

56

The problem is getting even more pushing as I'm now working with a team of experienced developers, and sometimes my attempts at writing smart code seem foolish even to myself after time dispels the illusion of elegance.

Your solution lies here. I'm presuming that "experienced" in this context means "more experienced than you." At the very least, you clearly respect them. This is a valuable learning opportunity -- assuming your ego can take the hit. (Irksome things, egos. A pity we need them so.)

Do you have code reviews with these folks? If so, if they're not doing it already, explicitly ask them to call you on your bullshit. Mention that you've noticed a tendency in yourself to overdesign, to use a meticulously designed top-of-the-line pneumatic jackhammer (preferably wielded by some sort of automated road-worker android) when a simple claw hammer would be more than sufficient.

You may often find yourself squirming in your seat while your face turns red during the code reviews. Endure it. You're learning.

Then, once you've got a few of these under your belt, pay attention to the moments where you suspect you're maybe possibly overdesigning. When those moments come, ask yourself: "If somebody calls me out on this during code review, can I defend my solution as the best one available? Or is there a simpler solution I'm forsaking?"

Sometimes, peer review is the best way to get a good look at your own work.

6
  • Thanks for a really good answer. No, we don't have code reviews, mostly because the project is big and the customer's resources are very limited. But I guess I can test myself by asking "can I defend my solution as the best one available" at the end of each day.
    – Dan
    Jul 11, 2011 at 14:45
  • 8
    No code reviews? Urk. I'd write something all self-righteous and horrified, but I've worked in that environment, too. They're time-consuming and kind of a pain in everybody's ass, but they really are valuable for both the project at hand and your own personal development. If the topic of "Should we maybe be doing code reviews?" ever comes up, make sure you're down as "Hell yes!" And if they're not slammed with their own looming deadlines, you could ask co-workers you respect to give work you're not sure about an informal code-review-lite.
    – BlairHippo
    Jul 11, 2011 at 14:50
  • 1
    Well, the project is kind of a startup and due to some planning mistakes, on the client side as well, we hit the situation when we really need to deliver quickly or else it isn't worth the effort. I just spoke to our PM and he confirmed aggressive deadline is the only reason why we don't do code reviews, at least now. If the startup goes successful and time constraints get more relaxed, we might be doing the reviews in the future.
    – Dan
    Jul 11, 2011 at 15:00
  • 3
    Oh my. Sounds exciting -- with all the good and bad connotations that word carries with it. :-) Good luck, mate; here's hoping you're at the beginning of something great.
    – BlairHippo
    Jul 11, 2011 at 15:04
  • 8
    @BlairHippo: I just followed your advice, calmed down and kindly asked the colleague who pointed at the problem introduced by my changes to do informal reviews with me, and he agreed to. This also helped to remove certain awkwardness from our conversation (as in "you write complex code and I have to fix it.."). Thanks!
    – Dan
    Jul 11, 2011 at 15:26
23

The best thing to do is to keep in mind Brian Kernighan's maxim:

“Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.”

6
  • 1
    I wholeheartedly agree with the quote but the question is how to overcome the temptation to be the clever boy? You can be told not to eat ice-cream when you're ill but sometimes it doesn't help.
    – Dan
    Jul 11, 2011 at 14:17
  • 14
    +1 for a maxim that every code monkey should know by heart, but -1 for not offering the OP any insight on how to apply it to his own work. So it all evens out to no arrow clicking.
    – BlairHippo
    Jul 11, 2011 at 14:45
  • 2
    Great quote, but not really an answer to the OP's question.
    – Jim G.
    Jul 11, 2011 at 18:53
  • 5
    Hi Daniel, we're looking for a lot more than a quotation: the site's only useful when questions are paired with long, thoughtful answers filled with experiences, facts, and references. Is there anything more, from your own experience, you can add?
    – user8
    Jul 11, 2011 at 18:56
  • 2
    -1: Does not answer the OP's question in the slightest. May 15, 2013 at 20:29
16

There are usually at least three solutions to software problems of any significance: the obvious way, a non-obvious complex way (clever), and a non-obvious simple way (elegant). A quote about authors is applicable here:

Put down everything that comes into your head and then you're a writer. But an author is one who can judge his own stuff's worth, without pity, and destroy most of it. — Colette

You will not be able to write elegant code until you can judge your own code's worth, without pity, and destroy most of it. If you judge elegant code by the end result, it looks deceptively easy, but it requires slowing down, going through many drafts, seeking the advice of others, and excising what doesn't sit right on the page. That means even if your code is working perfectly, you ask yourself or a colleague why something doesn't feel right, until you're satisfied with the answer. Maybe it feels too long, or repetitive, or you feel the compiler should have been able to catch a certain kind of bug. Most programmers with a modicum of experience can recognize inelegant code easily. The trick is to figure out why.

That's the methodical way to write more elegant code. It also frequently requires a flash of insight that helps you look at a problem in a new way. This is more difficult to attain, but it helps to slow down and just think about a problem before you dive into coding. When you find a good solution, look for a better one. Reading other code helps. Taking classes or reading books on best practices helps. Learning other programming paradigms helps. Asking for advice from colleagues whose code you admire helps.

1
  • 3
    That reminds me of an old mathematician's quote: "For every problem there is a solution that is simple, elegant, and wrong.". Jul 15, 2011 at 13:52
9

I would add to existing answers, develop in a TDD manner, so you first write tests about what your code should do, and then implement to make your tests go green. This way, you'll be only fulfilling the requirements that the tests are imposing. Since you'll be writing the test, it's a good way to a self-disciplined approach to developing.

2
  • I definitely try to impose this on myself whenever there's time.
    – jnewman
    Jul 12, 2011 at 4:38
  • Writing tests afterwards is also a good way to spot huge mistakes in your code. It is somehow self-reviewing. But TDD is clearly the best approach if you are starting fresh.
    – vanna
    Aug 28, 2012 at 19:06
6

When working for a large and dynamic team that spans across many different skill sets and years, development has a natural progression to be "dumbed down" to the lowest level of the most conservative or most intellectually deficient member of the team, current or historical.

This may not necessarily be a bad thing because clever code may be harder to debug, harder to convey in a technical specification, and take longer to write, slowing down the development time.

There are times when clever code is important, such as when clever code gives efficiency and performance gains later in the maturity cycle of the software when performance becomes a requirement.

Clever code also has a way of conveying a quicker to develop and more readable and understandable code to a team that may not be exposed to a new language feature or library call. For instance, when I was first introduced to Linq by a junior developer I had an immediate disgust to it as unnecessary, hard to debug, foolish, and "clever". After playing with it myself and discovering just how useful and powerful Linq queries can be, I invested the time to learn it and my DAL code has never been more clean and readable, as well as easier to debug and extend.

I regret not having an open mind before and wish I would not have been so harsh on such a "clever" junior developer.

My point is that "clever" code SHOULD be suspect, but we should not go on crusade against it because it may stifle creativity and innovation.

EDIT: I just realized I didn't fully answer your question. If you have the capacity in your project to very easily write clever code then perhaps the team should adopt stricter coding standards to follow a uniform and distinct template and style. This will help draw out the lines of your sandbox so you don't wander off into the street chasing after a ball.

6

If 20% (your % may vary) or more of your added lines need to be documentation - it's time to step back and rethink.

I really think you should strive to be clever, it's a natural side-effect of getting more proficient. Giving yourself a general guideline like % of comments needed to make yourself clear is a good way to force yourself to stand back and evaluate if using that new thing you learned is a wise choice or just a way to show off your new toy.

5
  • 3
    I tend to consider documentation/comments as a failure. When you need to document/comment something, it means in a first place your code isn't clear. Unhappily, this is a unrealistic goal and we needs docuemntationat some point. Just keep in mind that this part of the code should be reduced to a minimal amount.
    – deadalnix
    Jul 11, 2011 at 14:39
  • @deadalnix: Not a bad point. I suspect my % would be higher than most because I usually code in an otherwise dead and heavily macro'd assembly language. Harder to read and every new hire has to learn the langague, more commenting is required as a result.
    – DKnight
    Jul 11, 2011 at 14:45
  • 3
    @deadalnix - documentation to explain the how is a sign your code is unclear. Documentation to explain the why is very much needed. I've seen all too many pieces of code that I could understand what they did but not why they decided to do it that nonintuitive way. That makes it very hard to maintain.
    – HLGEM
    Jul 11, 2011 at 17:55
  • @HLGEM This is arguable. The unclarity of the code may come from badly designed libs/API, from unclarity within the conception itself like bad separation of concerns. We are living in the real world and our capacities are finite, so we definitively require documentation, but each we time need it, it means that someone has written unperfect code. No documentation is not something you should do - don't even think about it, but something you have to think about all the time to keep improving in the right direction.
    – deadalnix
    Jul 11, 2011 at 18:14
  • @deadalnix - perfect code is never a practical solution in the real world.
    – JeffO
    Jul 11, 2011 at 20:53
5

I believe that one way to find out if your code is too "clever" is to take a step back and ask yourself the following:

If I were to give a printout of this code to someone who has never worked on this project / code, would they be able to read it and describe back to me what the function does (after giving them some brief context)? If not, how much explaining would I have to do? How would I explain this to someone taking CS101?

If it turns out that you would have to walk someone through every line or most lines in a method or class, it's probably too clever. If you have to explain language constructs (LINQ for example) to someone who is unfamiliar with it, that is probably OK. If you have to look at a line and think about it for a bit before you can explain it, your code needs to be refactored.

1
  • I've heard this called "Rubber Ducking" when applied to problem solving; when stumped, try explaining the problem to somebody who knows nothing about it (like, you know, your rubber duckie) and see if the solution doesn't drop into your lap. I have to think it would work for this, too.
    – BlairHippo
    Jul 11, 2011 at 14:55
5

I can't resist trying something clever.

So I do it on a toy project, on my own time, at home.

When the novelty wears off - problem solved.

2

1) Get burned by it before so that you know it's a bad thing. Attempting to debug something from long ago that written cleverly is great fun. I think you have that covered.
2) Comment your code, explain what you're doing before each section of code.
3) If you find yourself struggling to explain it, or feel the need to insert a diagram, then what you've just done is too clever and could probably be done more cleanly.

Clever solutions to problems can be fantastic, until you have to debug or expand them. Sometimes it's the only solution. If you can accurately describe just what the hell it does, and how it does it, clever solutions can be acceptable.

I usually use commenting to describe what I'm doing with a section of code. If it seems in the least confusing, I also describe how I'm doing it. Ideally, the code should be straight forward and self explanatory. But if I struggle to explain how I did what I just did, then it's a clear sign that I need to step back and try again.

2
  • 2
    The comment trick works for me, too. Among other reasons, I always include a comment block above any non-trivial subroutines as a kind of final sanity check. If I find myself having to do a lot of explaining (or even, on occasion, apologizing for) convoluted or obtuse sections of code or weird input params or whatever, that's a warning sign I may need to rethink the solution a bit.
    – BlairHippo
    Jul 11, 2011 at 14:41
  • @BlairHippo HA! "final sanity check" I like that.
    – Philip
    Jul 11, 2011 at 14:52
2

Probably a good way to start writing simple code is to release cleverness passion on a project that asks for cleverness. The rest of the answer is specific to .NET but I'm sure one can find similar level projects in any other language.

There are open source dependency injection frameworks to work on which just ask for Expression tricks knowledge, there is F# and wonderful range of tasks one may want to try it for.

If you're into math (and that's language agnostic), there is Project Euler for you.

Last, but not the least, in the .NET world there is Mono Project that has a lot of areas that need developer attention, some of them pretty complicated. How about contributing to an open source static .NET code analyzer tool? There's some IL analysis involved, as well as high-level stuff. Jb Evain always works on something interesting, whether it is Cecil reflection library, Expression support or a .NET decompiler.

If nothing fits, just start your own mocking framework :-)

2

Do you know that feeling when you just need to show off that new trick with Expressions or generalize three different procedures?

No

This is one of the reasons why I always say that its a good thing when new developers get tossed into a big ol' mess of undocumented speghetti code to maintain and refactor. It'll teach them the realities of maintaining overly 'clever' code that they didnt write, and hopefully instill some empathy for the poor schmuck who'll have to debug their code 5 years from now.

1
  • I think this is more likely to make them frustrated and think that THEIR code will be much better and elegant than the noobs who wrote THIS mess. Nobody writes code with the intention of making it hard to maintain.
    – sara
    May 9, 2016 at 15:00
2

I think the topic is well chosen. It's "cool" to write a line of Perl that does ten thousand things all at once, but then it sucks when you have to revisit it.

On a different note, clever or not, code must be documented. There is an inherent impedance mismatch between the industry-accepted programming languages and the high level concepts that we as humans are accustomed to in our thinking. Self-documenting code is simply not realizable - until it becomes natural language, that is. Even Prolog code needs to be documented, as, however high level it may be, it is still rather formal.

Fine grained imperative code serves to implement coarse grained plans -- that needs to be documented. I don't want to have to read through all 50 lines of the method when a quick 3-line roadmap comment will do.

Later edit: A more eloquent example is one that transcends computers. A book may be very well written, but we often want to process it at different levels of abstraction. Often, a summary of the book will do, and that's what comments can offer to code. Of course well abstracted code can go a long way towards self documentation, but it can't give you all the levels of abstraction.

And comments can also act like sidenotes in a book, when we need to explain the reasoning process behind a claim in the main text without derailing it.

With this context, I find that my prior statement referring to natural language transcending the need for comments is incorrect. Even natural language, like in a book, may lend itself to documentation, to explain in a sparse manner the abstraction embodied in the text, or to provide detours without derailing the main text. With the note that well abstracted code may already have gone a long way towards being self documenting.

Last, but not least, comments can help the coder keep at a high level of abstraction. Often times I realize that two consecutive comments I included in a list of steps don't speak at the same level of abstraction, which immediately warrants a critical look at what I'm doing with that code.

Certain problems transcend coding and affect coding just like other activities. Comments can provide that help in clarifying the rationale behind, and facets of our code, and I find them a pleasant companion that speaks a softer language to benefit the person for a change.

1

How? Keep showing your code to those experienced developers. and when you get blasted for being sophomoric and showy, suck it up, and ask them how they'd do it and why (in a non-confrontational manner of course).

Edit in light of -1:

Many moons ago, I was in the same situation - I had one boss who would cringe every time I used a pointer in Delphi or the 'with construct', another one who threatened to fire me if I didn't stop shortcircuiting all my booleans with 0-1 and using single letter variables everywhere.

I learned because I asked why and they took the trouble to explain because they thought I might amount to something - LOL....

1
  • 1
    Hi Mikey, we're looking for a lot more than a one-liner: the site's only useful when questions are paired with long, thoughtful answers filled with experiences, facts, and references. Is there anything more, from your own experience, you can add?
    – user8
    Jul 11, 2011 at 18:58
1

Do I feel the need to show off? No, not anymore. How did I get past it? Like most people get past any other bad habit... conscious and deliberate practice of proper techniques. You do it enough you will understand the value of best practices and through their constant use you will develop good habits.

Also realize that by focusing on functional software, that is on time and easily maintained you will get the recognition you seek. Experienced developers will come to you and say "Man that module you wrote was well designed. I only had to implement one component to plug it into my project." as opposed to "I had to rework that entire module you wrote just to use it in another component? Have you even heard of Bob Martin or Ward Cunningham?"

TLDR: You are not alone. Recognition of skill is best achieved as a byproduct of solving problems the smart way.

0

For me, overly-clever code often strives to solve imaginary future requirements instead of focusing on today's requirements. Big trap!

0% over-complicated code is not an achievable goal. Maybe not even the best goal to strive for. Over-complicated code is bad, but you have to try new things in order to grow as a programmer. You should not try them out on production code if you can avoid it. Unlike machines, humans make mistakes.

Code reviews help. Spending years fixing other people's "clever" code helps. Staying focused on what the client really needs today helps.

Schools and business have crews of clean-up and maintenance people on staff. Code needs cleanup and maintenance too! When possible, clean up the messes (your own especially)! I think that's the best one can do.

0
-2

In addition to the good advices given until now (code review, debugging, TDD approach) you should (re)read from time to time the (best books imho) on good coding practices:

  • Pragmatic programmer
  • Code Complete
  • Clean Code

and others, depending on the technology you use.

-2

Just remember YAGNI - You Ain't Gonna Need It.

programmer should not add functionality until deemed necessary...

YAGNI is a principle behind the XP practice of "do the simplest thing that could possibly work" (DTSTTCPW). It is meant to be used in combination with several other practices, such as continuous refactoring, continuous automated unit testing and continuous integration. Used without continuous refactoring, it could lead to messy code and massive rework...

According to those who advocate the YAGNI approach, the temptation to write code that is not necessary at the moment, but might be in the future, has the following disadvantages:

  • The time spent is taken from adding, testing or improving the necessary functionality.
  • The new features must be debugged, documented, and supported.
  • Any new feature imposes constraints on what can be done in the future, so an unnecessary feature may preclude needed features from being added in the future.
  • Until the feature is actually needed, it is difficult to fully define what it should do and to test it. If the new feature is not properly defined and tested, it may not work correctly, even if it eventually is needed.
  • It leads to code bloat; the software becomes larger and more complicated.
  • Unless there are specifications and some kind of revision control, the feature may not be known to programmers who could make use of it.
  • Adding the new feature may suggest other new features. If these new features are implemented as well, this may result in a snowball effect towards feature creep...
1
  • 3
    While this may be true - more detail would make this a much better answer.
    – ChrisF
    Jul 11, 2011 at 14:34

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