So now what? Are we forever doomed to hate what we do? Well, actually there is hope: the key to enjoyable programming is in having a great programming experience. Experience? What does that mean? It means that we feel like we've solved problems, invested in future productivity, and/or made things better in a session of programming, while not stalling our progress towards the development of the software we are programming.
As we can see, this hasn't alot to do with the language we're using. And this brings me to what a great programmer is. You know the old saying that a bad programmer can write bad code in any language? Well, the great programmer is one at the opposite end of that spectrum:
A great programmer produces great code in any language.
Yep, that's right. A great programmer is one who has gotten so good at coding, that they have risen above the mire, the style that their everyday language nudges them towards, and they have found those good architectural and semantic patterns that make for great code, and then they can write great code in any language!
How do you recognize a great programmer?
- They tend to design reusable libraries, routines, and code, in general. Instead of writing 1,000-line algorithms, they develop a 1,200-line reusable, well-designed library, and simply reuse it when they need it again.
- They don't need to rely on comments: they read the code itself.
- They limit the amount of architectural aerobatics! Instead of spending 3 months creating a scripting programming language in the programming language, they spend a week creating an object-oriented system that is not much harder to deal with than a scripting language.
- They limit complexity! Instead of coding a perfect routine that takes 3 hours to write and 2 days to debug, they write a very simple, good-enough routine that takes 5 minutes to write, and doesn't have bugs.
- They seem to have ingrained habits of how to write good code and make good design choices. They've been here before, and they know that design X will easily solve problem Y.
- Their work is excellent in design. They know that abstraction means well-designed, flexible libraries.
- They optimize only 1% of the time, but when they do optimize, those optimizations produce durastic improvement.
- They code defensively. They attempt to ingrain air-tight error prevention into their libraries, so that nobody can use them incorrectly without knowing about it. They seek to catch errors on program start-up where possible. In addition, they exploit the whatever type checker is available to prevent errors at compile-time when possible.
- They test the functionality immediately, to make sure it works. Coding a feature means both writing it, and ensuring that it works correctly.