Great question. Ask it to n programmers and get n^2 responses. This could easily be the subject for another post or even a book. Just off the top of my head in no particular order:
- understands the problem at hand before writing any code
- uses the right tool for the right job
- follows accepted standards and protocols without sacrificing creativity
- names variables & functions what they actually are for the next programmer
- anticipates what could go wrong before relying on a debugger or testing
- understands the underlying architecture and how to best utilitze it
- never writes the same code twice
- never writes in 150 lines that which could be written in 100 lines
- Poor code: uncommented. Mediocre: commented. Good: doesn't need comments.
- understands the entire code life cycle & writes it to last
- has pity on the poor soul who has to maintain it & leaves a clue or 2
- writes flexibly enough to be easily changed before the project is done
I could go on and on, but you get the idea. In general...
A good programmer writes it right, once, in a week.
A mediocre programmer writes it OK, in 2 months, and then futzes with it forever.
I agree with a vast majority of this, except for the qualification of time.
There are many brands of mediocre programmer, some of which would claim a finished product well before the good programmer. But, the code will prove a nigh-unmaintainable disaster that will required all sorts of time later when a new feature is requested or bugs start creeping out.
There are times when a good programmer will take considerably longer than a bad programmer, and might spend time futzing around with different implementations, moving code around, creating various data structures, etc.
Depending on the task, I would argue that can be a good thing. The good programmer is attempting to understand and present a clear conceptual model of the problem and solution in his code; the mediocre programmer might just create a litany of special cases for the cases specified right now just so they can get that particular program behind them.
Although the mediocre programmer might produce code faster, I would argue the good programmer is still 10x more productive, because he has done that much more thinking than the mediocre programmer. Perhaps when you refer to futzing, you mean changing the code just for the sake of another commit to show management, where nothing is learned and nothing is improved.
Also, a good programmer might come back two months from now, with the knowledge he gained from some other project, and make a change to the program that tangibly improves it for the better. The mediocre programmer will have put all that behind them; it is not on their list of projects and requirements, therefore they won't bother, nor will they bother even mention it to anyone.
But, I suspect this sort of comparison of timespans varies with size, and with the difficulty of the problem space.
There's a rather simple metric actually: A good programmers stuff works.
You don't have to go back and fix it, you don't have to rewrite large parts of it to extend it.
One day I want to write a VCS history analyzer to quantify these things. Svn blame ($yourtool annotate) works to an extend, but there's a lot of untapped potential in that data.
I get the idea. However, I would be severely challenged to actually measure any of that. To me that means that "only a good programmer knows another good programmer", which is a hard situation to start from when you are trying to reward good programmers.
A good programmer abstracts and generalizes as much as reasonably necessary and no further. A mediocre programmer will over-abstract the system for pointless 'extensibility' that will never be used. A bad programmer just outright doesn't do anything.
A mediocre programmer always codes with the "kitchen sink" mentality, targeting specifications that do not exist, but in their own minds do.