1) Good programmers have the ability to step in and step back. They can spend a couple of hours focusing on minutiae and then pull back and look at the whole project and its goals -- and then step back in. It's like being a good host at a party, focusing on one person and making sure he's happy, and then stepping back and taking in the whole room, making sure there's enough beer and cheetos left for everybody. Then back to the one person.
Programming has helped me adjust my focus in other areas of life. In an argument, I am better able to gain some distance and cool off. But I can also zoom way in and point out a specific flaw in my opponent's reasoning. When I direct plays, I can see that if the current scene doesn't speed up, the entire evening will run too long. But I can also finesse the placement of a chair so that an actor can ease into after he crosses the stage. When I draw, I can see how the line I'm finishing affects the entire composition.
2) A refusal to cut corners. On a mundane level, this means naming a variable totalNumberOfSharksInTheTank instead of S. But programming is full of these sorts of decisions on large and small scales. Decisions that involve choosing between something that works and is easy to type and something that works and is more difficult to type -- but that will be easier to understand later.
Pretty much everything that makes your program easier to understand and debug is a pain to set up in the short-term. Long, descriptive variable names, comments, etc. It's so tempting to be penny wise and pound foolish. But the good programmers I know EMBRACE this extra work. They get pleasure out of going the long way around to make things clear. They love the beauty of transparent code.
I struggle to apply this tip to my non-programming life. I'm gradually improving. I try to go the extra mile, do all the dishes, clean the tub thoroughly -- not just good enough so that the grime doesn't show. When I'm directing a Shakespeare play, I look up ALL the words I don't know, and even the words I sort of know. If I only understand a word from its context, I don't really know it. So I look it up. When I teach or give someone directions, I explain everything clearly and in detail. Sometimes I'm tedious. Maybe I go overboard. But I'd rather bore people than confuse them.
3) Good programmers, like good writers, make multiple drafts. They go back over their code many times, optimizing and clarifying. Some people don't like making multiple drafts. If you're going to be a good programmer, you can't be the type of person who likes to go over something once and then be done with it.
Here, I'm a natural. Though it's undiagnosed, I may have some sort of OCD. I tend to go-over everything several times. When I go to bed, I set my alarm clock, check it to make sure I set it accurately, and then -- after I've put my head down -- sit up and check it again. I'm always stunned by the errors people make via carelessness. Friends think I'm careful. I'm not, but I check my work. When I do, I find tons of foolish errors. I EXPECT the errors. I think some people assume they're better first-drafters than they actually are.
4) Good programmers work to allow themselves to selectively forget information. The goal is to make parts of your program become "black boxes." You try to perfect functions, classes and the like so that you don't need to remember how they work any more. They are self-contained tools that you can just use. Programming needn't involve holding a zillion things in your head at once if you work this way.
The flip side of this is my item 2, a refusal to cut corners. Once you have forgotten the guts of function, there will come that inevitable day when you'll need to revisit it. On that day, you'll be ecstatic about the breadcrumbs you left yourself -- the comments, identifier names, and organization -- when you originally built the function.
This is the opposite of multi-tasking. Multi-tasking is a curse. I try to avoid it in all aspects of life ("try" being the operative word). When you multi-task, you have to keep several balls in the air at the same time, and chances are your split focus won't let any of them fly as high as they could if you threw them up one at a time. People mistakenly think that they get more work done when they multi-task. It's a lie. The trick is to finish task A -- really finish it, so that it's wrapped up and put away -- before going on to task B. You will save time by not having to return to task A again.
5) Good programmers learn from other good programmers. People have spend DECADES theorizing and experimenting, and they've learned a lot. There are all sorts of programming structures and practices that have been well worked out: design patterns, data structures, etc. These aren't things you're likely to come up with on you're own. You have to read, study and practice.
I'm saddened by the number of people who don't know how to use reference materials. This is a vital life skill. I rarely know what to do, but I know how to find out what to do. As with item 4 (above), that allows me to free up large parts of my brain. I don't have to remember how to bake sourdough bread. I have a recipe book that I can refer to.
The greatest thinkers and craftsmen know how to rely on others. Shakespeare stole plots; Stephen Sondheim uses a rhyming dictionary.
6) Good programmers (like good people in any field) work to improve themselves. I keep a personal "Syntax Error List." I tend to make the same mistakes over and over. For instance, I tend to write single equals in a conditional statement instead of double equals (accidentally making it an assignment instead of a test of equality). When my program doesn't work, instead of staring at it blankly, I go down my list and check for my common errors.
I've started using the same trick to improve my spelling. I'm an atrocious speller, and though I get by using spellcheckers, I also rely on them, so my spelling doesn't improve. It's embarrassing when I have to fill out a form and can't use MS Word. One day, I realized that spellcheckers could actually help me improve my spelling -- if I thought of them as data-collectors. I started writing down a list of words I continually misspell (I wouldn't know about these words if the spellcheckers didn't catch them) and I've begun memorizing their correct spellings.
7) Good programmers learn to debug. Debugging shouldn't be an afterthought that you do in a haphazard way. It's a specific and necessary skill that must be learned and applied. (Again, don't re-invent the wheel. Learn from people who have gone before!) You need to learn to think the way a good electrician thinks: the light doesn't come on. Is it the bulb, the socket, the switch, the wiring...? You need to test each component part to see where exactly the problem lies. Once again, it's about stepping in and stepping back.
Problem solving is a distinct mode. I must remember to click into it. I don't keep my problem-solving skills "online" all the time, because often they're not needed. When a problem arises, it's easy to forget about them and not use them. If face a problem without my problem-solving skills, I can only panic or throw up my hands. I need to step back (see item 1, above) and switch toolbelts.
Nowadays, if problem solving requires information, the web is key -- but you have to use it aggressively. Google is great, but do you know how to use ALL of it's search engines? Google Images? Google Maps? Google Groups? Google Video? Did you know that you can use Google as a calculator and a measurement converter (try entering "22 miles in furlongs")? What do you do when Google fails? Don't give up on the web yet! Use it to connect you with a person. Find the site of an expert and email him. Most people are surprisingly willing and happy to help. As a final straw, place an ad on Craigslist. Offer fifty bucks to anyone who can solve your problem.
8) Good programmers run tests. Test everything on the computer, not in your head. Unless you've coded the exact same thing 1000 times, don't assume something will work or won't work. Try it and see.
I drive actors crazy by trying everything out in rehearsal. They come to me and say, "Do you think my character is happy or sad in this scene?" I answer, "Let's try in once with you happy, and then go back and do it again with you sad." I refuse to make a decision in my head when it's possible to do it outside of my head. The world in my head is just a map of reality, and it's imperfect. If I assume anything, I might miss something. So I assume as little as possible. Over and over, this method has helped me strike gold and avoid potholes. I'm addicted to it.