Meaningful Variable Names
Choosing good names takes time but saves more than it takes.
Intention-Revealing Names
The name should answer all big questions. It should tell you why it exists, what it does, and how it is used. If the name requires a comment, the name does not reveal the intent.
let d; // elapsed time in days
We should choose the name that specifies what is being measured and the unit of that measurement:
let elapsedTimeInDays;
let daysSinceCreation;
let daysSinceModification;
let fileAgeInDays;
Example of code that is hard to understand because of using bad names:
function getThem() {
let list1 = [];
for (let x in theList)
if (x[0] == 4) list1.add(x);
return list1;
}
The problem isn’t the simplicity of the code but the implicity of the code. The code doesn’t tell what kinds of things are in theList
and what is the value of 4
. Just by giving concepts names, we can improve the code considerably:
function getFlaggedCells() {
let flaggedCells = [];
for (let cell in gameBoard) {
if (cell[STATUS_VALUE] == FLAGGED)
flaggedCells.add(cell);
}
return flaggedCells;
}
or in a functional way:
function getFlaggedCells(gameBoard) {
return gameBoard.filter(cell => cell[STATUS_VALUE] === FLAGGED)
}
Example of Good and Bad Variable Names
Purpose of Variable | Good Names | Bad Names |
---|---|---|
Running total of checks written to date | runningTotal , checkTotal | written , ct , checks , CHKTTL , x , x1 , x2 |
Velocity of a bullet | velocity , trainVelocity , velocityMph | velt , v , tv , train ,x , x1 , x2 |
Current date | currentDate , todaysDate | cd , current , c , x , x1 , x2 , date |
Lines per page | linesPerPage | lpp , lines , l , x , x1 , x2 |
Optimum Name Length
Too long | To short | Just Right |
---|---|---|
numberOfPeopleOnTheUsOlympicTeam | n , np , ntm | numTeamMembers , teamMemberCount |
numberOfSeatsInTheStadium | n , ns , nsisd | numSeatsInStadium , seatCount |
maximumNumberOfPointsInModernOlympics | m , mp , max , points | maxTeamPoints , maxPoints |
Meaningful Distinctions
Because you can’t use the same name to refer to two different things in the same scope, you might be tempted to change one name arbitrarily. It is not sufficient to add number series or noise words (redundant), even though the compiler or interpreter is satisfied.
function copyChars(a1, a2) {
for (let i = 0; i < a1.length; i++) {
a2[i] = a1[i];
}
}
If names must be different, then they should also mean something different. Number-series {a1, a2, ... aN}
is the opposite of intentional naming. Such names are not disinformative–they are noninformative; they provide no clue to the author’s intention. Consider:
function copyChars(source, target) {
for (let i = 0; i < source.length; i++) {
target[i] = source[i];
}
}
Use opposites precisely. Using naming conventions for opposites helps consistency, which helps readability.
Common Opposites in Variable Names
- begin/end
- first/last
- locked/unlocked
- min/max
- next/previous
- old/new
- opened/closed
- visible/invisible
- source/target
- up/down
Pronounceable Names
If you can’t pronounce it, you can’t discuss it without sounding like an idiot. This matters because programming is a social activity. Compare:
// ymdhms (date, year, month, day, hour)
let genymdhms;
let modymdhms;
let pszqint = "102";
to
let generationTimestamp;
let modificationTimestamp;
let recordId = "102";
Searchable Names
Single-letter names and numeric constants have a particular problem in that they are not easy to locate across a body of text. Single-letter names can ONLY be used as local variables inside short methods. The length of the 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. Compare:
for (let j = 0; j < 34; j++) {
s += (t[j] * 4) / 5;
}
to
let realDaysPerIdealDay = 4;
const WORK_DAYS_PER_WEEK = 5;
let sum = 0;
for (let j = 0; j < NUMBER_OF_TASK; j++) {
let realTaskDays = taskEstimate[j] * realDaysPerIdealDay;
let realTaskWeeks = realTaskDays / WORK_DAYS_PER_WEEK;
sum += realTaskWeeks;
}
Naming Specific Types of Data
Naming Loop Indexes
The names i
, j
, and k
are customary, simple loop variable names:
for (let i = firstItem; i < lastItem; i++) {
data[i] = 0;
}
If a variable is to be used outside the loop, it should be given a more meaningful name than i
, j
, k
. For example, if you are reading records from a file and need to remember how many records you’ve read, a more meaningful name like recordCount
would be appropriate:
let recordCount = 0
while (moreScore()) {
score[recordCount] = getNextScore();
recordCount++;
}
One common reason loops grow is that they’re nested. If you have several nested loops, assign longer names to the top variables to improve readability.
for (teamIndex = 0; teamIndex < teamCount; teamIndex++) {
for (eventIndex = 0; eventIndex < eventCount[teamIndex]; eventIndex++) {
score[teamIndex][eventIndex] = 0;
}
}
Carefully chosen names for loop-index variables avoid the common problem of index cross-talk. The simplest way to avoid such problems is simply to think of more descriptive names than i
, j
, k
. The score[teamIndex][eventIndex]
is more informative than score[i][j]
Naming Status Variables Status variables describe the state of your program. It’s better to think of flags as status variables. Flags should be assigned values and their values should be tested with enumerated types, named constants, or global variables that act as named constants. Here are some examples of flags with bad names:
if (flag) ...
if (statusFlag == 0x0F) ...
if (printFlag == 16) ...
if (computeFlag == 0) ...
flag = 0x1;
statusFlag = 0x80;
printFlag = 16
computeFlag = 0;
Here are equivalent code example that are clearer:
if (dataReady) ...
if (charType & PRINTABLE_CHAR) ...
if (reportType == reportTypeEnum.annual) ...
if (recalcNeeded == true) ...
dataReady = true;
charType = CONTROL_CHARACTER;
reportType = reportTypeEnum.annual
recalcNeeded = false;
Naming Temporary Variables
Temporary variables are used to hold intermediate results of calculations, as temporary placeholders, and to hold housekeeping values. They’re usually called temp
, x
, or some other vague and nondescriptive name. In general, temporary variables are a sign that the programmer does not yet fully understand the problem. Moreover, because the variables are officially given temporary
status, programmers tend to treat them more casually than other variables, increasing the chance of errors.
let temp = Math.sqrt(b^2 - 4*a*c);
root[0] = (-b + temp) / (2 * a);
root[1] = (-b - temp) / (2 * a);
The name temp
doesn’t tell you anything about what the variable does. A better approach is shown in this example:
let disciminant = Math.sqrt(b^2 - 4*a*c);
root[0] = (-b + disciminant) / (2 * a);
root[1] = (-b - disciminant) / (2 * a);
Naming Boolean Variables
Useful boolean variable names:
- done
- error
- found
- success
Give boolean variables names that imply true
or false
Names like done
and success
are good boolean names because the state is either true
or false
. Names like status
and sourceFile
, on the other hand, are poor boolean names because they’re not obviously true
or false
.
For better results, replace status
with the name like error
or statusOK
, and replace sourceFile
with sourceFileAvailable
or sourceFileFound
, or whatever the variable represents.
Some programmers like to put Is
in front of their boolean names. Then the variable name becomes question: isDone
? isError
? isFound
? isProcessingComplete
? Answering the question with true
or false
provides the value of the variable.
Use positive boolean variable names
Negative names like notFound
, notDone
, and notSuccessful
are difficult to read when they are negated.
Naming Enumerated Types
const daysEnum = Object.freeze({
monday: 0,
tuesday: 1,
wednesday: 2,
thursday: 3,
friday: 4,
saturday: 5,
sunday: 6
});
Taking this one step further, one could extract the logic into a function with a variable number of arguments and produce a frozen object. There is very little benefit to this technique, so a better alternative would be to create a simple class. After all, enums are more common in object-oriented programming languages, so this sounds like a great fit.
Naming Constants
When naming constants, name the abstract entity constant represents rather than the number the constant refers to. FIVE
is a bad name for constant. FIVE = 6
would be ridiculous. CYCLES_NEEDED
is a good name. By the same token, BAKERS_DOZEN
is also a poor constant name; DONUT_MAX
is a good constant name.
General Issues in Using Variable
Disinformation
Programmers must avoid leaving false clues that obscure the meaning of code. We should avoid words whose entrenched meanings vary from our intended meaning. Abbreviations could be disinformative.
Do not refer to grouping accounts as an accountList
unless it’s a List
. The word list means something specific to programmers. If the container holding the accounts is not a List
, it may lead to false conclusions. So accountGroup
or just plain accounts
would be better.
A truly awful example of disinformative names would be the use of lower-case L
and upper-case O
as variable names, especially in combination. The problem, of course, is that they look almost entirely like constants one and zero, respectively.
let a = l;
if (O == l) a = O1;
else l = 01;
Problem-Orientation
A good name mnemonic name generally speaks to the problem rather than the solution. A good name is the what more than how. In general, if a name refers to some aspect of computing rather than to the problem, it’s a how rather than a what. Avoid such a name in favor of a name that refers to the problem itself.
A record of employee data could be called inputRec
or employeeData
. inputRec
is a computer term that refers to computing ideas–input and record. employeeData
refers to the problem domain rather than the computing universe. Similarly, for a bit field indicating printer status, bitFlag
is a more computerish name than printerReady
. In accounting application, calcVal
is more computerish.
Encodings
We have enough encodings to deal with without adding more to our burden. Encoding type or scope information into names simply adds an extra burden of deciphering. It is an unnecessary mental burden when trying to solve a problem. Encoded names are seldom pronounceable and are easy to miss-type. An encoding system will mislead the reader.
Advice
- Avoid misleading names or abbreviations
- Avoid names with similar meanings
- Avoid variables with different meanings but similar names
- Avoid numerals in names
- Avoid misspelled words in names
- Don’t differentiate variable names solely by capitalization
- Avoid multiple natural languages
- Avoid the names of standard types, variables, and routines
- Don’t use a name that is unrelated to what the variable represents
- Avoid names containing hard-to-read characters
Naming Conventions
Why Have Convention?
- They let you take more for granted. By making one global decision rather than many local ones, you can concentrate on the more important characteristics of code.
- They help you transfer knowledge across projects. Similarities names give you an easier and more confident understanding of what unfamiliar variables are supposed to do.
- They help you learn to code more quickly on a new project.
- They reduce name proliferation. Without naming conventions, you can easily call the same thing by two different names. For example, you might call total points both
pointTotal
andtotalPoints
. - They compensate for language weaknesses. The convention can differentiate between local, class, and global data.
- They emphasize relationships among related items.
When You Should Have a Naming Convention?
- When multiple programmers are working on a project
- When you plan to turn the program over to another programmer for modification and maintenance
- When your programs are reviewed by other programmers in your organization
- When your program is so large that you can’t hold the whole thing in your brain at once and must think about it in pieces
- When your program will be long-lived enough that you might put it aside for a few weeks or months before working on it again
- When you have a lot of unusual terms that are common on a project and want to have standard terms or abbreviations to use in coding
You always benefit from having some kind of naming convention. The considerations above should help you determine the extent of the convention to be on the particular project.
The most important consideration in naming a variable is that the name fully and accurately describes the entity the variable represents.
Good variable names are a key element of program readability.
Bibliography:
- Martin, R. C. (2009). Clean code: a handbook of agile software craftsmanship. Pearson Education.
- McConnell, S. (2004). Code complete. Pearson Education.
Thanks to Julien Dephix, Ben Sinclair, and other advisors who have helped improve this article.