82

Very frequently, I am stuck when choosing the best design decision. Even for small details, such as function definitions, control flow, and variable names, I spend unusually long periods perusing the benefits and trade-offs of my choices.

I feel like I am losing a lot of efficiency by spending my hours on insignificant details like these. Even though, I know in the back of my mind that I can change these things if my current design doesn't work out, I have trouble deciding firmly on one choice.

What should I do to combat this problem?

2
  • 4
    xkcd covered this today.
    – zzzzBov
    Commented Jun 11, 2011 at 2:18
  • Discuss with a colleague on a whiteboard. This frequently helps clarify the matter and if you can agree then it has a good chance for being a good choice
    – user1249
    Commented Aug 28, 2011 at 20:10

16 Answers 16

47

Two simple rules:

  1. Do the simplest thing that could possibly work.
  2. Refactor continuously.

As you begin to do each of these things, you will gain confidence that you can make simple decisions now without compromising your ability to respond to change later.

Remember that future proofing means making code easy to change, not trying to anticipate every possible way your code might need to change.

7
  • 5
    Continuous refactoring is reasonable only if you have good test coverage. So I would say "Write a unit test. Then do the simplest thing to make the test pass. Refactor. Repeat." Commented Jun 10, 2011 at 22:49
  • Definitely agree. "Red, green, refactor" is the way to go. Commented Jun 10, 2011 at 23:18
  • 7
    Lovely little tidbit from the XP handbook, but really not great advice when taken out of context.
    – Aaronaught
    Commented Jun 12, 2011 at 20:14
  • 4
    Out of context, it is literally equivalent to cowboy coding. See Fowler's Is Design Dead? which cautions against cherry-picking principles from XP and similar methodologies. Maybe you are an excellent designer and coder and are intrinsically and implicitly able and motivated to maintain conceptual integrity while refactoring, but most programmers aren't, and giving them this advice out of context is irresponsible (although they all love to hear it, since it means less work for them).
    – Aaronaught
    Commented Jun 13, 2011 at 13:50
  • 1
    "Do the simplest thing that could possibly work" doesn't require any extra context. Refactoring does, but how would someone who doesn't know the context learn how to refactor but by learning the context? Commented Jun 13, 2011 at 16:36
10

Usually when I feel that way it means I need to try:

  1. Stand up, walk around, and make sure all the biology is working OK.
  2. Go over to a whiteboard and draw until I get a feeling of confidence.
  3. Find a "design complaint buddy" who you can just talk the problem through with.

If the problem involves syntax and small pieces, then:

  1. Satisfy yourself that, even if it is ugly, it is nicely encapsulated somewhere, and represents a purely local kind of cruft.
  2. Add TODO markers or just comments which explain why the code bugs you.
  3. Move on to the next task.
1
  • +1 for both the first and second #2s. Drawing boxes, lines, and labeling and getting the big pictures usually helps me decide between options. If you have a nice code analyzer that tracks tasks (Hudson can track TODOs and displays them nicely in your builds), you can easily track the things you don't like.
    – Randy
    Commented Jun 12, 2011 at 17:28
7

It's very easy to think yourself into inaction. Even if you manage, somehow, to come up with the best solution right now that could easily change before you complete the project, and then what?

It's better to pick a decent solution and run with it, than to sit and dither over what the best solution would be. The best solution is elusive and worse, subjective. If the requirements change even slightly, your solution may turn out to be worse than a solution that you discarded because it wasn't the best at the time.

2
  • I am aware of this, but I still have a hard time choosing any single choice. Commented Jun 10, 2011 at 19:56
  • @anne: It's better to do something constructive immediately, than the right thing too late. The only thing that is sure to be the wrong thing is to do nothing. Commented Jun 10, 2011 at 20:00
5

