Art of Readable Code
Write Easy to Read Code
Use specific words—for example, instead of
Get, words like
Downloadmight be better, depending on the context.
Avoid generic names like
retval, unless there’s a specific reason to use them.
Use concrete names that describe things in more detail—the name
ServerCanStart()is vague compared to
Attach important details to variable names—for example, append
_msto a variable whose value is in milliseconds or prepend
raw_to an unprocessed variable that needs escaping.
Use longer names for larger scopes—don’t use cryptic one- or two-letter names for variables that span multiple screens; shorter names are better for variables that span only a few lines.
Use capitalization, underscores, and so on in a meaningful way - for example, you can append “_” to class members to distinguish them from local variables.
Before you decide on a name, play devil’s advocate and imagine how your name might be misunderstood. The best names are resistant to misinterpretation.
- when defining an upper or lower limit for a value using
- For inclusive ranges,
- For inclusive/exclusive ranges,
endare best because they’re the most idiomatic.
- When naming a boolean, use words like
hasto make it clear that it’s a boolean.
- Avoid negated terms (e.g.,
- Beware of users’ expectations about certain words. For example, users may expect
size()to be lightweight methods.
"Code should be written to minimize the time it would take for someone else to understand it."
Consistent style is more important than the “right” style
- Pick a Meaningful Order, and Use It Consistently
- Match the order of the variables to the order of the input fields on the corresponding HTML form.
- Order them from “most important” to “least important.”
- Order them alphabetically.
- Whatever the order, you should use the same order throughout your code.
Everyone prefers to read code that’s aesthetically pleasing. By “formatting” your code in a consistent, meaningful way, you make it easier and faster to read.
- If multiple blocks of code are doing similar things, try to give them the same silhouette.
- Aligning parts of the code into “columns” can make code easy to skim through
- If code mentions A, B, and C in one place, don’t say B, C, and A in another. Pick a meaningful order and stick with it.
Use empty lines to break apart large blocks into logical “paragraphs.”
What not to comment:
- Facts that can be quickly derived from the code itself.
- “Crutch comments” that make up for bad code (such as a bad function name)—fix the code instead.
Thoughts you should be recording include:
- Insights about why code is one way and not another (“director commentary”).
- Flaws in your code, by using markers like TODO: or XXX:.
- The “story” for how a constant got its value.
Put yourself in the reader’s shoes:
- Anticipate which parts of your code will make readers say “Huh?” and comment those.
- Document any surprising behavior an average reader wouldn’t expect.
- Use “big picture” comments at the file/class level to explain how all the pieces fit together.
- Summarize blocks of code with comments so that the reader doesn’t get lost in the details.
You may not have given much thought about this before, but in some cases there are good reasons to prefer one order over the other:
- Prefer dealing with the positive case first instead of the negative—e.g.,
if (debug)instead of
- Prefer dealing with the simpler case first to get it out of the way. This approach might also allow both the
elseto be visible on the screen at the same time, which is nice.
- Prefer dealing with the more interesting or conspicuous case first.
Using De Morgan’s Laws
1) not (a or b or c) ⇔ (not a) and (not b) and (not c) 2) not (a and b and c) ⇔ (not a) or (not b) or (not c)
You can sometimes use these laws to make a boolean expression more readable. For instance, if your code is:
if (!(file_exists && !is_protected)) Error("Sorry, could not read file.");
It can be rewritten to:
if (!file_exists || is_protected) Error("Sorry, could not read file.");
Separate the generic code from the project-specific code
Most code is generic, use a library or framework to solve general problems. Keep a small core of what makes your program unique.
Martin Fowler’s Refactoring: Improving the Design of Existing Code (Fowler et al., Addison-Wesley Professional, 1999) describes the “Extract Method” of refactoring and catalogs many other ways to refactor your code.
Kent Beck’s Smalltalk Best Practice Patterns (Prentice Hall, 1996) describes the “Composed Method Pattern,” which lists a number of principles for breaking down your code into lots of little functions. In particular, one of the principles is “Keep all of the operations in a single method at the same level of abstraction.”
do only one task at a time
If you have code that’s difficult to read, try to list all of the tasks it’s doing. Some of these tasks might easily become separate functions (or classes). Others might just become logical “paragraphs” within a single function. The exact details of how you separate these tasks isn’t as important as the fact that they’re separated. The hard part is accurately describing all the little things your program is doing.
You can avoid writing new lines of code by:
- Eliminating nonessential features from your product and not overengineering
- Rethinking requirements to solve the easiest version of the problem that still gets the job done
- Staying familiar with standard libraries by periodically reading through their entire APIs
Test-driven development (TDD) is a programming style where you write the tests before you write the real code. TDD proponents believe this process profoundly improves the quality of the nontest code, much more so than if you write the tests after writing the code.
This is a hotly debated topic that we won’t get into. At the very least, we’ve found that just keeping testing in mind while writing code helps make the code better.
But regardless of whether you employ TDD, the end result is that you have code that tests other code. The goal of this chapter is to help you make your tests easier to read and write.
In test code, readability is still very important. If your tests are very readable, they will in turn be very writable, so people will add more of them. Also, if you design your real code to be easy to test, your code will have a better design overall.
- The top level of each test should be as concise as possible; ideally, each test input/output can be described in one line of code.
- If your test fails, it should emit an error message that makes the bug easy to track down and fix.
- Use the simplest test inputs that completely exercise your code.
- Give your test functions a fully descriptive name so it’s clear what each is testing. Instead of
Test1(), use a name like
And above all, make it easy to modify and add new tests.
Effective Java, 2nd edition, by Joshua Bloch (Prentice Hall, 2008)
Although it’s about Java, many of the principles apply to all languages. Highly recommended.
- Design Patterns: Elements of Reusable Object-Oriented Software, by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides (Addison-Wesley Professional, 1994)
The original book on a common language of “patterns” for software engineers to talk about object-oriented programming. As a catalog of common, useful patterns, it helps programmers avoid the pitfalls that often happen when people try to solve a tricky problem on their own for the first time.
- Programming Pearls, 2nd edition, by Jon Bentley (Addison-Wesley Professional, 1999)
Great insights on solving real-world problems in each chapter.
- High Performance Web Sites, by Steve Souders (O’Reilly, 2007)
Describes a number of ways to optimize a website without writing much code (in keeping with Chapter 13, Writing Less Code).
- Joel on Software: And on Diverse and …, by Joel Spolsky
Some of the best articles from http://www.joelonsoftware.com/. Spolsky writes about many aspects of software engineering and has an insightful take on many related topics. Be sure to read “Things You Should Never Do, Part I,” and “The Joel Test: 12 Steps to Better Code.”