What is the difference between very good programmers and excellent programmers? I think it’s only one single thing that makes the difference between excellent programmers and the others, and that’s the ability to “tie the knot”. But let me explain first…
What are very good programmers, anyway? The final product does not matter; I think you don’t need to be an excellent programmer to write excellent software—and likewise, there are excellent programmers which don’t (always) write excellent software. The quality of a programmer better is shown in the ways she programs, not what she programs. And with that said, 80% of the programming jobs (just a SWAG) don’t need any kind of very good programmer, one that knows what she does is good enough for your usual web application or payroll system. The other 20%, however, are commonly known as interesting projects, and having really good to excellent programmers helps here.
Apart from learning various programming techniques, languages, libraries and having general experience in programming, the most important thing that changes during the lifetime of a programmer are the means of abstraction she can use.
Most programmers, like it or not, start off with some dialect of Basic. Basically (no pun intended), Basic allows for no means of abstraction, Visual Fred aside. And if it did, the new programmers wouldn’t know how to use it, anyway.
The common procedural languages one often learns next, say C or
Pascal, allow for abstraction from a data point of view, they provide
records and functions and procedures, so you can
abstract how to store the data, and what do to with the data.
After this, most people dabble into object-oriented programming—and if they manage to stay on track (and learn a good OO language), they usually can learn and apply the concepts of OO pretty quickly. Object-orientation allows for further abstraction: due to polymorphism, we can not only abstract the ways data is kept, but also how data is dealt with. A good way to see how far they have progressed is to look at their method definitions, does it more look like imperative or functional code inside?
Given enough time, and some mathematical interest, functional programming is next. (You could do FP before OO, as well—the concepts are orthogonal enough they do not really interfere.) In comparison to OO, encapsulation is not that appraised here, but by means of abstraction, FP allows for things the usual OO developer never would have dreamt of (the more pure and typed the language is, the better this works—no-one cares anymore how pragmatic the language is, at that level!).
Now, say, you’ve become a very good programmer that thinks about continuation monads during breakfast and quickly writes a Prolog implementation in Common Lisp to solve some logical puzzles after lunchtime, what’s missing before you become an excellent programmer?
The thing that’s missing is getting rid of all the abstraction again, to tie the knot, usually by means of a compiler. Computers aren’t made to run maths, they are made to run code. Fortunately, that code even can take maths and produce code, but to make it do that it needs an excellent programmer.
Studying continuations on it’s own is a mathematically interesting thing, but it’s of no use to the computer. When you are able to generate code, however, that rewrites code in continuation passing style in order to use direct jumps and avoid using the stack, so your code runs more efficient and allows for more flexible ways of programming, your CPU will thank you.
“All problems in computer science can be solved by another level of abstraction”, they say, but if you don’t manage to get rid of them when you don’t need them anymore, you don’t need to wonder when your programs are slow, complex, and inefficient.
When you are able to abstract your problem as far as possible, you are a very good programmer; but if you are able to abstract your problem in a way it is most efficient for the machine, you have become an excellent programmer.
NP: Dan Bern—Elliott Smith