I'm learning to avoid analysis paralysis as well, so kudos to us =) This often happens because we want to do the "best design". In reality, "best" is in the eye of the beholder. My formula to avoid analysis paralysis, is to apply the good enough design principle. How I do that? I bring variables like time-constrains, schedule and ask myself what is the simplest design that can get the job done(this doesn't mean the easiest) without compromising quality, but at the same time, I make sure that is a testable and a open for extension closed for modification (OCP) design as well. What do I mean by testable and OCP? Well, instead of looking for what I considered best, I considered a design that can tell me when things are going bad and try to do just enough code that allows me to refactor and improve later. Also, try to separate the code that will change with the code that stays the same. Refactoring becomes easier, because the code that is not supposed to change is safer from your future you or someone else.

4

How about letting your gut feeling decide for one of the options? That should go pretty fast and combine well with timeboxing, which ammoQ also proposed. You could try a limit of 1 minute if the options are already established, or 2 minutes if you have to define them first. Or whatever seems appropriate (defined beforehand). When learning to listen to your gut instinct, your intuitive choosing will become faster and better with practice.

In case you're plagued by worries about the possibility of choosing non-perfectly, here are some thoughts for addressing that:

  • If there were an option with a clear edge over the others, you wouldn't ask yourself which one to choose. So by that reasoning, whenever you are undecisive about some choice on a not too complicated matter, that indicates that the options are all in all quite equal; so there is not much to loose by just opting for any one of them.
  • That being said, intuition is not random at all, but a pretty good, educated guess for the optimal solution. Often better than what one would come up with through endless rummaging.
  • Catering to perfectionism, one could rate swiftness of decision higher than optimality of choice when semi-consciously evaluating one's performance. Which makes complete sense with unimportant choices, but is not trivial to keep in mind.

Good luck! :)

2

I suffer from the same problem. For small problems, the way I try to deal with it is to go with the first design I think of that isn't stupid. There's no point trying to find an optimal design; it's difficult if not impossible to reason about all of the nuances of any design you may think of without writing it up. As you code, you'll find that you can make small improvements. Done right, I find it's fairly easy to converge on a reasonably good solution this way.

For bigger problems, I think there is merit in thinking through your options first, but timebox it. Big problems have big solution spaces, you can't evaluate every possibility, neither should you try to.

TLDR; Pick a reasonable solution, improve it as you go.

This is also relevant:

The ceramics teacher announced on opening day that he was dividing the class into two groups. All those on the left side of the studio, he said, would be graded solely on the quantity of work they produced, all those on the right solely on its quality. His procedure was simple: on the final day of class he would bring in his bathroom scales and weigh the work of the "quantity" group: fifty pound of pots rated an "A", forty pounds a "B", and so on. Those being graded on "quality", however, needed to produce only one pot - albeit a perfect one - to get an "A".

Well, came grading time and a curious fact emerged: the works of highest quality were all produced by the group being graded for quantity. It seems that while the "quantity" group was busily churning out piles of work - and learning from their mistakes - the "quality" group had sat theorizing about perfection, and in the end had little more to show for their efforts than grandiose theories and a pile of dead clay.

from http://www.codinghorror.com/blog/2008/08/quantity-always-trumps-quality.html .

1

I think it goes away with a little experience. Most of my paralysis happens because I try to imagine what the code base will look like much farther ahead than I need to so to overcome it I just do the simplest possible thing that will work and then move on. Once the project has some definite shape the repetitive code units start to stand out and it's easy enough to abstract the repetitive patterns and simplify the code.

0

Create a prototype. Remember, a prototype is made to be thrown away, so it doesn't matter what functions, variable name or even grand architecture you use. You just building it to prove that it works.

Once you've created it, and thrown it out, I'd be willing to bet you'd have an easier time making those decisions.

3
  • You should never throw away a prototype because maybe you can expand upon it later when you add a feature. Or maybe you need to test a bug with a SSCCE. I always source control all of my prototypes in a seperate place.
    – maple_shaft
    Commented Jun 10, 2011 at 19:59
  • 2
    I think the idea behind "throw away" isn't that you lose data, but that you shouldn't use prototypes as the foundation for a program since the whole point of prototypes is to experiment with the freedom to make mistakes.
    – Darien
    Commented Jun 10, 2011 at 21:05
  • prototype in a branch, do the necessary testing, and create a clean version in core.
    – zzzzBov
    Commented Jun 11, 2011 at 2:16
