Our fearless leader Steve asked me recently “do 80% of programmers think they’re in the top 20% of good programmers?” I certainly think I’m in the top 20%. Heck, I think I’m in the top 10%. Putting aside my not-inconsiderable ego for a moment, though, it begs the question “what makes a good programmer?”
In this post, I’m going to try to define the qualities that separate the good programmers from the bad. These qualities apply primarily to programmers working in a team with the goal to build quality, maintainable software. If you’re slaving away trying to win the International Obfuscated C Contest, these qualities may not be a useful metric to gauge your ability.
I’ve identified nine qualities that I believe good programmers posses. Many of these qualities support one another, so you’ll find that the whole is greater than the sum of its parts. So, without further ado, a good programmer is….
The holy grail of documentation is “self-documenting code”. Like most holy grails, it’s something to be strived for, even if it’s never achieved. Assuming you and I possess similar fluency in the language, and a similar understanding of the problem domain, it should be clear to me what your code is doing just by reading your code. Where it is impossible or impractical to make the code itself clear, the documentation should provide that clarity. Writing clear code is a natural result of clear thinking: adequately understanding the problem and understanding how best to solve it with the tools available to you. Writing clear code means that your algorithms are logical, the names you chose for things are descriptive, your methods generally fit on one screen, and the interfaces between code structures are well thought-out.
Here I’m talking about your skill in communicating with other humans, not computers. If you’re working on a team, the ability to clearly articulate the problem is vital. Furthermore, it makes you a more effective advocate of your solutions, and a more skillful critic of other people’s solutions. And, perhaps the most important benefit of this quality, the ability to write clear and concise documentation (when I say “documentation”, I’m referring to requirements documents, design documents, code comments, and commit comments).
Fluency is your ability with the languages and technologies you’re working with. I’ve seen too many programmers learn the bare minimum necessary to bang out a solution, and never bother furthering their ability. There’s a tendency among programmers to feel that once you’ve learned one language, you are somehow imbued with fluency in any language. There is a certain amount of truth here, but most languages are extremely deep and complex, and the better you understand them, the more effective you will be. For example, if you’re a C# programmer, and you don’t know how the
using keyword works, and its relationship to
IDisposable, you should probably hit the books. (Think that was easy? How about this one: in C#, is an anonymous method a lexical closure? If not, what does that imply?)
As much as possible, you should be an expert in the problem domain. That is, if you’re trying to solve a problem, do you understand the problem? Both at a high level and a very detailed level? A mistake a lot of programmers make (and probably my biggest weakness) is to just muddle through a problem without trying to understand it fully. Obviously, it’s not always feasible to be an expert in every problem you encounter, but you should strive for as much expertise as possible.
Like defensive driving, defensive program reduces your chances of something bad happening. For every line of code you write, you should be thinking two things: “how can this break?” and “how might I want to change this in the future?” Keeping in mind functionality you may want to add in the future means that you are less likely to paint yourself into a corner. Employing test-driven development is a great aid in defensive programming: not only are you forced to think about how something might break, you now have a test to prove that it doesn’t break.
Don’t repeat yourself. Sometimes I think this principle should be named the more emphatic DO NOT REPEAT YOURSELF, but DNRY isn’t as catchy, I guess. The software engineering “patterns” movement has spawned a lot of cute aphorisms, catch phrases, and acronyms, and many of them are very good and useful, but this gem is important enough to include in this list. It’s always been true; it just hasn’t had a catchy acronym until recently. What this boils down to is having the perspicacity to write code in a truly useful, modular, and re-usable manner. Get your fingers off of Ctrl+C and Ctrl+V and write a method already! The big problem with cut-and-paste coding is that every time you do it, you double the places you have to modify to fix a bug or add a feature in that code. ”Double” implies exponential growth, kids. If you cut-and-paste some code, and then cut-and-paste code that includes that code, now there are four places for your bug to hide. And so on. Most commonly, I see bad programmers cutting-and-pasting code and hiding behind the excuse “but each copy does something slightly different.” That may be true, but that’s what arguments are for: parameterize that code!
Good Under Pressure
No matter how good your organization is at setting schedules, the unexpected will always get you, and there will be crunches. No one likes working nights and weekends, but it happens, and you’ll notice a difference in the way a good programmer handles it. A bad programmer will revert to every bad habit in the book: defensiveness, DRY code, version control hygiene, and documentation are the first casualties. The good programmer, by contrast, stays calm, and is considered in the way he or she cuts corners in order to hit the deadline. In a natural disaster, the people who save lives are the ones who stay calm, and let their training take over. The good programmer is like this in a schedule crisis: they don’t revert to sloppy coding, because they train to write good code. The good programmer doesn’t forget to commit their code in small chunks; he or she knows that this is exactly where good version control hygiene can save your bacon and, if anything, they are more assiduous about committing in small chunks, and making meaningful commit comments. Finally, the good programmer keeps a list of things that will have to be re-visited once the crunch is over, and they have the discipline to go and fill in that missing documentation, or implement more robust error-handling when time permits. The bad programmer simply moves on, thinking “thank God that’s done,” and never re-visits the sloppy code that they wrote in a state of panic.
This is perhaps the most important quality of a good programmer, and also one of the hardest, especially when deadlines loom. It’s easy to fall into the habit of “getting it done” without thinking about the future of your code (especially if you’re under the gun). Refactoring takes discipline. Clearly thinking through a problem takes discipline. Code reviews take discipline. Documentation takes discipline.
In Possession of a Healthy, Balanced Ego
My friend Damion, after reading the first version of this post, said that the only thing he would add to this list is “humility”. I slept on this, and struggled with including it here, and realized that he was right, but something still bothered me about it. After thinking about it, I realized that humility is not always helpful, and pride is not always a bad thing. If you endeavor to meet all of the qualities I have laid out here, you can, and should take pride in your work. There’s nothing wrong with that. However, Damion makes a solid point: humility keeps your ego in check, and allows you to be gracious and open when someone criticizes your work. In a collaborative effort, the ego of individuals should come as secondary to the good of the project as a whole. On the other hand, pride (perhaps a better way of saying this would be “confidence in your work”) is motivating, and promotes a sense of ownership and investment. So, instead of listing “humility” as one of the qualities of a good programmer, I’ve decided to go with “balanced ego”. What I mean by this is that you are free to take pride in, and express confidence about your work, but that you are willing and able to put your ego aside when making team decisions and hearing criticism.