It's hard to over-emphasize the importance names bring to the maintainability of code. Unfortunately, there is no formula for generating names, just some good heuristics, and some major "don't"'s.

Bad names reduce code maintainability. Names are bad when they are:

Good names are:

Function Names

A function name should

Avoid names that are:

Common Bad Function Prefixes and Suffixes

Avoid the prefix check- as in check-date. Other than saying that something is being checked, this is useless. Is this a predicate? Does it return true for good data? Does it print a warning? Does it throw an error? Say what you mean, e.g., date-legal-p, or report-bad-date.

Avoid the prefix my- as in my-length. That says nothing about what makes your length different from the standard one.

Avoid the suffix -helper as in read-date-helper. If there's a subtask in need of a function, there's a name for that subtask. Sometimes, helpers are created just to get an additional parameter for recursion. Use optional or keyword parameters instead.

For the same reason, avoid numeric suffixes, as in read-date-1 and read-date-2. A numeric suffix communicates nothing. (Note: macroexpand-1 is an exception; the suffix means something, namely "expand once.")

One common reason for difficulty in finding a short accurate name for a function is because the function violates the Cardinal Rule of Functions.

A bit tricky to name are helper functions, e.g., these two common recursive definitions:

(defun fact (n) (fact2 n 1))

(defun fact2 (n r)
  (if (= n 1) r (fact2 (1- n) (* n r))))

(defun my-reverse (l) (my-reverse-helper l nil))

(defun my-reverse-helper (l r)
  (if (null l) r (my-reverse-helper (cdr l) (cons (car l) r))))

The code is fine but the names of the helper functions are bad. If all else fails, use a suffix that at least indicates that this is the function that does the looping, e.g., fact-loop. But often the function can be distinguished by how the parameters differ, e.g., a cube-root function might handle a negative number by calling a helper to get the cube root of the absolute value. In that case, call the helper cube-root-positive.

In the case of my-reverse the helper function actually does a different task, even if it's not used that way. The helper returns a list with the reversed elements of l followed by the non-reversed elements of r. This function actually exists in Lisp and is called revappend for "reverse append."

Variable Names

Most of the rules that apply to function names apply to variable names, as well, except that variables hold objects, not actions, so verb-object and qualified-verb are inappropriate name forms.

In addition, when defining functions that are generic and reusable for a wide variety of tasks, such as a "reverse sequence" function or a "find anywhere" function, there are a number of common conventional short variables names that can and should be used:

Thus, a function that adds a number to every element in a list of numbers could clearly be defined using:

(defun add-number (n l)
  (mapcar #'(lambda (i) (+ i n)) l))

The n and i suggest numbers and the l suggests list. There's nothing wrong with

(defun add-number (num num-list)
  (mapcar #'(lambda (num-item) (+ num-item num)) num-list))

but it's more verbose without being any clearer. On the other hand,

(defun add-number (x y)
  (mapcar #'(lambda (z) (+ x z)) y))

is definitely bad. The variables are too general and easily confused with each other.

For a list of many ways to not name things, check out the naming section of Roedy Green's excellent essay How to Write Unmaintainable Code.

Faculty: Chris Riesbeck
Time: Monday, Wednesday, Friday: 1pm - 2pm
Location:Annenberg G15


Important Links