0

I suffer from this problem too. What I would say is that you don't have enough completion incentive.

For example, when I was writing rendering code, then I had a large completion incentive because I knew that if I got on with it, I'd get to see the system in action and think of how awesome I was for texturing a quad, or transforming a vert. But now that I'm re-factoring (attempt 4, if you would like to know) then I'm suffering because it's a lot of work and even if I finish, I'm just gonna see the same old quad. And I really don't want to have to refactor again and I'm sick of seeing the same old quad over and over again, and it's not a reward for me anymore.

You need to break it down into components and reward yourself for finishing them, even if it's just with some console i/o that shows that it's working.

0

I was reading your question and thinking things along the line of the other posters: you're not suited to this job; give yourself a time limit; do something else for a moment. After some reflection, I'm not sure any of the answers are really that helpful

The trouble with mental issues like this is that they're not easy to solve, they're part of you, and obviously you care (too much perhaps) about your job, don't have the confidence to agree with yourself, are too inexperienced to consider you're first choice was right all along, or stress too much over getting it perfectly right. Why else would you worry over such trivialities?!

Now I have similar problems, but not with code so much.. usually its what to have for dinner.. pizza or curry.. hmm... pizza but then curry is nice, but do I feel like a curry, pizza is cheaper, but then you get more curry, but... and so on. :)

So I thought - why don't I have similar problems with coding, and I think its simply because I have a set of patterns that I use regularly. If I need a function definition, its easy.. it'll be in the same vein as every other function definition I've ever coded up. If I need a control flow, first I decide whether I need a for loop or a while loop and then create the same old code that I used last time I needed one of these things. The same goes for everything, do I want a queue? Sure - lets go cut and paste my 'standard' queue code (filched from the last project I worked on, or any one I can remember using one of these things). End result... I only fret over new stuff, and to be honest, that's a pleasure.

So, my advice is to start building a library of code snippets - I used to email them to myself and put them in a folder but whatever you work with is best - and then you will begin to know what to do every time. You'll always go to the old code you've written and get the problem out of the way, ready for the next problem. You'll find you become a much faster developer (seriously, this is the only way to gain programmer productivity) and hopefully will find time for the fun bits, not the dreary day-to-day stuff that you've already solved many times over.

Of course, the latter part of all that is important too - the more work you have, the less luxury you have to spend time thinking.

3
  • snippet programming is the worst kind of bad practice Commented Jun 10, 2011 at 23:28
  • @Neil: Using other people's snippets as snippet programming, and not knowing what they do, is bad practice. Using your own code snippets is generally good, since it's quite likely you understand what you wrote. If not, then there's probably no hope for you.
    – Jordan
    Commented Jun 11, 2011 at 3:48
  • @Neil, you're in a particularly bad mood today! Most senior coders have a vast library of snippets in their heads anyway, you just don't notice yourself using them. For a junior, writing them down helps them build this up.
    – gbjbaanb
    Commented Jun 11, 2011 at 13:38
0

Here's a strategy that combines the suggestions by Rein Henrichs (start simple, refactor) and ammoQ (timeboxing):

  1. Give yourself a pretty strict time limit for a first solution that just works. E.g. 30 seconds for a variable name. You could first come up with something like x, then refine it to string, then name until the time is up.
  2. Then proceed to other tasks for some specified time, e.g. 10 minutes.
  3. Only then allow yourself another time box for further improving your decision, e.g. to userHandle

Possible benefits of this approach:

  • the knowledge of coming back to this later may ease the letting go of the problem for now
  • while continuing other tasks, you may just come up with a good satisfying solution without time-consuming rummaging
  • having let go after step 1 and being in the flow of step 2, it may come easy to keep step 3 really swift, as you want to continue with step 2, and thus happily just pick one decent solution and accept it
2
  • This answer seems more specific and complete than your previous one, but they both seem to cover the same ground. Please merge them into one or pick which you'd like to keep.
    – Adam Lear
    Commented Jun 11, 2011 at 3:00
  • @Anna I made two separate posts, because I found they contain different concept ideas that should be voted upon independently: This one: letting go by postponing final decision. The previous one: gut feeling. Indeed both techniques go well together, but each also works without the other. Commented Jun 12, 2011 at 15:34
