40

Perfectionism may be good and bad when programming.

  • When and where do you draw the line when you are problem solving?
  • When do you decide when a solution is overkill, too general or simply too futuristic?

Please comment if the question is unclear.

Robert Harvey
  • 198,589
  • 55
  • 464
  • 673
Amir Rezaei
  • 10,938
  • 6
  • 61
  • 86

10 Answers10

42

KISS and YAGNI, especially YAGNI.

Only engineer a solution for the things you know you're going to need soon. Don't engineer it for the things that might be needed in two years, because most likely you're going to need very different things and will have to re-engineer it anyway.

The moment you start talking about "with this design at some point in the future we could do X, or even Y", instead of "this design allows us to do customer requirement Z in the next release", that's when you're getting into architecture astronomy.

In response to the comments:

  • KISS = Keep It Simple, Stupid = pretend you're a moron and have to understand the design
  • YAGNI = You Ain't Gonna Need It = stop pretending you can predict the future in your design
Joeri Sebrechts
  • 12,922
  • 3
  • 29
  • 39
  • 5
    +1 - It's hard enough solving the problems we know we have, without also trying to solve problems we think we might have. – Jon Hopkins Jan 14 '11 at 12:37
  • 6
    I like this, but a clear definition of the acronyms would be helpful. I had never heard of `YAGNI` until today. – Philip Regan Jan 14 '11 at 13:51
  • +1 for Philip that learn something today ! +1 for KISS as well. –  Jan 14 '11 at 15:57
  • Well, the answer is good. Though obviously any interface (be it to permanent storage (files), network, or IPC) must at least be versionable or you *know* your re-design will make back-compat impossible. – Deduplicator Apr 04 '15 at 14:43
7

Use an iterative approach and this problem mostly goes away. You code should run on the first day and nearly every day after that. Meet the minimal requirements first and add more as you have time. Never stray off big change where you can't run your code for a long time.

6

A solution is overkill when the extra time taken to complete it is worth more than the potential negative impact from when the easier solution is finished to when it would next be naturally upgraded/amended.

Basically you are trading time now with time later. If your spending more time now then you will save later, you are doing it wrong. If you're really over engineering, you are spending time now that doesn't affect how much time (or even makes it more) you spend later.

You get better at working this out the more experience you have. The best way to go about things (from my experience) is to do what you need now, but in a manner that is most easily augmented should later requirements demand it. Working out how to do that is the tricky bit.

Dan McGrath
  • 11,163
  • 6
  • 55
  • 81
6

I used to be very perfectionist (spending time creating frameworks, not solutions).

But the thing that really helped me accelerate my production was learning and following BDD/TDD principles, including the outside in principle (which I have found particularly hard to learn to embrace).

This really taught me not to write a single line of code before a test exists for it. But the unit tests doesn't exists either before an acceptance test exists for it. And the acceptance tests comes from real user needs.

So therefore, all lines of code originate from a real user need.

If you're not familiar with the outside in principle, it dictates that you start writing tests for the outermost layer in your application (i.e. the GUI in virtually all cases) using test doubles to simulate the behavior of the lower layers. Then you implement just enough for the tests to pass. This implementation of the top layer then dictates the tests you need to write for the next layer, etc, until you hit the bottom layer of your application.

Kamafeather
  • 335
  • 1
  • 2
  • 7
Pete
  • 8,916
  • 3
  • 41
  • 53
5

I notice I get better at this by experience.

When I was (very) young I always went for the most perfect solution, no compromises. Now I'm better at keep things like budget and time in mind.

Thomas Stock
  • 1,810
  • 13
  • 18
4

The time limit draws this line pretty clear.

Simon
  • 1,774
  • 12
  • 15
  • 1
    Good point, but a bad solution may need more time to fix in future. – Amir Rezaei Jan 14 '11 at 12:28
  • I think you have to make a judgement on what is "good enough" software. The line should be defined by the specification and your common sense. – Nobody Jan 14 '11 at 12:30
3

My boss does actually :)

I must admit I'm getting better, but I'm still not much for compromise. Thankfully I've got my boss to rein me in ;)

I'd like to raise another problem than overengineering though, as overengineering is quite easy to detect.

My main problem is with refactoring. The problem is that most of the times, even though I tried to write the code as good as I could, I didn't know back then what I do know now (seen more codes, more patterns, new idioms, new issues, new solutions). And so, even though it works, I now know better ways to do it:

  • Ways that would improve usuability and reduce the chances of getting a bug in
  • Ways that would reduce the dependencies, improving compile-time

However, it's working as it is, and therefore refactoring it is not a priority, and the truth is that it's nagging at me; I understand the economic reasons, and I understand the client expectations (they don't see the code and prefer new features and bug fixes), but I do wish I had time to work on it still.

For now, I just follow my boss' order, but I must admit I'm feeling uneasy knowing that the code delivered into production is not the best I could come up with now. Perfectionism, I guess.

Matthieu M.
  • 14,567
  • 4
  • 44
  • 65
2

Both professionally and personally, the standard I try to apply to myself is:

Be content with winning.

If my code solves the problem it's meant to solve and doesn't create any new problems*, it's very likely time to move on. When you learn to set the bar as high as it needs to be set, "Good enough" becomes, well, good enough.

Perfection is like the speed of light: you'll never get there, but there's no limit to the energy you can expend trying.

(* -- Note that "Buggy" and "Difficult to maintain" both firmly fall under the heading of "New problems." So I don't call it complete until the code has been tested, had the superfluous bits trimmed, and had the comments/API documentation brought up to date.)

BlairHippo
  • 8,663
  • 5
  • 41
  • 46
0

With experience I've realized that perfectionism is not even possible until I've got at least a few years under the belt in any particular context (language, framework, platform, standard). As a newbie there will be all sorts of idiosyncrasies which you will not be aware of (escaping, precedence, reserved words, syntactic sugar, timeouts, asynchronous calls, undocumented features & bugs), so I just try for a good solution, all the while learning as much as possible. Importantly, I always try to make it simple to refactor the result - Modular architecture, comments where needed, and no clever tricks.

l0b0
  • 11,014
  • 2
  • 43
  • 47
  • Perfectionism is not possible even after MANY years of experience; that is, if you ever want to actually DELIVER anything. The most valuable thing experience teaches is when to recognize "good enough". – Jeff Knecht Jan 14 '11 at 20:45
0

I, like many other programmers, have a lot of legacy code to maintain. The temptation to redo it all will always be there, but I've essentially boiled it down to one principle:

Am I (or someone else) going to have to figure this out again?

That usually takes care of a lot of spaghetti code into somewhat more manageable spaghetti-chunk code. Abstract away some of the chunks, throw in your tests, and now it doesn't look so much in need of perfection.

MPelletier
  • 2,038
  • 1
  • 18
  • 27