DEV Community

Cover image for The Power of Variable Names
Ahmad Adillaumam
Ahmad Adillaumam

Posted on • Edited on

The Power of Variable Names

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
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

or in a functional way:

function getFlaggedCells(gameBoard) {
    return gameBoard.filter(cell => cell[STATUS_VALUE] === FLAGGED)
}
Enter fullscreen mode Exit fullscreen mode

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];
    }
}
Enter fullscreen mode Exit fullscreen mode

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];
    }
}
Enter fullscreen mode Exit fullscreen mode

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";
Enter fullscreen mode Exit fullscreen mode

to

let generationTimestamp;
let modificationTimestamp;
let recordId = "102";
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

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++;
}
Enter fullscreen mode Exit fullscreen mode

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;
    }
}
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

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
});
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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 and totalPoints.
  • 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.

Top comments (8)

Collapse
 
joolsmcfly profile image
Julien Dephix

Despite typos here and there this is a nice article.

Good variable naming is hard but important and when done correctly there is no need for comments.

Function/method names are equally important.
For example when you do this:

// Compute roots of a quadratic equation.
// This assumes that (b^2-4*a*c) is positive.
let temp = Math.sqrt(b^2 - 4*a*c);
root[0] = (-b + temp) / (2 * a);
root[1] = (-b - temp) / (2 * a);
Enter fullscreen mode Exit fullscreen mode

You can get create a function called getQuadraticRoot and get rid of the first comment because we now know what the function does.
Same goes with the second one by adding an if:

function getQuadraticRoot(a, b) {
    const discriminantSquare = b^2 - 4*a*c;
    if (discriminantSquare <= 0) {
        return null; // or whatever makes sense, I’m no quadratic root expert!
    }

    const discriminant = Math.sqrt(discriminantSquare);
    root[0] = (-b + discriminant) / (2 * a);
    root[1] = (-b - discriminant) / (2 * a);

    return root;
Enter fullscreen mode Exit fullscreen mode

We could then argue about discriminant which could well be called d as it does not really help understand the code: it’s an official formula. E=mc2 won’t be easier to grasp with good variable names. ;)

One more thing. You mention convention but you list teamPointsMax, maxPoints as just right. Convention could be to prefix with max so choices should be maxTeamPoints and maxPoints.

Lastly, you do not need let when filling arrays in a loop.

Again, nice article!

Collapse
 
adillaumam profile image
Ahmad Adillaumam • Edited

Wow, thanks for the advice and additional knowledge. I need to learn more. After I reread it, I realized I was careless with lots of typos and wrong implementation. Thank you for being reminded. I have very little experience so I am very grateful to be able to listen to experienced people. Thank you so much for taking the time 🙏

Collapse
 
joolsmcfly profile image
Julien Dephix

Glad I can be of any help.

Good variable names is one thing but it's just one step.
If I take your example:

function getFlaggedCells() {
    let flaggedCells = [];
    for (let cell in gameBoard) {
        if (cell[STATUS_VALUE] == FLAGGED)
            flaggedCells.add(cell);
    }
    return flaggedCells;
}
Enter fullscreen mode Exit fullscreen mode

It's more readable but

  1. it's not a pure function since gameBoard is defined outside of the function.
  2. it can be refactored in a more functional way
function getFlaggedCells(gameBoard) {
    return gameBoard.filter(cell => cell[STATUS_VALUE] === FLAGGED)
}
Enter fullscreen mode Exit fullscreen mode

I find it more readable.

Thread Thread
 
adillaumam profile image
Ahmad Adillaumam

Again, I really learned a lot from you, but here I can only say thank you very much to you and thank you for creating this discussion.

Thread Thread
 
joolsmcfly profile image
Julien Dephix

ha no problems. Keep on writing, it opens up discussions. 👌

Collapse
 
moopet profile image
Ben Sinclair

I agree with most of the points here, but picked up on a couple of points:

I don't think that pointsRecord is a better variable name than maximumNumberOfPointsInModernOlympics because "record" doesn't imply the same thing as "maximum possible", and also because "record" is more usually used to convey the idea of a set of data.

Your last example says that you don't need to use "m_" as a member variable prefix anymore, but you immediately follow that with a list of "Standarized Prefixes" including "m_". I think that either you use a language where the convention includes metadata about the variable or you don't, and you go with what the rest of the world does.

Collapse
 
adillaumam profile image
Ahmad Adillaumam

First, thanks for the comment. I can agree with your first argument. pointsRecord does not fully represent maximumNumberOfPointsInModernOlympics. I will learn more about it. Regarding the m_ prefix, it is not recommended to use prefixes but in certain situations such as in the organization, prefixes may be needed and used with name conventions. I included an explanation of prefixes in the name convention section. I just realized that I'm converting C++ syntax to Javascript carelessly. At first, I meant it for intermezzo, but it seems misguided and misunderstood. Maybe I need to delete it or add a note. Thanks again for the comment, I appreciate it, and it helped me :)

Collapse
 
alimertcakar profile image
Ali Mert Çakar

God I hate nested loops with variables named i,j,k. It's ok for simple stuff but 20 lines of i,j,k mistery is a rejected pr