“Any fool can write code that a computer can understand. Good programmers write code that humans can understand.”
— Refactoring: Improving the Design of Existing Code, by Martin Fowler.
Reading of any sort is a difficult and high-effort task. Human beings need years of training to learn the basics of reading, and more years after that to master comprehension of the written word. Once you have learned how to read, it’s easy to take it for granted, but it remains a difficult task, one that requires effort and concentrated attention. Reading for retention and comprehension is especially hard work.
Now, think of what it takes to read code. Not only do you need to understand the programming language, you also need to understand the commonly-used patterns and structures of that language. Every programmer is an author, potentially with his own idioms and expressions and almost certainly with his own style. Programming languages are not as nuanced and interwoven as natural languages, but they still require effort to interpret and understand.
Effort versus reward
Reading code feels unproductive. In reading, you may be gaining knowledge about a program, but you are not creating anything new. At best, you are comprehending the previous work of someone else. To a developer, especially one who thinks he is being paid just to write code, the level of effort involved in understanding the work of another developer seems like a horrific waste of time. The high-effort, low-reward feedback loop is frustrating.
Alternatively, the effort-to-reward feedback loop for writing new code is very short and feels very positive. It’s much less frustrating than trying to understand the work from another developer, because you are the developer. It feels immediately productive, because every line you write is something new you can point to as the result of your efforts. This kind of instant gratification is hard to resist.
Code as communication
A large part of the problem in reading code is that most programs are written in the moment, not thinking ahead, and not thinking of the other developers who will have to read the program. It is natural to think of the program as being for the computer, but this is not entirely the case. As a developer, you have to deal with two readers: the computer, and other developers. Your programs are a medium for communicating, indirectly, with other developers. Code is a conversation between you and the developers who have to work with it.
For other developers, reading your code is hard work. To them, reading your code is a learning exercise. They have to figure out what problem you are trying to solve, what you are doing to solve it, and why you are taking a particular approach. Once you realize that reading code is a learning exercise, you can begin to appreciate that you should write your code as a teaching exercise so they can learn more quickly. This may be more work for you, but it is the high-reward kind of work that developers like.
In short: when writing code, remember the poor bastard who will have to read your program. That poor bastard may be you, six months from now.
Toward better communication
What can we do to make our programs easier to comprehend? There are many volumes on this subject, such as Code Complete. There is little I can add to these technical treasures.
However, in addition to the technicalities of code organization, there are many softer guidelines that make a great difference in comprehensibility. Think of these softer styles as making the difference between reading an Army technical manual and a good tutorial. The technical manual may have perfect grammar and structure, but lacks comprehensibility, whereas the tutorial has good grammar and good style.
Here are three communication measures you can adopt to improve readability and ease-of-understanding in your own work:
Adopt a coding style standard already in use by others.
I have long been a proponent of shared coding standards. In a way, using a shared standard is a variation on Jakob’s Law: “Users spend most of their time on other sites. This means that users prefer your site to work the same way as all the other sites they already know.” The same thing applies to code; if your code is styled and organized in a common fashion, you (and other developers) can read it with much less cognitive load.
I am a fan of the PEAR style guide; I gave up my own style long ago in favor of it. When comparing the PEAR style to your own, beware the narcissism of small differences. For example, where to put braces is not a matter of moral significance; placing them consistently and within reason is the key.
Also note the PEAR readability recommendations, which give hints on good coding style.
A program is a list of instructions, not a series of sentences.
Programming languages are not English prose. Language expressiveness is all well and good, but be sure that it does not get in the way of easy human comprehension of the tasks being performed. In particular, with PHP, having more lines of code is generally easier to understand than combining several operations on a single line. This means trading greater line volume for lower line density; it may use more lines, but lines are free.
Trade cleverness and performance for clarity and straightforwardness.
It’s hard enough for another developer to figure out what you’re doing in simple cases. Don’t make it harder by being clever. The goal of your program is to perform a certain task, not to prove how clever you can be. If you must be clever in code, comment the hell out it so that the reader knows why you are working that way.
Similarly, if there is a highly-performant but difficult-to-understand approach, and a less-performant but reasonable and straightforward approach, err on the side of the easier-to-understand code. Communicating with other developers in this fashion will improve their ability to comprehend your logic and intent.
The art of conversation
Technical mastery of a language does not confer an ability to communicate well using it. Just as with real conversations, good programming style is a matter of art and craft, not science. It is a skill that improves with practice, and there’s always room for improvement.
By looking at your own code as an opportunity to communicate with other developers, I hope that you will begin to see your high-reward writing efforts as a teaching exercise for those who will have to work with it, thereby granting them high rewards for the effort of reading your code.
Improving the quality of your conversations in code will go a long way toward increasing the number of people who can work with your code, and reduce the frustrations of those developers who have to discern your intent. For other developers, reading and comprehending your code is hard work. Always remember that the other developer may be your future self, coming back to maintain your own work. If for no one else, write comprehensible code for you.
I welcome your comments and criticism. We can continue our conversation on my blog.