0

When I've done the research and am left with no clear best choice, I give myself a time limit (usually 5 minutes) to pick one, then just move forward with it. Even when you run into obstacles, at this point, there's not guarantee, you wouldn't have hit an equal obstacle by making a different decision. I can't think of a time I've regretted my decision.

0

Usually the reason you cannot decide is the difference is insignificant, or you do not have enough information.

In case a) Set a time limit to come up with reasonable options to consider. Don't decide which one yet. At the end of the time, choose one (at random if no clear prefernce ) of the identified options, and another time limit. If no clear decision is made at the end of the time, the already choosen one it is. Start codeing, and refactor if you have clearly got it wrong. If the boss asks why, say "I flipped a coin, you got a better way?"

In case b) - you need more information, and sitting around on your big fat A.... all day is not going to provide it. Get out of design mode and go into information gathering mode. Prototypes, ask questions, read tecnical magazines. WHatever you do, don't sleep on it for too long.

0

To overcome your reluctance to decide, apply timeboxing: set an alarm clock to go off in a few minutes; torment your mind till then, but when the alarm goes off, choose the best option you have found till then.

2
  • 5
    And then he can spend hours tormenting himself about exactly how long the alarm clock should be set for! :)
    – Jordan
    Commented Jun 11, 2011 at 3:41
  • 1
    Jordan: There are several possible solutions for that problem too. Unfortunately, I can't decide which one to propose.
    – user281377
    Commented Jun 11, 2011 at 7:00
0

Often, the best solution is to try explaining your decision to a colleague. However, since you don't want to do this very often, the next best thing is to think on paper - either with a paper/pen, or an empty notepad window.

Start by writing absolutely anything - just to get into the rhythm of writing. In a notepad window you may just type "I am thinking on paper" and then just carry on with a stream of consciousness. After a few seconds you'll be in the rhythm of writing, so press enter a few times, and start explaining your dilemma.

State the problem, then state the possible solutions, what's good about each one, etc.

Though it doesn't always work, the process of getting thoughts out of your head (RAM) and onto external media (the notepad document) gives you more freedom to make new connections, and view the decision from different perspectives.

-7

I have never understood this. When I was an instructor, I would say something like:

"OK, create an integer variable and assign the return value of strlen() to it."

Not too complicated, you might think, and 95% of the people wrote something like:

int x;   // or y, or len, or whatever
x = strlen( s );

But there would occasionally be one who sat like a rabbit paralysed in the headlights. I would sympathetically ask what the problem was, and they would say "I don't know what to call it!".

These are the people who should look for another career. As maybe should you.

11
  • 2
    @Anne I'm not making assumptions - you yourself said you found it hard to think up names for things - "Very frequently, I am stuck when choosing the best design decision. Even for small details, such as ... variable names" Commented Jun 10, 2011 at 20:03
  • 3
    And why should I look for another career because I have difficulty naming some things? Not every concept has an clean, short mapping to natural language. Commented Jun 10, 2011 at 20:10
  • 2
    @Anne The thrust of your original question seems to me to be that you are having problems doing what comes naturally to good programmers. There is no shame in this - most people (even most programmers!) are awful at doing these things. However, assuming that like me you can only be happy doing something you are really good at, I suggested that programming may not be what you are cut out for. I spent the first 10 years of my adult life as a microbiologist. I wasn't very good at it, and was much happier when I changed to being a programmer. Commented Jun 10, 2011 at 20:17
  • 3
    A friendly reminder to all: if you disagree with the answer, feel free to use downvotes to express that. Personal attacks from either side will be removed.
    – Adam Lear
    Commented Jun 10, 2011 at 20:35
  • 3
    Ultimately, I feel that the answer comes off rather harshly, but the comments make me feel like it's not that harsh. Perhaps you should edit that in.
    – DeadMG
    Commented Jun 10, 2011 at 20:53

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