Clean Code: Chapter 2, “Meaningful Names”

Here are my notes and favourite quotes from chapter 2, “Meaningful Names”, of one of my all-time favourite books: Clean Code: A Handbook of Agile Software Craftsmanship, by Robert C. Martin.

Chapter 2 lays out a set of eminently sensible and simple rules, backed up by rationale, for creating good names with the aim of being more precise which, according to Uncle Bob, is the point of all naming. So do buy and read the book to get this valuable detail.
To set the scene for the rules, I first present a few quotes from near the end of the chapter.

The hardest thing about choosing good names is that it requires good descriptive skills and a shared cultural background. This is a teaching issue rather than a technical, business, or management issue. As a result, many people in this field do not do it very well.

People are also afraid of renaming things for fear that some other developers will object. … You will probably end up surprising someone when you rename, just like you might with any other code improvement. Don’t let it stop you in your tracks.

Follow some of these rules and see whether you don’t improve the readability of your code. If you are maintaining someone else’s code, use refactoring tools to help resolve these problems. It will pay off in the short term and continue to pay in the long run.

Rule: Use Intention-Revealing Names

  • Choosing good names takes time but saves more than it takes.
  • Take care with your names and change them when you find better ones.
  • The name of a variable, function or class should answer the big questions such as why it exists, what it does, how it is used.
  • If a name requires a comment, then the name does not reveal its intent. For example, these names specify what is being measured and the unit of that measurement:
int elapsedTimeInDays;
int daysSinceCreation;
int daysSinceModification;
int fileAgeInDays;
  • Give names to concepts, from the context, to make the purpose of the code more explicit. For example, this function from a “mine sweeper” style game:
public List getFlaggedCells() {
	List flaggedCells = new ArrayList();
	for (Cell cell : gameBoard){
		if (cell.isFlagged())
			flaggedCells.add(cell);
	}
	return flaggedCells;
}

Rule: Avoid Disinformation

  • You must avoid leaving false clues that obscure the meaning of code. For example using words whose entrenched meaning vary from our intended meaning, such as using hp for the concept of a hypotenuse, because “hp” is a well-entrenched name (of a Unix platform).
  • As another example, do not use accountList unless it is actually a Java List. Use something else instead, such as accountGroup.
  • Avoid using names that vary only in small ways.
  • Spelling similar concepts in similar ways is good – it is informative. Using inconsistent spelling, however, is disinformation.
  • It is very helpful if names for very similar things sort together alphabetically, and if the differences are very obvious.

Rule: Make meaningful Distinctions

  • Distinguish names in such a way that the reader knows what the differences offer. For example, the two classes ProductInfo and ProductData have different names but the names don’t mean anything different, because here Info and Data are indistinct noise words.

Rule: Use Pronounceable Names

  • Our minds have evolved to deal with spoken language, so take advantage of that when creating names.
  • Also, if you can’t pronounce it, you can’t discuss it without sounding like an idiot.
  • As an example, note the benefits of using the second version of this variable instead of the first version:
Private Date genymdhms;
Private Date generationTimestamp;

Rule: Use Searchable Names

  • Names should be easy to locate across a body of text.
  • The length of a name should correspond to the size of its scope.
  • If a variable or constant might be seen or used in multiple places in a body of code, it is imperative to give it a search-friendly name.
  • Single-letter names should ONLY be used as local variables inside short methods.

Rule: Avoid Encodings

  • Encoding type or scope information into names simply adds to the burden of deciphering. They are a mental burden, seldom pronounceable and easy to mistype.
  • Hungarian Notation (HN) adds nothing to Java, as the objects are strongly typed and IDEs detect type errors long before compilation. A variable that has its type changed, but accidentally not had its HN name changed can be misleading: PhoneNumber phoneString;
  • Member prefixes are not needed any more. Your IDE should distinguish member variables by their colour. Plus, your classes and functions should be small enough so that you do not need them.
  • Sometimes there is a special case for encodings. For example, creating an interface and an implementation of that interface for, say, an implementation of an ABSTRACT FACTORY.  If you must encode the interface and implementation names, then leave the interface name without the encoding and add a suffix to the implementation class name, for example: ShapeFactory (the interface name) and ShapeFactoryImpl (the implementation class name). That’s because you don’t want your users to know that you are handing them an interface; you just want them to know that it’s a ShapeFactory.

