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.

17 Answers
17

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.

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.
–
BlairHippoJul 11 '11 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.
–
DanJul 11 '11 at 15:00

2

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.
–
BlairHippoJul 11 '11 at 15:04

6

@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!
–
DanJul 11 '11 at 15:26

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.
–
DanJul 11 '11 at 14:17

6

+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.
–
BlairHippoJul 11 '11 at 14:45

2

Great quote, but not really an answer to the OP's question.
–
Jim G.Jul 11 '11 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?
–
user8Jul 11 '11 at 18:56

1

-1: Does not answer the OP's question in the slightest.
–
Thomas EdingMay 15 '13 at 20:29

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.

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.

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.

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.

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.
–
deadalnixJul 11 '11 at 14:39

2

@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.
–
HLGEMJul 11 '11 at 17:55

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) 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.

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.
–
BlairHippoJul 11 '11 at 14:41

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.

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.

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.

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....

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% 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.

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.

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...