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.

Dan
  • 2,902

16 Answers16

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.

Jim G.
  • 8,035
BlairHippo
  • 8,693
  • 5
  • 42
  • 46
25

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

17

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.

Karl Bielefeldt
  • 148,830
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.

7

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.

maple_shaft
  • 26,570
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.

DKnight
  • 3,887
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.

Becuzz
  • 4,855
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.

Mike Dunlavey
  • 12,905
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 :-)

Dan
  • 2,902
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.

Philip
  • 6,762
  • 29
  • 43
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.

GrandmasterB
  • 39,412
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....

Vector
  • 3,241
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.

Heath Lilley
  • 1,280
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.

GlenPeterson
  • 14,950
-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.

Random42
  • 10,520
  • 10
  • 52
  • 65