Rule: Avoid Mental Mapping

  • Readers should not need to mentally translate your names into other names they already know/are familiar with. This problem generally arises from a choice to use NEITHER problem-domain terms nor solution-domain terms (see more, below, on problem-domain and solution-domain).
  • Single-letter variable names are really only okay for use as loop counters if their scope is very small and no other names can conflict with them; plus they are traditional.
  • In general programmers are pretty smart people. Smart people sometimes like to show off their smarts by demonstrating their mental juggling abilities. However:

One difference between a smart programmer and a professional programmer is that the professional understands that clarity is king. Professionals use their powers for good and write code that others can understand.

Rule: Class Names

  • Classes and objects should have noun or noun-phrase names, like Customer, WikiPage, Account and AddressParser.
  • But avoid names like Manager, Processor, Data or Info in the name of a class.
  • A class name should not be a verb.

Rule: Method Names

  • Methods should have verb or verb-phrase names, like deletePage or save.
  • Accessors and mutators, and their predicates, should be named according to JavaBean standards.

NOTE: When constructors are overloaded, use static FACTORY METHODs with names that describe the arguments. For example:

Complex fulcrumPoint = Complex.FromRealNumber(23.0);

is generally better than

Complex fulcrumPoint = new Complex(23.0);

Consider enforcing their use by making the corresponding constructors private.

Rule: Don’t Be Cute

  • Don’t be too clever or humourous with your names. Don’t use a function name like holyHandGrenade, when you mean deleItems.

Rule: Pick One Word per Concept

  • Pick and use one word for abstract concept and stick with it.
  • A consistent lexicon is a great boon to the programmers who use your code.
  • Example: What’s the difference between fetch, retrieve and get?
  • Example: What’s the difference between a manager and a controller and a driver?

Rule: Don’t Pun

  • Don’t deliberately or inadvertently re-use the same term where its semantic meaning in the code is different; for example using the term add in several classes, for “consistency”, when you are in fact not using it in the same sense.

Rule: Use Solution Domain Names

  • The people who read you code are programmers, so go ahead and use solution domain terms, such as AccountVisitor, where Visitor means the VISITOR pattern, or JobQueue.

Rule: Use Problem Domain Names

  • When there is no programmer-eese for what you are doing, use the name from the problem domain. However:

The code that has more to do problem domain concepts should have names drawn from the problem domain.

Rule: Add meaningful Context

  • Most names are not meaningful in and of themselves. So:

You need to place names in a context for your reader  by enclosing them in well-named classes, functions or namespaces.

  • Look at the difference between these two examples of code, the first which has an unclear context and the second which does.
	private void printGuessStatistics(char candidate, int count) {
		String number;
		String verb;
		String pluralModifier;
		if (count == 0) {
			number = "no";
			verb = "are";
			pluralModifier = "s";
		} else if (count == 1) {
			number = "1";
			verb = "is";
			pluralModifier = "";
		} else {
			number = Integer.toString(count);
			verb = "are";
			pluralModifier = "s";
		}
		String guessMessage = String.format("There %s %s %s%s", verb,
				 number, candidate, pluralModifier);
		print(guessMessage);
	}
public class GuessStatisticsMessage {
	private String number;
	private String verb;
	private String pluralModifier;

	public String make(char candidate, int count) {
		createPluralDependentMessageParts(count);
		return String.format("There %s %s %s%s", verb, 
				number, candidate, pluralModifier);
	}

	private void createPluralDependentMessageParts(int count) {
		if (count == 0) {
			thereAreNoLetters();
		} else if (count == 1) {
			thereIsOneLetter();
		} else {
			thereAreManyLetters(count);
		}
	}

	private void thereAreManyLetters(int count) {
		number = Integer.toString(count);
		verb = "are";
		pluralModifier = "s";
	}

	private void thereIsOneLetter() {
		number = "1";
		verb = "is";
		pluralModifier = "";
	}

	private void thereAreNoLetters() {
		number = "no";
		verb = "are";
		pluralModifier = "s";
	}
}

Rule: Don’t Add Gratuitous Context

  • Shorter names are generally better than longer ones, so long as they are clear.
  • Add no more context to a name than is necessary.
  • Examples: The names accountAddress and customerAddress are fine names for instances of the class Address but could be poor names for classes. Address is a fine name for a class. If you need to differentiate between MAC addresses, port addresses, and Web addresses, you might consider PostalAddress, MAC, and URI.

SEE ALSO: Clean Code: “Introduction”, Clean Code: Chapter 1, “Clean Code”.

Speak Your Mind

*